Extended previous example with data sending from X4 → ESP32
Important: A bit of “hack” is required to access some internal RoboBoard functionality. Will implement a proper way to do it later (with furter software releases).
For now, update this file path to match your file system. It should point to this file inside “TotemLibrary”:
#include "C:\Users\NAME\Documents\Arduino\libraries\TotemArduino\src\core\TotemBUS.h"
Example demonstrates sending 32bit integer, string or data array.
RoboBoard X4 Arduino sketch:
void appEvent(int evt, int value) {
// If disconnected from RoboBoard - stop all motors
if (evt == TotemApp.evtDisconnect) {
DC.brake();
return;
}
// Accept only "functionA"
if (evt != TotemApp.evtFunctionA) return;
// Unpack data from 32-bit "value" variable
int cmd = value & 0xFF; // Function type to call
int port = (value >> 8) & 0xFF; // Motor port (A,B,C,D)
value = value >> 16; // Value sent to the function (16-bit)
// Execute selected command
switch (cmd) {
case 0: DC[port].brake(value); break;
case 1: DC[port].spin(value); break;
case 2: DC[port].tone(value); break;
case 3: DC[port].setAccelerationTime(value); break;
case 4: DC[port].setDecelerationTime(value); break;
}
}
// Update path to match your local file system
#include "C:\Users\USER\Documents\Arduino\libraries\TotemArduino\src\core\TotemBUS.h"
int BleServerService_sendFrame(TotemBUS::Frame frame, uint16_t number, uint16_t serial);
// Functions to send data back to ESP32
int sendValue(int command, int value) {
return BleServerService_sendFrame(TotemBUS::respond(command, value), 4, 0);
}
int sendData(int command, uint8_t *data, uint32_t len) {
return BleServerService_sendFrame(TotemBUS::respond(command, {(const char*)data, len}), 4, 0);
}
int sendString(int command, const char *str) {
return BleServerService_sendFrame(TotemBUS::respond(command, {str, strlen(str)}), 4, 0);
}
IOButton button(BUTTON_BUILTIN);
void buttonEvent(int evt) {
// Send X4 button state to ESP32
if (evt == Button.evtPress) { sendValue(11, 1); }
else if (evt == Button.evtRelease) { sendValue(11, 0); }
}
void setup() {
TotemApp.addEvent(appEvent); // Register events from Totem.BLE
button.addEvent(buttonEvent); // Regiser button event
}
void loop() {
// Send value (integer) to ESP32
sendValue(55, 1000);
printf("send command:55 value:1000 to ESP32\n");
delay(1000);
// Send string to ESP32
sendString(66, "This is a text");
printf("send command:66 string:'This is a text' to ESP32\n");
delay(1000);
// Send byte array to ESP32
uint8_t arr[] = {1, 2, 3, 4, 5, 0};
sendData(77, arr, sizeof(arr));
printf("send command:77 bytes: 1,2,3,4,5,0 to ESP32\n");
delay(1000);
}
Remote ESP32 Arduino sketch:
#include <Totem.h>
// Define object that will be used to access X4 board.
// It will become active when BLE connection is established.
TotemModule rb_x4(04);
// Function wrapper to send custom commands to X4
class RoboBoardX4 {
void write(int cmd, int port, int value) {
// Pack parameters to 32-bit "value"
value <<= 16;
value |= (port & 0xFF) << 8;
value |= (cmd & 0xFF);
rb_x4.write("functionA", value); // Send to X4
}
public:
// port: 0-A, 1-B, 2-C, 3-D
void brake(int port, int value = 100) { write(0, port, value); }
void spin(int port, int value) { write(1, port, value); }
void tone(int port, int value) { write(2, port, value); }
void setAccelerationTime(int port, int value) { write(3, port, value); }
void setDecelerationTime(int port, int value) { write(4, port, value); }
} X4;
// Receive data from RoboBoard X4
void onSendFromX4(ModuleData data) {
if (data.getHashCmd() == 11) { // Buton was pressed on RoboBoard X4
printf("==>> BUTTON: %d\n", data.getInt());
}
else if (data.isInt()) { // Used "sendValue"
// Get command and value
int command = data.getHashCmd();
int value = data.getInt();
// Print command and value
printf("==>> Got command: %d value: %d\n", command, value);
}
else if (data.isString()) { // Used "sendData" or "sendString"
// Get command and string
int command = data.getHashCmd();
const char *str = data.getString();
// Get data array
uint8_t *dataPtr; int dataLen;
data.getData(dataPtr, dataLen);
// Print string & data array (choose the one you need)
printf("==>> Got command: %d string: %s\nBytes(%d): ", command, str, dataLen);
for (int i=0; i<dataLen; i++) {
printf(" %d", dataPtr[i]);
}
printf("\n");
}
}
// Arduino setup function.
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Totem.BLE.begin(); // Start Bluetooth Low Energy interface
Serial.println("Searching for Totem board...");
// Start scanning for Totem board. It's representing a Totem robot.
TotemRobot robot = Totem.BLE.findRobot(); // Wait until connected to first found Totem robot
// Print connected robot name
Serial.print("Connected to: ");
Serial.println(robot.getName());
// Register data receiver from RoboBoard X4
rb_x4.attachOnData(onSendFromX4);
// Proceed to loop
}
// Arduino loop function
void loop() {
X4.spin(0, 50); // Send to X4
Serial.println("Spin DC A 50%");
delay(1000);
X4.brake(0); // Send to X4
Serial.println("Stop DC A");
delay(1000);
}