Some years ago I created a voice controlled Robotis Bioloid robot...
I was able to use a voice app called Snips (later bought by Sonos) and then Google's Assistant embedded in a Raspberry Pi programmed in Python to send HEX-based packets to the Bioloid's proprietary CM-530 controller which caused it to respond with canned motions such as movements forward, back, etc.
I used PySerial to send the packets...here is a code snippet to show how the serial port was initialized and how the writes were done:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from hermes_python.ontology import *
import actions_leds
import serial
import time
# open serial port
ser = serial.Serial(port='/dev/ttyUSB0', baudrate=57600, timeout=1)
class Motions(object):
"""Class used to define which command(s) to send to robot
"""
# --> Sub callback function, one per intent
def move_forward(hermes, intent_message):
# terminate the session first if not continue
hermes.publish_end_session(intent_message.session_id, "")
# action code goes here...
print('[Received] intent: {}'.format(intent_message.intent.intent_name))
# send command to bot
ser.write(b'\xFF\x55\x01\xFE\x00\xFF')
# terminates action at one step
ser.write(b'\xFF\x55\x00\xFF\x00\xFF')
# if need to speak the execution result by tts
hermes.publish_start_session_notification(intent_message.site_id, "Going forward", "")
def move_back(hermes, intent_message):
# terminate the session first if not continue
hermes.publish_end_session(intent_message.session_id, "")
# action code goes here...
print('[Received] intent: {}'.format(intent_message.intent.intent_name))
# send command to bot
ser.write(b'\xFF\x55\x02\xFD\x00\xFF')
ser.write(b'\xFF\x55\x00\xFF\x00\xFF')
etc. for more actions...
I am trying to resurrect something similar, but both Amazon and Google have ceased allowing their API keys, so I am trying to move over to Arduino's Cloud app, and am therefore now trying to emulate sending the packets in Arduino's C[++], but cannot get the robot to accept/react to the packet...
So, I assume that either I have an issue with the serial port connection or the Serial.write function (or of course, both)...
My test is simple, I turn on the on-board LED for the Arduino NANO 33 and send out the packet...when I trigger Alexa, the LED flashes and I see that some characters come across the serial monitor that is included in the Arduino Cloud IDE, but they are gibberish so not sure if they are what should be coming through...
I have tried a few different forms of writing the packets as you can see from the code and have included some images of the results in the monitor...if I count the characters coming across, some stripping is occurring (which I believe is precluded in PySerial), so maybe that is the issue?
This is the code for the Arduino Cloud:
/*
Sketch generated by the Arduino IoT Cloud Thing "Untitled"
https://create.arduino.cc/cloud/things/2710fead-27c0-4e43-ab92-f1c4aa0ab11c
Arduino IoT Cloud Variables description
The following variables are automatically generated and updated when changes are made to the Thing
CloudSwitch lED_BLU;
Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
which are called when their values are changed from the Dashboard.
These functions are generated with the Thing and added at the end of this sketch.
*/
#include "thingProperties.h"
// 10-17-24 FBH initial setup
const int ledPin = 13;
int COUNTER1 = 0;
const long interval = 250; // delay in milliseconds for LED extinguish
void setup() {
// Initialize serial and wait for port to open:
//Serial.begin(9600); // default
Serial.begin(57600); // bot speed
// This delay gives the chance to wait for a Serial Monitor without blocking if none is found
delay(1500);
// Defined in thingProperties.h
initProperties();
// Connect to Arduino IoT Cloud
ArduinoCloud.begin(ArduinoIoTPreferredConnection);
/*
The following function allows you to obtain more information
related to the state of network and IoT Cloud connection and errors
the higher number the more granular information you’ll get.
The default is 0 (only errors).
Maximum is 4
*/
setDebugMessageLevel(2);
ArduinoCloud.printDebugInfo();
// 10-17-24 FBH initial setup
pinMode(ledPin, OUTPUT);
}
void loop() {
ArduinoCloud.update();
// Your code here
}
/*
Since LEDBLU is READ_WRITE variable, onLEDBLUChange() is
executed every time a new value is received from IoT Cloud.
*/
void onLEDBLUChange() {
// Add your code here to act upon LEDBLU change
if (lED_BLU == 1) {
// send one set of instructions to robot then hand off to delay for reset ro ready state
do {
// send command to bot
// method 1
/*
Serial.write(0xFF);
Serial.write(0x55);
Serial.write(0x21);
Serial.write(0xDE);
Serial.write((byte) 0x00); // (byte) required by Arduino
Serial.write(0xFF);
*/
// method 2
byte action_poundChest[] = {0xFF, 0x55, 0x21, 0xDE, 0x00, 0xFF};
Serial.write(action_poundChest, 6);
// method 3
//Serial.write("\xFF\x55\x21\xDE\x00\xFF");
digitalWrite(ledPin, HIGH); // just for t/s now
COUNTER1 = 1; // use to limit robot instructions to one set of sequences
}
while (COUNTER1 == 0);
delay(interval);
digitalWrite(ledPin, LOW);
COUNTER1 = 0;
}
else {
digitalWrite(ledPin, LOW);
}
}
These are the images of the serial monitor associated with the three different approaches to the packet writes:
So, wondering if someone who is familiar with both pySerial and Arduino Serial may be able to understand what is changing and causing the packet data not to be registering in the robot's controller...
Thanks, Frank
UPDATE
I am now on a path to check with a serial monitor and see what actually is coming out of the pipe, but I realized it would be best to compare it to whatever actually worked before, so, I decided to try and re-create the previous episode with the RPi...
I fired up an RPi and wrote a short button-press Python sketch, checked that it worked okay, then added a serial port with initialization as is shown above using PySerial and inserted ser.write line as before to follow the button push - lo-and-behold, the robot woke up and pounded its chest!
So at least now I have something to work on to compare and see what's missing when I port this over to Arduino C[++]...
My plan is to learn a bit about serial monitoring and see if I can figure out what is different, but I would till appreciate any thoughts...
Frank