Arduino SDK Questions

Hello Sphero! I received my RVR today and have it charged up, firmware updated, and zipping around the house. Very cool! :grinning:

I was poking around in the Arduino SDK GitHub repository and see that the SDK is currently a compiled library for the older atmeg328 (AVR) boards like the UNO and MEGA. These boards a getting pretty old at this point and have some definite limitations, especially the UNO with only 2K of RAM. However, I know they are ubiquitous in the Arduino community and I am glad to see support for them already.

I know it is early, but I am really hoping that Sphero will release actual source code for the Arduino library like most all other Arduino libraries. This will allow the code to be run on multiple platforms compatible with the Arduino IDE. I use newer Arduino boards like the MKR1010WiFi, Nano33IoT, ESP8266, and ESP32 as these all include WiFi. These are also 3.3v boards, which are more compatible with the RVR’s 3.3v UART pins (Note: I believe the UNO is supposed to be connected via the USB A connector on the RVR and not the UART pins, correct?)

Again, I realize that is very early. I am very hopeful that support for more boards is part of Sphero’s plans for the Arduino support for the RVR. I’d also be fine with full documentation for the UART serial protocol which will allow the user community to build an OpenSource Arduino IDE compatible library for the RVR that would work on all 3.3v UART compatible boards.

Thanks for listening! :wink: And Thank You for creating such a great set of Bots! Keep up the great work.

Dan

1 Like

Hi @ogiewon, it’s great to hear you’re enjoying your RVR!

We are working on public-facing API documentation which will include the packet format and individual command definitions. RVR uses the same protocol over UART, BLE, and USB serial. You are correct that the UNO is intended to be connected to the USB A connector on the RVR for a USB serial connection.

There may be more open-source SDK code in the future, but in the meantime while you’re waiting for our documentation to be ready, you can look at this python file from the micro:bit SDK for some examples of packet construction for a few commands: https://github.com/sphero-inc/sphero-sdk-microbit-python/blob/master/sphero.py

Have fun!
Jim

2 Likes

@Sphero_JimK

Jim,

Thanks for the reply and glad to hear the documentation is coming along. I spent a little bit of time yesterday looking at the sphero.py script and can see the basics of the serial protocol. Should be enough to get started tinkering via an Arduino IDE compatible board like a NodeMCU ESP8266. Looking forward to the official documentation when it is ready.

Thanks,
Dan

3 Likes

There’s actually a lot more detail available in the Raspberry Pi Python SDK, this file and others with it are probably better to check out than the micro:bit library since micro:bit doesn’t have enough memory to support the full command set in python.

2 Likes

I’d LOVE to see some ESP8266 implementation.

1 Like

I’m reverse engineering the protocol in C++ using my desktop and a USB to 3.3v serial converter (Adafruit 954). I’ve gotten codes that allow Wake, Sleep, Twist (speed & heading - name comes from ROS), and raw drive. Reset yaw doesn’t seem to do anything. Haven’t tried the LEDs, yet.

Been looking at the Pi and microBits code but it’s a hard slog in some places.

The outer protocol message is bracketed between 0x8D and 0xD8 bytes. Checksum is a summation of the payload, negated, and the last byte before the 0xD8. Haven’t implemented the escape coding but will do that soon.

What would be nice is if we could get @Codeman or someone from Sphero to at least explain the other ‘header’ bytes.

Byte   Usage
0      cmd: 0x3e
       resp: 0x28
       assume actually a flag but what are the bits?
1      cmd: 0x11 (LED/Power) or 0x12 (drive) - processor code?
       resp: 0x01 accepted command flag. Haven't seen error code so???
2      cmd: 01 - processor code? Haven't seen another value
       resp: cmd code acknowledged? 
3      cmd: subsystem code? Power 0x13, Drive 0x16, LEd 0x1A
       resp: ????
4      cmd: cmd code?
       resp: ???

I see a lot of hints in the Python code but hard to tell how those hings map to a message. I see slots for:

['__flags', '__did', '__cid', '__seq', '__target', '__source', '__err', 'byte_length']

Not sure how they map to the message.

Thinking of writing an article(s) on Medium about decoding the protocol. It will include explaining the techniques that go into creating a protocol as I decipher this one.

More later…

5 Likes

Hey @rmerriam!

Your work is impressive! We will be releasing the API docs soon (on sdk.sphero.com), which will help much more with having a byte-level understanding of communication with RVR :slight_smile:

In the meantime, I can tell you that the header bytes, in order are:
TID - Target ID (if there is one) - the address of the target, expressed as a port ID and a node ID
SID - Source ID (if there is one) - the address of the sorce, expressed as a port ID and a node ID
DID - Device ID - The command group (eg Power or LEDs or Driving )
CID - Command ID - The command to execute
Seq - A token (random number) that the sender sends to the receiver and the receiver sends back
Err - Error (if there is one)

There are also flags, as you noted, that modify the behavior of the packet:
Bit 0 indicates whether the packet is a response(1) or a command (0); if the packet is a response, you can expect there to be an error code byte in the header.
Bit 4 indicates whether the packet has a Target ID in the header (1) or not (0).
Bit 5 indicates whether the packet has a Source ID in the header (1) or not (0).

We are so excited to have you so engaged and look forward to all your questions and projects to come!

Kelsey

3 Likes

To add a bit more to @brightnbubbly’s description:

The target ID is either 1 or 2 for RVR, and dictates which of the 2 on-board processors will receive the command.

  • Target 1 is the Bluetooth SOC, which also handles the power system, indications, the color sensor, and the ambient light sensor. (This is why you’ve only seen 1 so far).
  • Target 2 is a general-purpose microcontroller which handles the control system, IR communication, USB, and the IMU.

When our full command documentation is available it will include the proper target addressing for each command. When you send commands to RVR you do not need to include a source address. One will be generated internally for routing responses back to you if requested.

-Jim

4 Likes

Appreciate it Jim. Is the Source the UART vs USB port?

1 Like

BLE is also included in the source, but it’s more complicated than just which external port.

Source and target are actually compound fields, split by nibble into a node and a port. So there are some additional things you can do with multiple API nodes outside of the robot. It’s best to wait for the official documentation on that, since it’s difficult to fully explain the addressing without diagrams.

-Jim

1 Like

ETA for this information? I’m looking for the same information but to create a Parallax Propeller version.

1 Like

Based on the Python code, here’s a C start for the packets:

#ifndef __RVRDEFS_H
#define __RVRDEFS_H 1

#include <sys/types.h>

struct header {
    struct flag_bits flags;         
    struct locationID targetID;     /* optional, depends on flags */
    struct locationID sourceID;     /* optional, depends on flags */
    uint8_t deviceID;     /* command group ... see defines below */
    uint8_t commandID;
    uint8_t sequence_num;
};

struct flag_bits {
    unsigned int is_response:1;
    unsigned int response_requested:1;
    unsigned int response_requested_if_error:1;
    unsigned int is_activity:1;
    unsigned int has_target:1;
    unsigned int has_source:1;
    unsigned int UNUSED:1;
    unsigned int has_more_flags:1;
};

struct locationID {
    unsigned int port:4;
    unsigned int node:4;
}

#define DRIVE_GROUP   0x13
#define POWER_GROUP   0x16
#define LED_GROUP     0x1a

#define MESSAGE_START 0x8D
#define MESSAGE_END   0xD8

struct message {
    struct header msghdr;
    char * payload;
    uint8_t checksum;
};

#define ECHO_COMMAND             0x00
#define RAW_MOTOR_COMMAND        0x01
#define GET_BLUETOOTH_ADVERT     0x05
#define RESET_YAW_COMMAND        0x07
#define WAKE_COMMAND             0x0D
#define GET_BATT_LEVEL_COMMAND   0x10
#define SET_ALL_LEDS_COMMAND     0x1A

I put in some commands. I have not been through all the Python SDK.

An actual RVR packet is then a MESSAGE_START, a struct message, and a MESSAGE_END.

Is this close?

3 Likes

Starting a new thread “Reverse Engineering the Protocol” for these discussions. Started a Wiki with information and will post URL there.

2 Likes