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.infoFor 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_tin C++ andUInt8in Swift - and represented as
hexvalues
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
idcorresponding to one command, e.g. theinfocommand - complex command - one
idand additionaldataneeded 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 bufferis empty, we exit thewhileloop 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
sizeis smaller than the minimum length --> we return and wait for more serial data - if
sizeis greater than the minimum length --> we continue the process
While serialBuffer is not empty:
-
The
serialBufferis parsed forstart sequence:- if not found, the
serialBufferis purged and we go back to the main loop waiting for new serial data - if found, the next value, corresponding to the
command frame lengthis read
- if not found, the
-
The command frame is then read and stored in the
commandBuffer -
When
serialBufferis empty, we exit thewhileloop 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