# Programming API

API Compatibility: S500 communication uses a binary packet format compatible with the Blue Robotics [Ping-Protocol](https://github.com/bluerobotics/ping-protocol). It supports most of the Blue Robotics [Ping1](https://bluerobotics.com/store/sensors-sonars-cameras/sonar/ping-sonar-r2-rp/) packet types.

Documentation: The generic packet format is documented below, as are the specific payloads. These packet types are recommended for new applications targeting the S500 sounder.

Apology: The terms "altitude," "distance," and "depth" are used somewhat interchangeably here. They all mean the sensed distance from the device to some object, which in many applications is "the bottom."&#x20;

## **Packet Format**&#x20;

<table data-header-hidden><thead><tr><th width="150"></th><th width="150"></th><th width="150"></th><th></th></tr></thead><tbody><tr><td><strong>Byte</strong></td><td><p> </p><p><strong>Data Type</strong></p><p> </p></td><td><p> </p><p><strong>Name</strong></p><p> </p></td><td><p> </p><p><strong>Description</strong></p><p> </p></td></tr><tr><td>0 to 1</td><td><p> </p><p>char[2]</p><p> </p></td><td><p> </p><p>start_of_packet</p><p> </p></td><td><p> </p><p>2 byte ASCII string "BR" marks start of packet</p><p> </p></td></tr><tr><td>2 to 3</td><td><p> </p><p>u16</p><p> </p></td><td><p> </p><p>payload_length</p><p> </p></td><td><p> </p><p>number of bytes in payload</p><p> </p></td></tr><tr><td>4 to 5</td><td><p> </p><p>u16</p><p> </p></td><td><p> </p><p>packet_id</p><p> </p></td><td><p> </p><p>corresponds to ID field in packet payload definitions below</p><p> </p></td></tr><tr><td>6</td><td><p> </p><p>u8</p><p> </p></td><td><p> </p><p>reserved</p><p> </p></td><td><p> </p><p>set to 0</p><p> </p></td></tr><tr><td>7</td><td><p> </p><p>u8</p><p> </p></td><td><p> </p><p>reserved</p><p> </p></td><td><p> </p><p>set to 0</p><p> </p></td></tr><tr><td>8 to n</td><td><p> </p><p>u8[]</p><p> </p></td><td><p> </p><p>payload</p><p> </p></td><td><p> </p><p>payload message. Format varies with packet id per payload definitions below</p><p> </p></td></tr><tr><td>(n+1) to (n+2)</td><td><p> </p><p>u16</p><p> </p></td><td><p> </p><p>checksum</p><p> </p></td><td><p> </p><p>sum of all the bytes in the packet. Truncated to 16 bits</p><p> </p></td></tr></tbody></table>

## **Packet Payload Definitions**

### **General**&#x20;

<table><thead><tr><th width="184">Name</th><th width="150">ID</th><th width="150">Data Type</th><th width="150">Name</th><th>Description</th></tr></thead><tbody><tr><td>nop</td><td>0</td><td></td><td>none</td><td>clients may ignore. Sometimes useful to keep things awake</td></tr><tr><td>ack</td><td>1</td><td>u16</td><td>id</td><td>id being acked</td></tr><tr><td>nack</td><td>2</td><td>u16</td><td>id</td><td>id being nacked</td></tr><tr><td></td><td></td><td>char[]</td><td>msg</td><td>optional ascii text message describing error*</td></tr><tr><td>ascii_text</td><td>3</td><td>char[]</td><td>msg</td><td>any ascii text string*</td></tr><tr><td>general_request</td><td>6</td><td>u16</td><td>id</td><td>request client to respond with packet id type</td></tr></tbody></table>

\*STR\_LEN: Length of the string determined based on payload\_length in packet header.

### **Request Info Response Packets**

*These are the responses that the device will send to the host in response to a general\_request packet (id = 6, see above). Alternatively, host may send any one of these packet ids with no payload and device will respond with same id and the payload indicated here.*

<table><thead><tr><th width="202">Name</th><th width="94">ID</th><th width="113">Data Type</th><th width="162">Name</th><th>Description</th></tr></thead><tbody><tr><td>fw_version</td><td>1200</td><td>u8</td><td>device_type</td><td></td></tr><tr><td></td><td></td><td>u8</td><td>device_model</td><td></td></tr><tr><td></td><td></td><td>u16</td><td>version_major</td><td></td></tr><tr><td></td><td></td><td>u16</td><td>version_minor</td><td></td></tr><tr><td>speed_of_sound</td><td>1203</td><td>u32</td><td>sos_mm_per_sec</td><td>current speed of sound setting in mm/sec default is 1500 m/sec</td></tr><tr><td>range</td><td>1204</td><td>u32</td><td>start_mm</td><td>normally 0</td></tr><tr><td></td><td></td><td>u32</td><td>length_mm</td><td>start_mm + length_mm is max range</td></tr><tr><td>ping_rate_msec</td><td>1206</td><td>u16</td><td>msec_per_ping</td><td>minimum time between successive pings. Can be longer depending on range</td></tr><tr><td>gain_index</td><td>1207</td><td>u32</td><td>gain_index</td><td>current gain index setting</td></tr><tr><td>altitude</td><td>1211</td><td>u32</td><td>altitude_mm</td><td>result of most recent calculated distance from device to bottom (or other target)</td></tr><tr><td></td><td></td><td>u8</td><td>quality</td><td>measure of confidence of altitude measure 0 (no idea) to 100 (quite sure)</td></tr><tr><td>processor_degC</td><td>1213</td><td>u32</td><td>centi_degC</td><td>device CPU temperature degrees C * 100</td></tr></tbody></table>

### **Commands**&#x20;

<table><thead><tr><th width="219">Name</th><th width="72">ID</th><th width="111">Data Type</th><th width="168">Name</th><th>Description</th></tr></thead><tbody><tr><td>set_speed_of_sound</td><td>1002</td><td>u32</td><td>sos_mm_per_sec</td><td>default value is 15000000 mm/sec (1500 meters/sec)</td></tr><tr><td>set_ping_params</td><td>1015</td><td>u32</td><td>start_mm</td><td>start of ping range, normally 0</td></tr><tr><td></td><td></td><td>u32</td><td>length_mm</td><td>length of the returned profile. so end of range = start_mm + length_mm. Set to 0 for auto range.</td></tr><tr><td></td><td></td><td>i16</td><td>gain_index</td><td>set to -1 for auto gain, otherwise 0-13 sets gain for manual gain</td></tr><tr><td></td><td></td><td>i16</td><td>msec_per_ping</td><td>set to -1 to start a single ping. Otherwise sets minimum ping interval</td></tr><tr><td></td><td></td><td>u16</td><td>pulse_len_usec</td><td>0 for auto mode. currently ignored and auto duration always used</td></tr><tr><td></td><td></td><td>u16</td><td>report_id</td><td>the ID of the packet type that you would like in response. Options are: distance2 (1223), profile6 (1308), or zero. Zero disables pinging.</td></tr><tr><td></td><td></td><td>u16</td><td>reserved</td><td>Set to 0.</td></tr><tr><td></td><td></td><td>u8</td><td>chirp</td><td>set to 1 for chirp, 0 for monotone ping</td></tr><tr><td></td><td></td><td>u8</td><td>decimation</td><td>set to 0 for auto range resolution in chirp mode.</td></tr></tbody></table>

### **Ping Response Packets**&#x20;

*These packet types can be returned after each ping by specifying their packet id in the report\_id field of the set\_ping\_params packet described above.*

*distance2 reports a simple distance measurement.*&#x20;

*profile6\_t report a measure of signal strength at all depths within the ping range. This could be used to present a "waterfall" type display similar to a commercial marine depth sounder or fish finder. The Cerulean SonarView app uses profile6\_t to do just that.*

*The native number of results reported for the profile6\_t is 1024 for monotone pings. For chirp pings, the range resolution is affected by the "decimation" field in the set\_ping\_params command. If decimation is set to 0, the device will vary decimation depending on range. The smallest decimation will be used that does not exceed 6000 reported data elements.*

*Keep in mind the bandwidth of the communication channel in use when considering which profile report to use. For example, profile6\_t can generate a lot of data, and is probably best used with the USB or Ethernet interface.*&#x20;

<table><thead><tr><th width="150">Name</th><th width="80">ID</th><th width="150">Data Type</th><th width="196">Name</th><th>Description</th></tr></thead><tbody><tr><td>distance2</td><td>1223</td><td>u32</td><td>this ping distance mm</td><td>most recent ping</td></tr><tr><td></td><td></td><td>u32</td><td>averaged distance mm</td><td>average over last 20 pings</td></tr><tr><td></td><td></td><td>u16</td><td>reserved</td><td></td></tr><tr><td></td><td></td><td>u8</td><td>this ping confidence</td><td>0 to 100</td></tr><tr><td></td><td></td><td>u8</td><td>confidence of averaged distance</td><td>0 to 100</td></tr><tr><td></td><td></td><td>u32</td><td>timestamp </td><td>msec</td></tr><tr><td></td><td></td><td></td><td></td><td></td></tr><tr><td>profile6_t</td><td>1308</td><td>u32</td><td>ping_number</td><td>sequentially assigned from 0 at power up</td></tr><tr><td></td><td></td><td>u32</td><td>start_mm</td><td></td></tr><tr><td></td><td></td><td>u32</td><td>length_mm</td><td></td></tr><tr><td></td><td></td><td>u32</td><td>start_ping_hz</td><td></td></tr><tr><td></td><td></td><td>u32</td><td>end_ping_hz</td><td></td></tr><tr><td></td><td></td><td>u32</td><td>adc_sample_hz</td><td></td></tr><tr><td></td><td></td><td>u32</td><td>timestamp_msec</td><td></td></tr><tr><td></td><td></td><td>u32</td><td>spare2</td><td></td></tr><tr><td></td><td></td><td>float</td><td>pulse_duration_sec</td><td></td></tr><tr><td></td><td></td><td>float</td><td>analog_gain</td><td></td></tr><tr><td></td><td></td><td>float</td><td>max_pwr_db</td><td></td></tr><tr><td></td><td></td><td>float</td><td>min_pwr_db</td><td></td></tr><tr><td></td><td></td><td>float</td><td>this_ping_depth_m</td><td>depth in meters as calculated from the most recent ping</td></tr><tr><td></td><td></td><td>float</td><td>smooth_depth_m</td><td>smoothed calculated depth</td></tr><tr><td></td><td></td><td>float</td><td>fspare2</td><td>0</td></tr><tr><td></td><td></td><td>u8</td><td>this ping depth measurement  confidence</td><td>depth measurement confidence (0-100) based on most recent ping</td></tr><tr><td></td><td></td><td>u8</td><td>gain_index</td><td></td></tr><tr><td></td><td></td><td>u8</td><td>decimation</td><td></td></tr><tr><td></td><td></td><td>u8</td><td>smoothed depth measurement confidence (0-100)</td><td>0</td></tr><tr><td></td><td></td><td>u16</td><td>num_results</td><td></td></tr><tr><td></td><td></td><td>u16</td><td>pwr_results[]</td><td>power results scaled from min_pwr to max_pwr. num_results entries</td></tr></tbody></table>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ceruleansonar.com/c/s-500-sounder/technical-details/programming-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
