Bidirectional Communication Between Arduino and Python Scripts

Hello,

I am trying to get bidirectional communication between my arduino and python script. Currently the arduino receives inputs from the python script when a user inputs a value. I would like the arduino to send 3 values back when it is not receiving something. These values are floats between 0 and 2Pi (in radians) accurate to the hundredth decimal.

My current method is to multiply these floats by 100 to remove the decimal (they can be divided by 100 on the python side later), convert them to a 10 bit value (leading zeros added if value is less than 10 bits), then concatenate them into a 32 entry long (4 bytes). I was hoping I could just do a Serial.write(buf,len) to send it over, but when I do I get the error

no matching function for call to 'UARTClass::write(volatile long unsigned int [32], int)'

My entire script is quite long, but here are the points of interest for this problem…

#include <math.h>

volatile unsigned long arm_angles_bin[32];
volatile unsigned int q1_remainder = 0;
volatile unsigned int q2_remainder = 0;
volatile unsigned int q0_remainder = 0;
volatile unsigned int q1_for_bit_math;
volatile unsigned int q2_for_bit_math;
volatile unsigned int q0_for_bit_math;
volatile unsigned long q1_as_bits[10];
volatile unsigned long q2_as_bits[10];
volatile unsigned long q0_as_bits[10];

void setup() {
  //Serial stuff
  Serial.begin(baudrate);
  Serial.println("Ready");
}

void loop() {
  while (Serial.available()) {
     //do list of commands
}
if (!Serial.available()) {
    //multiply by 100 to remove decimals
    q1_for_bit_math = q1*100;
    q2_for_bit_math = q2*100;
    q0_for_bit_math = q0*100;

    //Serial.print("q1: ");
    //Serial.println(q1_for_bit_math);
    
    //convert to binary
    for (int i = 0; i < 10; i++) {
      //angle 1
      q1_remainder = q1_for_bit_math % 2;
      q1_for_bit_math = (q1_for_bit_math - q1_remainder) / 2;
      q1_as_bits[i] = q1_remainder;

      //angle 2
      q2_remainder = q2_for_bit_math % 2;
      q2_for_bit_math = (q2_for_bit_math - q2_remainder) / 2;
      q2_as_bits[i] = q2_remainder;

      //angle 3
      q0_remainder = q0_for_bit_math % 2;
      q0_for_bit_math = (q0_for_bit_math - q0_remainder) / 2;
      q0_as_bits[i] = q0_remainder;

      arm_angles_bin[i] = q1_remainder;
      arm_angles_bin[i+10] = q2_remainder;
      arm_angles_bin[i+20] = q0_remainder;
      //Serial.print(q1_as_bits[10-i]);
    }
    //Serial.println("");
    q1_remainder = 0;
    q2_remainder = 0;
    q0_remainder = 0;
    arm_angles_bin[31] = 0;
    arm_angles_bin[30] = 0;

    Serial.write(arm_angles_bin, 32)
}

I have tried adding #include <UARTClass.h> at the top and still receive the same error. Any thoughts on what the issue could be? Also I am not committed to the way I have this written, as long as I can send the 3 floats over from the arduino to the python script and still be able to receive data the other way around, any method will do.

Thank you in advance

The issue is that the AVR Serial classes do not support 32 bit ints which makes sense as the AVR do not support 32bit ints

Mark

Thanks for the quick reply! Is there any other way you recommend I could send these values?

byte by byte

Mark

Use a union with a 32 element unsigned long array and a 128 element byte array. Create an instance of the union, populate the 32 unsigned longs in the array, and send the 128 bytes of the byte array.

This looks similar to using a struct (which also did not work unfortunately -.-). Maybe I am misunderstanding how to use a union, but what is the purpose of the 128 element byte array if the values are stored in the long array?

This Python Binary Data demo uses a union to organize data for sending/receiving. It may give you some ideas.

...R

p3jawors: This looks similar to using a struct (which also did not work unfortunately -.-). Maybe I am misunderstanding how to use a union, but what is the purpose of the 128 element byte array if the values are stored in the long array?

All of the things defined in a union share the same memory. Storing data in a long is easy. Storing data in 4 bytes that make up a long is not.

Sending an array of bytes is easy. Sending an array of longs is not.

By making the long array and the byte array share the same memory, you get the advantage of easily writing to the long array and the advantage of easily sending the byte array, with no disadvantages.

Thanks, that makes sense. Looking at this approach, would I be able to do the multiplication by 100 to make the three floats I want to send into three ints between 0-628, then make the union between 3 ints and a 32 element byte array? Would I not be converting to binary twice otherwise?

Would I not be converting to binary twice otherwise?

The Arduino only understands binary. There is no “conversion” involved.

So does that mean I can keep my three values as integers and have the union with the byte array? At the moment I am converting my three integers into binary and storing them concatenated in a long.

p3jawors: So does that mean I can keep my three values as integers ...

Did you study the demo I linked to in Reply #6?

...R

At the moment I am converting my three integers into binary and storing them concatenated in a long.

I have no idea what you mean by "converting my three integers into binary". I have no idea how you think you can store 6 bytes in a 4 byte long.

My apologies, I had something come up and had to put this on hold. @ Robin2 thank you for the demo! I have a question in regards to the start / end markers on the python side. Why are they set to 60 and 62, respectively, while the arduino sends chevrons (’<’ and ‘>’)?

Why are they set to 60 and 62, respectively, while the arduino sends chevrons (’<’ and ‘>’)?

http://www.asciitable.com/

Hi
By chance, I just saw this thread.
I wrote an arduino library and a python module for bi directionnal communication :
https://github.com/Tahitibob35/SerialComm
Actually, You can only send integers and char arrays.
But it is easy to add other types supports.
David.

p3jawors:
Why are they set to 60 and 62, respectively, while the arduino sends chevrons (’<’ and ‘>’)?

60 and 62 are the ascii codes for the chevrons.

…R

Thank you for all of the help! Turns out I was having a timeout issue where the ord(x) was reading a string of length zero. Changed the timeout and it works fine now.

Thanks again!