logo-mobile

ROHM

ROHM
Menu
  • Arduino –
  • Raspberry Pi –
  • Trending –
  • Others –
  • About –
  • Contact –

Arduino

Arduino Explorer Rover Part 3 – Programming

Jan Gromes
Published by Jan Gromes at January 16, 2018
Categories
  • Arduino
Tags
  • Arduino
  • arduino explorer
  • ardurover
  • programming
  • remote control
  • rover
  • space rover
ardurover

Commands and packet structure

Since we’re using LoRa to transmit and receive data, we have to keep in mind what that technology was designed for: transmitting small amount of data over long distances. This means that all our commands have to be as brief as possible as every byte will count. We could just send some string, e.g. “motor left 50” to set left motors to 50% speed, but that is incredibly wasteful. This string takes up 14 bytes of data just to pass two three chunks of information: what subsystem the command is meant for (“motor”) are which motors will be affected (“left”) and the percentage of maximum speed will they be set to (“50”). Safe to say, we can do better than that. The advantage is that this type of commands is very easy to read, but then again, as long as the system is working correctly, there should be no human interaction on the command level.

Instead of passing around long strings, I decided to develop a simple command system that only uses a maximum of 4 bytes for a command packet. The first byte in the packet is called header. It is further divided in half: the upper 4 bits contain the classification of command from the control system. The lower 4 bits are used for the response from the robot; 0 is success, non-zero values are error codes with known meaning.

1st byte Command description
0x00 Stop all motors
0x10 Set speed and direction of all motors
0x20 Set speed and direction of left side motors
0x30 Set speed and direction of right side motors
0x40 Set camera tilt
0x50 Set camera pan
0x60 Take a picture with camera
0x70 Start JPEG transmission
0x80 Force new sensor measurement
0x90 Get latest sensor data
0xA0 Resend last packet
0xB0 Set LoRa modem configuration
0xC0 Get all currently active errors
0xD0 unused
0xE0 unused
0xF0 unused

The next part of the packet is the payload – this is where all additional information for the command in header is stored. This part is a bit less straightforward than the header, because its contents depend on the type of command: some commands don’t require any additional info – 0x00 (stop both motors), for example. These commands have empty payload. However, some require up to three bytes of extra data, take for example command 0xD0 (LoRa configuration), which requires one byte for each of the main settings i.e. bandwidth, spreading factor, and coding rate (see the tutorial on LoRaLib or the GitHub wiki for details on LoRa). The following table describes structure of all packets.

1st byte 2nd byte 3rd byte 4th byte
0x00 – – –
0x10 left side speed PWM right side speed PWM direction
0x20 left side speed PWM direction –
0x30 right side speed PWM direction –
0x40 tilt position degrees – –
0x50 pan position degrees – –
0x60 – – –
0x70 picture number – –
0x80 sensor ID(s) – –
0x90 sensor ID(s) – –
0xA0 – – –
0xB0 bandwidth spreading factor coding rate
0xC0 – – –
0xD0 – – –
0xE0 – – –
0xF0 – – –

Of course, these are only the command packets transmitted by the control system and received by the robot. We also want the robot to respond. For some commands, this response can be very simple, just something to let the control system know that the command was either executed successfully or failed. If you take a closer look at the command table above, you will notice that all the commands only use the upper 4 bits of the 1st command byte. That leaves the bottom four bits which can be used for the response. This approach has two significant advantages: first, there’s no way to lose track which response belongs to a given command, because the command bits are always a part of the response. And second, there’s enough space for 16 different responses for each of the commands.

Let’s illustrate with an example. Say we want to take a picture with the camera, so we send command 0x60. The robot then has 16 different ways to respond. If the response is 0x60, it means that the command was executed successfully. All the other responses 0x61 to 0x6F mean something has gone wrong. Not only do we know that the command failed, we also have an idea of what’s wrong and how to fix it. Of course, the responses don’t always have to be just a single byte long. Some of the commands require the robot to send back additional information,like sensor data. The following table shows all the response packets for different commands.

Command 1st byte 2nd byte 3rd byte 4th – 240th byte
0x00 0x00 – – –
0x10 0x10 – – –
0x20 0x20 – – –
0x30 0x30 – – –
0x40 0x40 – – –
0x50 0x50 – – –
0x60 0x6_ – – –
0x70 0x7_ image data image data image data
0x80 0x8_ sensor(s) that failed sensor data sensor data
0x90 0x9_ sensor(s) that failed sensor data sensor data
0xA0 0xA0 – – –
0xB0 0xB0 – – –
0xC0 0xC_ error flags error flags –
0xD0 0xD0 – – –
0xE0 0xE0 – – –
0xF0 0xF0 – – –

You can notice that some of the commands – mainly those related to motors and servos – can only return 0 (success). That’s because the current version of on-board electronics has no way to tell if those command was executed successfully. To check that, we would have to add new equipment to test whether the motors are actually moving, or if the servo is physically in the correct position. While that shouldn’t be too difficult, let’s leave it for now and take a look at commands that can result in fail:

  • 0x60 (take a picture with camera)
    There’s a lot that can go wrong with this command. If there’s no camera present, the robot will return 0x61. If the camera is present and working, but fails to take the picture, it will return 0x62. Finally, if the picture was successfully taken, but cannot be stored, the return value will be 0x63.
  • 0x70 (start JPEG transmission)
    Again, this is a command that can return multiple values. If you recall from my article JPEG Decoding on Arduino, the first packet will contain information about the image, not actual pixel values. We need to distinguish the two types, so if the packet only contains image info. The response will be 0x70, followed by the information like width, height and MCU count. If the packet contains raw pixels values, the robot will respond with 0x71, followed by 238 bytes of pixel data.
    Now the error codes: if the response is 0x72, it means that the SD card was not found. If it is 0x73, it means that the card is fine but the requested image is not there.
  • 0x80 (force new sensor measurement)
    This command can only fail in a single way – if the requested sensor fails to take a measurement. In that case, the response will be 0x81, followed by one byte that contains information indicating sensor failed. The index of bit in that byte corresponds to sensors in the following order (from MSB to LSB): left VNH5019, right VNH5019, BD1020HFV, ML8511A, BM1383GLV, KX022-1020, RPR-0521RS and BM1422GMV. For example, if the second byte of the response is 0x03 (0b0000 00011), it means that sensors RPR-0521RS and BM1422GMV failed.
  • 0x90 (get latest sensor data)
    This command is very similar to 0x80 – it can only fail if some of the sensors fail. If that’s the case, it will respond with 0x91, followed by the same byte with error flags. After that, there will be up to 46 bytes of data from sensors. If none of the sensors fail, the second response byte will be simply 0x00, followed by all 46 bytes of data.
  • 0xB0 (set LoRa modem configuration)
    This is the last of the currently implemented commands that can fail, although this one really shouldn’t. It will set new LoRa modem configuration, and the provided configuration is checked for validity by LoRaLib. If one or more of the configuration values is invalid, one of the lower four bits in response byte will be set. So if the provided bandwidth is invalid, the robot will respond with 0xB1 (0b1011 0001). If all the provided configuration values are incorrect, the response will be 0xB7 (0b1011 0111). This command shouldn’t fail, because user can only select from known values. But still, it’s better to double check in this case. The LoRa module is the most critical subsystem, because without it, there’s no control over the robot. Due to the nature of LoRa modulation, the settings have to be the same on both modules. Otherwise, the receiver cannot demodulate the transmission.

With all that explained, let’s return to the original example. We wanted to set the left side motors speed to 50%. We already know that the header will be 0x20. So according to the above tables, we can fill in the rest of the bytes and the resulting packet sent from the controller will look like this:

0x20 0x7F 0x00 0x00

The first byte is obviously the header – set left motor speed. The next one is the speed. The motor driver changes speed of the motor by PWM modulation, so the number 0xF7 (127 in decadic format) corresponds to 50% duty cycle or 50% speed. The third byte is the direction – 0x00 means forward, 0x01 means backward. The last byte is just padding – it’s added so that the command packets are always four bytes long. Once the command is received and successfully executed by the robot, it will respond with the following packet:

0x20

The implementation of the command system in Arduino sketch that is running on the robot is on my GitHub. Usually, this is the place where I would post the actual code, unfortunately, it is far too big to fit into this article, so if you’re interested in details of the implementation, see the comments inside the actual code. Now, let’s move onto something more interesting, which is the remote control app!

 

1 2 3 4
Jan Gromes
Jan Gromes
Jan is currently studying Electrical Engineering at Brno University of Technology. He has many years of experience building projects using Arduino and other microcontrollers. His special interest lies in mechanical design of robotic systems.

Check us out on Social Media

  • Facebook
  • Twitter

Recommended Posts

  • Arduino Explorer Rover Part 2 – Electronics & WiringArduino Explorer Rover Part 2 – Electronics & Wiring
  • Arduino Explorer Rover Part 1 – ChassisArduino Explorer Rover Part 1 – Chassis
  • Arduino Explorer Rover Part 1 – Chassis Final AssemblyArduino Explorer Rover Part 1 – Chassis Final Assembly
  • Arduino Robot RF Explorer – Mechanics – Part 1Arduino Robot RF Explorer – Mechanics – Part 1
  • JPEG Decoding on Arduino TutorialJPEG Decoding on Arduino Tutorial
  • Arduino Long Range Communication Tutorial – LoRaLib LibraryArduino Long Range Communication Tutorial – LoRaLib Library
Receive update on new postsPrivacy Policy

Recommended Tutorials

  • How to integrate an RFID module with Raspberry Pi How to integrate an RFID module with Raspberry Pi
  • How to Use the NRF24l01+ Module with Arduino How to Use the NRF24l01+ Module with Arduino
  • How to Run Arduino Sketches on Raspberry Pi How to Run Arduino Sketches on Raspberry Pi
  • Setting Up Raspberry Pi as a Home Media Server Setting Up Raspberry Pi as a Home Media Server

Recommended Trends

  • SewBot Is Revolutionizing the Clothing Manufacturing Industry SewBot Is Revolutionizing the Clothing Manufacturing Industry
  • All About The Sumo Robot Competition And Technology All About The Sumo Robot Competition And Technology
  • 5 Interesting Tips to Calculating the Forward Kinematics of a Robot 5 Interesting Tips to Calculating the Forward Kinematics of a Robot
  • Go Inside the Drones That Are Changing Food Delivery Go Inside the Drones That Are Changing Food Delivery
Menu
  • Arduino –
    Arduino Beginner’s Guide
  • Raspberry Pi –
    Raspberry Pi Beginner's Guide
  • Trending –
    Updates on New Technologies
  • Others –
    Interviews / Events / Others

Check us out on Social Media

  • Facebook
  • Twitter
  • About
  • Company
  • Privacy Policy
  • Terms of Service
  • Contact
  • Japanese
  • 简体中文
  • 繁體中文
Don’t Forget to Follow Us!
© Copyright 2016-2022. Device Plus - Powered by ROHM
© 2022 Device Plus. All Rights Reserved. Muffin group

istanbul escort istanbul escort istanbul escort