This repository contains the specifications to easily implement master-slave communication between a master-device (computer, phone, tablet) and a slave-Leka robot, provided that the master has BLE compatible hardware.
- About
- Table of Contents
- Installation
- Use
- Definitions
- Command frame Specifications
- Command Specifications
- How it works inside Leka
With SPM, add the following to the dependencies of your Package.swift
.package(url: "https://github.com/leka/LKAlphaComSpecs", from: "3.0.0")
// TODO: -
// TODO: -
Copy the file Sources/LKAlphaComSpecs.swift
in your project.
import LKAlphaComSpecs
let cmd = LKCommand.info
For easier understanding:
-
frame
/command frame
- the whole structure of data sent by the master to the robot, including start sequence, length, commands and checksum -
commands
/command group
: a group of one or more commands to be performed by the robot -
command
: a specific command performed by the robot
A command frame is composed of the following:
- start sequence
- length of the command group
- command group with one or more commands
- checksum
The data are always encoded on:
8 bits
/1 byte
- using
uint8_t
in C++ andUInt8
in Swift - and represented as
hex
values
Each command frame starts with a start sequence
:
- length:
4 bytes
- values:
[0x2A, 0x2B, 0x2C, 0x2D]
Each command frame ends with a checksum:
- type: BSD Checksum
- input:
command group
&command group length
To generate a valid command frame, the following steps are needed:
-
commands are concatenated in an command group
-
the length of the command group is calculated and stored
-
a checksum of the command group is generated
-
a command frame is generated by concatenation of:
- start sequence
- command group's length
- command group
- command group's checksum
Here is an example with a simple command:
Goal: turn on belt LED[0] in red / RGB(255, 00, 00)
- Command id: led/belt/single --> 15
- LED id: 0 --> 00
- RGB values: 255, 0, 0 --> FF 00 00
1. Create command group:
--> 15 00 FF 00 00
2. Get command group length:
--> 05
3. Calculated checksum:
--> 41
4. Concatenate command frame:
--> 2A 2B 2C 2D 05 15 00 FF 00 00 41
The minimum length of a command frame is 7 bytes
, corresponding to the info
(0x70
) action:
2A 2B 2C 2D 01 70 70
In theory, the maximum length of a command frame is 128 bytes
, corresponding to the size of the serial buffer used in Leka.
But one has to always assume that data is still present in the buffer and might prevent the whole command from being received and processed.
In real life, one will almost never reach the 128 bytes
limit.
As an example, the following command frame turns on color each one of the 20 LEDs of the robot's belt in a specific RGB color:
2A 2B 2C 2D 64 15 00 33 00 00 15 01 66 00 00 15 02 99 00 00 15 03 CC 00 00 15 04 FF 00 00 15 05 00 00 00 15 06 00 33 00 15 07 00 66 00 15 08 00 99 00 15 09 00 CC 00 15 0A 00 FF 00 15 0B 00 00 00 15 0C 00 00 33 15 0D 00 00 66 15 0E 00 00 99 15 0F 00 00 CC 15 10 FF 00 00 15 11 00 FF 00 15 12 00 00 FF 15 13 FF FF FF A8
The length of the whole command frame is 106 bytes
, far from the 128 bytes
limit.
The detailed list of commands available is available here:
A command can have one of two forms:
- simple command - one
id
corresponding to one command, e.g. theinfo
command - complex command - one
id
and additionaldata
needed to perform the command, e.g. turning the ears of the robot red
You can find all the commands available in Specs/LKAlphaComSpecs.yml
Command | Type | ID | Length | Data | |
---|---|---|---|---|---|
info |
simple | 0x70 |
0 | 0 | n/a |
stop.led |
simple | 0xFD |
0 | 0 | n/a |
stop.motor |
simple | 0xFE |
0 | 0 | n/a |
stop.robot |
simple | 0xFF |
0 | 0 | n/a |
led.ear.all |
complex | 0x11 |
3 | 3 | R / G / B |
led.ear.single |
complex | 0x12 |
1 + 3 | 4 | id (0x00..0x01 ) + R / G / B |
led.belt.all |
complex | 0x13 |
3 | 3 | R / G / B |
led.belt.range |
complex | 0x14 |
1 + 1 + 3 | 5 | first + last + R / G / B |
led.belt.single |
complex | 0x15 |
1 + 3 | 4 | id (0x00..0x19 ) + R / G / B |
motor.all |
complex | 0x21 |
1 + 1 | 2 | direction + speed |
motor.duo |
complex | 0x22 |
1 + 1 + 1 + 1 | 4 | L-spin + L-speed + R-spin + L-spin |
motor.left |
complex | 0x23 |
1 + 1 | 2 | spin + speed |
motor.right |
complex | 0x24 |
1 + 1 | 2 | spin + speed |
motivator |
complex | 0x50 |
1 | 1 | id (0x51..0x55 ) |
guidance |
complex | 0x40 |
1 | 1 | id (0x41..0x4F ) |
The way Leka Alpha handles command on the inside can be decided in 3 main steps.
Leka Alpha runs an infinite loop while waiting for incoming data.
-
While serial data is available, we read the
hardware serial buffer
^1 and store the data in our own software circularserialBuffer
-
When the the
hardware serial buffer
is empty, we exit thewhile
loop and move to the next step
First, check that the size of serialBuffer
is greater than the minimum length of a command frame (7 bytes
):
- if
size
is smaller than the minimum length --> we return and wait for more serial data - if
size
is greater than the minimum length --> we continue the process
While serialBuffer
is not empty:
-
The
serialBuffer
is parsed forstart sequence
:- if not found, the
serialBuffer
is purged and we go back to the main loop waiting for new serial data - if found, the next value, corresponding to the
command frame length
is read
- if not found, the
-
The command frame is then read and stored in the
commandBuffer
-
When
serialBuffer
is empty, we exit thewhile
loop and move to the next step
While commandBuffer
is not empty, it is read and each command is ran one after the other.
When commandBuffer
is empty, we exit the while
loop and start the process all over again by waiting for serial data to be available.
[1]: in reality it is not a hardware buffer, it is the Arduino provided serial buffer. But as its API is very limited, it's easier to use our own circular buffer serialBuffer