# Offline Batch Execution Offline batches store a group of CAN, CAN FD, or RS485 commands in the board and execute them in order. The batch can continue running after the computer is disconnected, which is useful for cyclic tests and fixed action sequences. Batch execution is relatively complex. We recommend using the online [SANPO Studio](https://www.sanporobot.com/sanpo-studio) tool to configure offline commands quickly. Batch commands are configured through USB serial ports. After connecting the board, Windows shows two `SANPO Studio Management Port` serial ports, one for each STM32 MCU. STM32 (1) controls CAN-1/2 and RS485-1/2; STM32 (2) controls CAN-3/4 and RS485-3/4. Port numbering is not guaranteed to follow the board silkscreen; initially connect only one device to verify the mapping. ## Basic Rules - Send all commands through a management port and terminate each line with `CRLF`. - Batch IDs are `1` to `99`. Names are 1 to 16 characters and may contain only letters, digits, `_`, and `-`. - Item IDs must start at `1` and increase continuously without gaps or duplicates. - A single payload is limited to 80 bytes. An RS485 item may use at most 68 of those bytes. - The firmware allows more items internally, but we recommend no more than 64 items per batch to simplify maintenance and reduce storage pressure. - `Channel=0` sends to both same-type interfaces managed by the current MCU; `1/3` selects the first interface and `2/4` selects the second interface. ## Create and Run a Batch The following example creates a CAN FD extended-frame task and runs it once: ```text AT+BATBEGIN=1,fd_test AT+BATADD=1,1,5,1,10,000001230A01020304050607081112131415161718 AT+BATCOMMIT=1 AT+BATRUN=1,1,0,1 ``` Each successful command returns: ```text OK ``` Query the status after execution: ```text AT+BATSTAT? ``` Typical response: ```text BATSTAT:run=0,batch_id=1,mode=1,idx=2,count=1,repeat_cfg=1,repeat_done=0,last_err=0,tx_ok=1,tx_fail=0 ``` Check especially that `last_err=0`, `tx_ok` increased, and `tx_fail=0`. ## Item Format ```text AT+BATADD=,,,,, ``` | Field | Description | | --- | --- | | `id` | Batch ID, `1` to `99` | | `idx` | Item ID, continuously increasing from `1` | | `proto` | Bus and frame type; see the table below | | `ch` | Target channel; `0` means both interfaces on the current MCU | | `delay_ms` | Wait after this item succeeds and before the next starts, `0` to `9999 ms` | | `hex_payload` | Hexadecimal data without spaces | The `proto` and payload formats are: | `proto` | Type | `hex_payload` | | ---: | --- | --- | | `1` | Classic CAN standard frame | `CANID(2B) + Len(1B) + Data(0-8B)` | | `2` | Classic CAN extended frame | `CANID(4B) + Len(1B) + Data(0-8B)` | | `3` | RS485 | Raw device command `Data(1-68B)` | | `4` | CAN FD standard frame | `CANID(2B) + length code(1B) + Data(0-64B)` | | `5` | CAN FD extended frame | `CANID(4B) + length code(1B) + Data(0-64B)` | CAN IDs use big-endian byte order. Classic CAN `Len` is the actual byte count. CAN FD uses the following length code: | Code | Bytes | Code | Bytes | | ---: | ---: | ---: | ---: | | `00` | 0 | `08` | 8 | | `01` | 1 | `09` | 12 | | `02` | 2 | `0A` | 16 | | `03` | 3 | `0B` | 20 | | `04` | 4 | `0C` | 24 | | `05` | 5 | `0D` | 32 | | `06` | 6 | `0E` | 48 | | `07` | 7 | `0F` | 64 | ## Run Modes ```text AT+BATRUN=,,, ``` | Field | Description | | --- | --- | | `mode=1` | Run once in order, then stop | | `mode=2` | Run periodically | | `period_ms` | Wait between rounds in periodic mode, `0` to `65535 ms` | | `repeat` | Number of rounds; `0` runs continuously until `AT+BATSTOP` | For example, run one round every 100 ms for 10 rounds: ```text AT+BATRUN=1,2,100,10 ``` Stop the current batch: ```text AT+BATSTOP ``` ## Run Automatically at Power-On After a batch has been tested, configure automatic execution at power-on: ```text AT+BATAUTOSET=,,, ``` Query or clear the setting: ```text AT+BATAUTO? AT+BATAUTOCLR ``` This setting is saved to Flash. When `mode=1`, `period_ms` must be `0`. ## Query and Delete | Command | Purpose | | --- | --- | | `AT+BATLIST?` | List saved batches | | `AT+BATREAD=,` | Read a specified item | | `AT+BATSTAT?` | Read run status and transfer statistics | | `AT+BATDEL=` | Delete a specified batch | | `AT+BATERASE` | Clear all batches | `AT+BATERASE` does not clear device identity or communication parameters, but saved batches cannot be recovered. ## Upload a Long Command in Chunks If a serial tool cannot reliably send a long AT command, upload one payload in chunks: ```text AT+BATADDX=,,,,,,,, AT+BATADDEND=,, ``` - Start the first chunk with `seq=1` and `off=0`. - Increase `seq` continuously. Set `off` to the total number of bytes already uploaded. - After all chunks are complete, calculate CRC16-CCITT over the complete payload with initial value `0x0000`, then send `AT+BATADDEND`. - Complete one item before uploading the next item ID. ## Error Responses Failures return `ERR,`: | Code | Description | Common action | | ---: | --- | --- | | `1` | Invalid parameter format | Check field count, hexadecimal data, and payload layout | | `2` | Current state does not allow the operation | Check `BATBEGIN`, continuous numbering, and completed chunks | | `3` | Parameter out of range | Check batch, channel, delay, and length | | `4` | CRC mismatch | Recalculate CRC16 over the complete payload | | `5` | Insufficient storage | Delete unused batches; use `AT+CFGERASE` when the configuration area is full | | `6` | Batch does not exist | Confirm the ID with `AT+BATLIST?` | | `7` | Transmit queue is busy | Lower the task frequency or increase item intervals | | `8` | Flash read/write failure | Power-cycle and test again; check the hardware if it persists | See [Communication Settings](baudrate_config) for CAN, CAN FD, SPI length-mode, and RS485 passthrough settings.