Closed masoudir closed 3 years ago
In short, we've never tested on Foxy; the last time I looked at this was in Dashing days. However, see #79 which should make it compile on Foxy.
This was fixed by #79, so closing.
Hi @masoudir . I wonder that you can build the ros2_serial_example package or not? I got the error when building it. thank.
Hi @huak95 , I am not sure, as I remember I have built it in foxy using the help of #79. But that was a couple of months ago and I do not remember it exactly.
But you can simply use the uros arduino library to transfer your messages easily. I have not used ros2_serial_example repo. link.
@masoudir I have Arduino mega 2560 board that is not support for that micro-ROS for Arduino library. So, what should I need to do for using ROS2 with Arduino.
I have used uros library for other not supported microcontrollers, using the static library using this link. But that is a little complicated for absolute beginners. But if you was successful for building that static library, you can use it for your project. But remember that this static library can be used in a project with similar configuration as you have used for Cmake in building uros.
I have done that for STM32G474 arduino framework using Platformio IDE.
I recommend you to search another git issue to find your exact solution, or if there are not any issues related to your problem, create a new one for this repo.
Sorry, I did not work with AVR for uros libraries and I have not the exact solution for you.
@huak95 I'm also looking for a ros2 library to use serial and I don't find any that are satisfying and lightweight enough. I think it'll be easier to make your own ros2 node that receive the messages for the arduino, read the message and send the useful data to the arduino using serial (like pyserial) , and vice versa in the other side. If you're beggining, learn to communicate in serial between your computer and arduino, then learn how to make a basic ros2 node and then combine the two!
@jonathanTIE I have try create new node with PySerial to received Serial.print from arduino but it's working very slow. If I send the spin message faster than 1 second the arduino mega can't received the serial data from PySerial.
Here is my code for Arduino
// check if data is available
if (Serial.available() > 0) {
// read the incoming string:
incomingString = Serial.readString();
}
int str_len = incomingString.length() + 1;
char char_array[str_len];
incomingString.toCharArray(char_array, str_len);
pch = strtok(char_array,",");
Serial.print("cmd_vel:");
int i = 0;
while(pch != NULL)
{
cmd_vel[i] = String(pch).toDouble();
Serial.print(" ");
Serial.print(cmd_vel[i]);
pch = strtok(NULL, ",");
i = i+1;
}
Serial.println("");
Here is my code for PySerial and ROS2
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
import serial
import time
ser = serial.Serial('/dev/ttyUSB1', 115200, timeout=0.1)
r = 1
class Connect_Arduino_Node(Node):
def __init__(self):
super().__init__("Connect_Arduino_Node")
self.counter_ = 0
self.get_logger().info("Hello ROS2")
# self.create_timer(0.5, self.arduino_callback) # this can't work
self.create_timer(0.1, self.arduino_callback) # this can work
def arduino_callback(self):
vel_x = -3.0
vel_th = 0.0
self.value_ = self.write_read(vel_x, vel_th)
self.get_logger().info("read "+str(self.value_))
def write_read(self, vel_x, vel_th):
global r, ser
print("I am writing!" + " vel_x:" + str(vel_x) + " vel_th:" + str(vel_th))
x = str(r * vel_x) +","+ str(vel_th) +"\n"
ser.write(bytes(x,'utf-8'))
time.sleep(0.02)
data = ser.readline()
txt = str(data).split(",")
r = r * -1
return (txt[1:])
I don't know how to make it a better ROS2 communication with Arduino. May I code something wrong. Please help. Thank you.
@huak95
The first parameter of self.create_timer is the interval between every call, so if 0.1 work fast enough, 0.5 should work too.
The problem is on the arduino side, the function Serial.readString()
, if you don't set the Serial.setTimeout()
, waits by default for 1s before executing the code. The readString
waits like a sleep(1)
.
The same problem on the pyserial side is present, the timeout is too high on the ser
, it waits 0.1 s when you read the serial, so you can't read more than 10 times per second.
So for the arduino side, you can reduce the timeout, but personally I prefer to read the serial port using read
, to avoid hanging the program for a few ms everytime, like so :
char buffer[50];
int buff_index=0;
void update() {
int a;
a = SerialCtrl.available();
if (a) {
for (int k=0;k<a;k++) {
char c=SerialCtrl.read();
//serialCtrl.write(c);
if (c=='\n'){
buffer[buff_index]='\0';
parse_data(); //function that will read the buffer variable
buff_index=0;
}
else if (c=='\r') {}
else {
buffer[buff_index]=c;
buff_index++;
}
}
}
It's unrelated with the issue, if you want you can contact me by mail or by discord if you have other questions !
On top of what is already said, the Arduino code makes a bad assumption. It assumes that if any serial data is available then the entire line of text is available. Statistically this assumption will be true much of the time but not always.
What if you check for data just after the first character of the line is written? This will happen one in athousand times and then the system stops working What if on poer up the Arduino stars after the line is half written?
The correct solution is to accumulate characters one at a time until the "/n" is found. An improved solution uses a "start" character, perhaps a "$" at the start of each line, then you reader waits until it reads a "$". Even better is to place a checksum in the line and ignore lines that have a wrong checksum.
So, on the arduino.. waitfor data to be available, if so read a character. Is the character s "$"? If not ignore the data.
Finally we see a start sign "$", so now we read until we see "/n"
Process the line, including the checksum, if the checksum is bad ignore the line if OK then save the data.
One other idea, reading charagters and convertingthem to floating point is expensive on an arduino. Why not send them as binary data?
On Thu, Aug 19, 2021 at 5:23 AM jonathanTIE @.***> wrote:
@huak95 https://github.com/huak95
The first parameter of self.create_timer is the interval between every call, so if 0.1 work fast enough, 0.5 should work too. The problem is on the arduino side, the function Serial.readString(), if you don't set the Serial.setTimeout(), waits by default for 1s before executing the code. The readString waits like a sleep(1). The same problem on the pyserial side is present, the timeout is too high on the ser, it waits 0.1 s when you read the serial, so you can't read more than 10 times per second. So for the arduino side, you can reduce the timeout, but personally I prefer to read the serial port using read, to avoid hanging the program for a few ms everytime, like so :
char buffer[50]; int buff_index=0; void update() { int a; a = SerialCtrl.available();
if (a) { for (int k=0;k<a;k++) { char c=SerialCtrl.read(); //serialCtrl.write(c); if (c=='\n'){ buffer[buff_index]='\0'; parse_data(); //function that will read the buffer variable buff_index=0; } else if (c=='\r') {} else { buffer[buff_index]=c; buff_index++; } } }
It's unrelated with the issue, if you want you can contact me by mail or by discord if you have other questions !
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/osrf/ros2_serial_example/issues/78#issuecomment-901870294, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABQKNRUO73WIIUU7EEAZS5TT5TZUFANCNFSM4YLPBCIQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .
--
Chris Albertson Redondo Beach, California
Problem
I am trying to build ros2_serial bridge you provided with ros2 foxy. But it does not build for any packages like std_msgs, geometry_msgs , ... What is the problem?
Error log