When reading serial data between Arduino and a node, it hangs. How can I properly send and read data?
Hi. I'm using ROS2 foxy with no libraries installed. It runs on an Ubuntu 21.04 x64 machine with kernel 5.8.0-59-generic.
I created a project with the goal of controlling an Arduino using python serial in a workspace with the following structure:
- workspace
- src
- arduino_comm
- serial_server.py
- serial_client.py
- motor_interface
- other_interface
the motor interface provides the action that is used by the arduino_comm package to send serial data. I have an old Arduino Nano that I've had for like 7 years ago that uses the old legacy bootloader. Still operational but sadly seems incompatible with the rosserial and I've checked the Micro-Ros packages and they also seem incompatible with my old arduino. Also I wanted to understand the code I'm working with at its bare basics before adding more complexity with an external library.
So I created the following code.
Arduino code
//Variable to store the bot command.
String botCommand;
void setup() {
//Initialize Serial port.
Serial.begin(9600);
//Initialize BUILTIN LED to light up for feedback.
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if(Serial.available()){
botCommand = Serial.readString();
if(botCommand == "forward"){
//Light up the led.
digitalWrite(LED_BUILTIN, HIGH);
delay(10);
}
Serial.println(botCommand);
}
//Shut down the LED.
digitalWrite(LED_BUILTIN, LOW);
delay(10);
}
The Server and Client use the following action, which is based on the tutorial
##################################################
#Action that sends robot towards a specific spatial position.
##################################################
#Goal of achieving a specific position.
int32 botgoalposition
---
#Resulting position that we're aiming to attain.
int32[] botendposition
---
#Feedback message about current position.
int32[] botcurrposition
The arduino_comm serial_server.py dedicated to sending commands to the Arduino to follow.
import time
#Import the Serial library to send commands to Arduino.
import serial
#Elements required to generate an ActionServer.
import rclpy
from rclpy.action import ActionServer
#Library required to generate a ROS2 Node.
from rclpy.node import Node
##################################################
# ACTIONS
##################################################
#Action to calculate Fibonacci code. FOR DEBUGGING.
from code_interfaces.action import Fibonacci
#Action to send commands to the Arduino until it reaches the desired coordinates.
from bot_move.action import BotMove
#Class that encapsulates the Action Server.
class SerialCommServer(Node):
def __init__(self):
#Declare the Node with the name "serial server".
super().__init__('serial_server')
#Declare it'll be an ActionServer that publishes to the topic 'botmove'.
self._action_server = ActionServer(
self,
BotMove,
#Action name.
'botmove',
#Callback for executing accepted goals.
self.executeCallback
)
#When it has been initialized, it'll start executing the following callback.
def executeCallback(self, goalHandle):
#Set the logger to indicate we're starting to execute our goal.
self.get_logger().info('Executing goal...')
#Get feedback to see if we're close to our goal.
feedbackMsg = BotMove.Feedback()
feedbackMsg.botcurrposition = [0,1]
goalHandle.publish_feedback(feedbackMsg)
#Send a small Hello to Arduino.
arduino = serial.Serial(port="/dev/ttyUSB0")
for i in range(1, 10):
arduino.write(bytes(str("forward"), 'utf-8'))
feedbackMsg.botcurrposition.append(i)
self.get_logger().info('Feedback: {0}'.format(i))
#Read back response from the Arduino.
#TODO: THIS SECTION HANGS, NEED TO FIGURE HOW TO FIX IT.
# response = arduino.readline()
# print("Response: " + str(response ...
Can you please, upload your action file also.
Done! Added the action, its based on the tutorial so I haven't modified much because I'm scared of screwing up the data type, I assume I'll have to change it to an array of only 2 or 3 elements representing the x,y,z coordinates I want the robot to take.
But first gotta solve the serial issue.