Hi Community,
I need assistance with trying to extract data from serial data sent by a Python3 script that will control motors attached to my arduino.
C++ is not my strong point and i have been racking my brains trying to solve this solution. I have spent weeks scouring the net for a solution, have learnt lots but obviously not enough. Hence me reaching out to the community. I did have code working but it was really laggy. i have been trying to implement the endmarkers solution but i can't work out how to extract the the data in the arduino to control motors; motor direction and speed (PWM).
I am sending the following value format from python3 script:
('b', 157)
The letter is the motor direction and the integer is the pwm value (motor speed).
I would appreciate if someone could offer assistance with code that is responsive and can control my motors.
My Python3 code that generates random values to simulate motor direction and speed:
import random
import string
import serial
import time
startMarker = '<'
endMarker = '>'
dataStarted = False
dataBuf = ""
messageComplete = False
#========================
#========================
# the functions
def setupSerial(baudRate, serialPortName):
global serialPort
serialPort = serial.Serial(port= serialPortName, baudrate = baudRate, timeout=0, rtscts=True)
print("Serial port " + serialPortName + " opened Baudrate " + str(baudRate))
waitForArduino()
#========================
def sendToArduino(stringToSend):
# this adds the start- and end-markers before sending
global startMarker, endMarker, serialPort
stringWithMarkers = (startMarker)
stringWithMarkers += stringToSend
stringWithMarkers += (endMarker)
serialPort.write(stringWithMarkers.encode('utf-8')) # encode needed for Python3
#==================
def recvLikeArduino():
global startMarker, endMarker, serialPort, dataStarted, dataBuf, messageComplete
if serialPort.inWaiting() > 0 and messageComplete == False:
x = serialPort.read().decode("utf-8") # decode needed for Python3
if dataStarted == True:
if x != endMarker:
dataBuf = dataBuf + x
else:
dataStarted = False
messageComplete = True
elif x == startMarker:
dataBuf = ''
dataStarted = True
if (messageComplete == True):
messageComplete = False
return dataBuf
else:
return "XXX"
#==================
def waitForArduino():
# wait until the Arduino sends 'Arduino is ready' - allows time for Arduino reset
# it also ensures that any bytes left over from a previous message are discarded
print("Waiting for Arduino to reset")
msg = ""
while msg.find("Arduino is ready") == -1:
msg = recvLikeArduino()
if not (msg == 'XXX'):
print(msg)
#====================
#====================
# the program
setupSerial(115200, "/dev/ttyUSB0")
count = 0
prevTime = time.time()
while True:
# check for a reply
arduinoReply = recvLikeArduino()
if not (arduinoReply == 'XXX'):
print ("Time %s Reply %s" %(time.time(), arduinoReply))
num = random.randint(0,254)
letters = random.choice(string.ascii_lowercase)
command = (letters,num)
commandstr = str(command)
# # send a message at intervals
# if time.time() - prevTime > 1.0:
# sendToArduino("this is a test " + str(count))
# prevTime = time.time()
# count += 1
print (command)
sendToArduino(commandstr)
time.sleep(.2)
#======================================
# End of Python3 code
My arduino code that receives the data is below. I have only included a portion of the code i am trying to get working. The full code is attached as a file You will see portions of the code // out because i tried to get certain portions working before i move on.
void setup()
{
Serial.begin(115200);
// delay(300);
Serial.println("<Arduino is ready>");
IO_init();
}
//==========================
void loop() {
// UART_Control();
recvWithStartEndMarkers();
// replyToPython();
}
//==========================
// Receiving data from Python
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//=====================
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,","); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integerFromPC = atoi(strtokIndx); // convert this part to an integer
}
//============
void showParsedData() {
Serial.print("Message ");
Serial.println(messageFromPC);
Serial.print("Integer ");
Serial.println(integerFromPC);
}
//=========================================
// Below is leftover from old code but you can see what i am trying to do
// Serial.print(receivedChars);
// Direction = receivedChars.substring(0,1);
// Direction = receivedChars.substring(2,1);
// Serial.print("Direction: " + Direction + "\n");
// string_receivedChars = str(receivedChars);
// pwmstr = receivedChars.substring(4,3);
// Serial.print("pwmstr: " + pwmstr + "\n");
// pwmint = (int) pwmstr.toInt();
// Motor_PWM = pwmint;
// Serial.print("pwmstr_x: ");
// Serial.print(pwmint);
// if (Direction == "a") {
// ADVANCE();
// }
// else if (Direction == "z") {
// STOP();
// }
// else if (Direction == "b") {
// RIGHT_1();
// }
// else if (Direction == "c") {
// RIGHT_2();
// }
// else if (Direction == "d") {
// RIGHT_3();
// }
// else if (Direction == "e") {
// BACK();
// }
// else if (Direction == "f") {
// LEFT_3();
// }
// else if (Direction == "g") {
// LEFT_2();
// }
// else if (Direction == "h") {
// LEFT_1();
// }
// else if (Direction == "i") {
// RIGHT_4();
// }
// else if (Direction == "j") {
// LEFT_4();
// }
//
// else {
// Serial.write("invald");
// }
// }
ArduinoSerialPWMBenV3.ino (8 KB)