-2

I am trying to communicate between Arduino Due and Jetson nano through usb serial communication. I want send two separate signals (integer values) from Jetson to Arduino to control a DC motor and servo motor and get their speed and position feedback back to Jetson from Arduino. The value will be greater than 200 ans lesser than 1000.

I have tried sending as bytes but the Arduino is not receiving the data properly when the value is greater than 255. I tried structpack, now I am sending two variables as a single string and at the receiving side of the Arduino I am converting the string back to integers and it is working. I want to know whether this is the only solution for sending integer values greater than 255 ? I tried various suggestions and it didn't work for me. I am attaching my codes:

#python
import serial
import time
import struct
arduino = serial.Serial('/dev/ttyACM0',115200)

time.sleep(1)
while True:
    print('Sending 430180')
    arduino.write(struct.pack('<6s', b'430180')) # 430 is the servo position and 180 is the DC motor speed 
    data = arduino.readline()
    print(data)

    print('Sending 330180')
    arduino.write(struct.pack('<6s', b'330200')) # 330 is the servo position and 200 is the DC motor speed 
    data = arduino.readline()
    print(data)

    time.sleep(5)
    
//Arduino 


String servo,dc;
int servo1,dc1;
String data_in[6];

void setup()

{
Serial.begin(115200);

}

void loop()
{
      
      if(Serial.available() >= 3)
      {
        for (int i = 0; i < 3; i++)
        {
          data_in[i] = Serial.readString();
        }
        servo= data_in[0].substring(0,3);
        dc= data_in[0].substring(3,6);
        servo1 = servo.toInt();
        dc1 = dc.toInt();
        
        while(Serial.available() ==0)
        {
          //setting limits for servo position
          if(servo1>=300 && servo1<=500)
          {
            servo_position = servo1  
          }
          else
          {
            Servo_position = 380     //safer position when the data is garbage value 
          }
          if(dc1>=50)
          {
            //minimum motor speed = 50 (pwm signal) 
            motor_speed = dc1
          }
        }
        
        Serial.println(servo1);   
        Serial.println(dc1); 
     }
  }

Another issue is the python program is not working in a loop. Any help would be appreciated.

  • 3
    Not really sure what you are asking, but I note you are currently sending 6 bytes for 2 readings. As both are under 1,000 they need 10 bits each, so you could pack 2 readings into 3 bytes (i.e. 24 bits), thereby halving the required bandwidth and potentially doubling the data rate. A little simpler, and still only 4 bytes, rather than 6, would be to send 2 unsigned 16-bit values. If you're only sending the readings at 1Hz, it's not worth bothering. – Mark Setchell Mar 01 '23 at 07:42
  • 1
    When you sending data as a string, you need to have some 'delimiter' to separate each data, for example, you are assuming string "430180" representing two numeric numbers, the problem is what if the first numeric is 1000? you won't be able to know where the first numeric end with a string like "1000180", with a delimiter, for example, a ",", you will know which part of the string belong to first numeric and which belong to the second with "1000,180". – hcheung Mar 01 '23 at 08:26
  • @hcheung That is true when the field width is variable, but if the field width is always 3 digits (i.e. 200-999) a delimiter is not strictly necessary. – Mark Setchell Mar 01 '23 at 16:00

1 Answers1

0

I would recommend sending the values as bytes. With two bytes you can send values in the range 0 to 65535. In four bytes you can send both the values.

import serial
import time
import struct

with serial.Serial('/dev/ttyACM0', 115200) as arduino:
    while True:
        data_pkt = struct.pack('<2H', 430, 180)
        print('Sending 430 & 180 as', data_pkt.hex())
        arduino.write(data_pkt)

        data_pkt = struct.pack('<2H', 330, 200)
        print('Sending 330 & 200 as', data_pkt.hex())
        arduino.write(data_pkt)

        time.sleep(5)

Which reported in the terminal:

Sending 430 & 180 as ae01b400
Sending 330 & 200 as 4a01c800

The code I had on the Arduino was:

byte buffer[4];
uint16_t value1;
uint16_t value2;
  
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() {

  while(!Serial.available());
  {
     int size = Serial.readBytes(buffer, 4);
     value1 = buffer[0] | buffer[1] << 8;
     value2 = buffer[2] | buffer[3] << 8;
     Serial.print("Recieved: ");
     for(int i=0; i < size; i++){
       printHex(buffer[i]);
     }
     Serial.println();
     Serial.print("Value1:");
     Serial.println(value1);
     Serial.print("Value2:");
     Serial.println(value2);
     Serial.println();
  }
}

void printHex(uint8_t num) {
  char hexCar[2];

  sprintf(hexCar, "%02X", num);
  Serial.print(hexCar);
}

Which reported the following in the serial monitor:


Recieved: AE01B400
Value1:430
Value2:180

Recieved: 4A01C800
Value1:330
Value2:200
ukBaz
  • 6,985
  • 2
  • 8
  • 31