How can I a python list send to Arduino, and convert Ardunino array?

Dear community,

I can a python list send to Arduino, and I use here array type. This is min. 10 element.
I test the pySerialTransfer modul, and I don't find good documentation, or tutorial (just a github source). Just the example works, and it's not good for me
I'm open all new solutions.

Thanks.

Sorry, my English is not perfect, because I'm a young student.

The author of the pySerialTransfer library, @PowerBroker, is a regular contributor here. Hopefully he will come to your aid.

I have not use that library myself.

If it was my project I would almost certainly always send the same size of array, even if some elements were just zero. I would create an array on the Arduino of the appropriate size and use code like this demo receive the data.

int myArray[10];
byte* ddata = reinterpret_cast<byte*>(&myArray); // pointer for transferData()
pcDataLen = sizeof(myArray);

void setup() {
    // usual stuff
}

void loop() {
    checkForNewData();
    if (newData == true) {
        // code to use the data
        newData = false;
    }

void checkForNewData () {
    if (Serial.available >= pcDataLen and newData = false) {
        byte inByte;
        for (byte n = 0; n < pcDataLen; n++) {
            inByte = Serial.read();
            *(ddata + n) = inByte;
        }
        newData = true;
    }
}

You will need to use the Python function struct.pack() to make sure that the Python data is in a format that is recognizable by the Arduino.

This code is adapted from some code that is working in one of my Python-Arduino projects but I have not tested the code I have posted here

…R

Thanks Robin!

I test this code, and (after some edit) it’s work!
But I have a problem:
send data=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
arduino recived data: 02030405060708090100110120130140001 . {0,2,0,3…0,11,0,12…}
Every second element are a 0, and the first 2 sended intiger will be at the end. And I don’t know, why.

Here is the edited arduino code:

int myArray[30];
byte* ddata = reinterpret_cast<byte*>(&myArray); // pointer for transferData()
size_t pcDataLen = sizeof(myArray);
bool newData=false;

void setup() {
    Serial.begin(115200);//baudrate
}

void loop() {
    checkForNewData();
    if (newData == true) {
      for (int i; i<30;i++){
        Serial.print("The list  ");
        Serial.print(i);Serial.print(". element:   ");
        Serial.println(myArray[i]);
      }
      Serial.println();//print a \n and \r character 
        newData = false;
    }
    }

void checkForNewData () {
    if (Serial.available() >= pcDataLen && newData == false) {
        byte inByte;
        for (byte n = 0; n < pcDataLen; n++) {
            inByte = Serial.read();
            *(ddata + n) = inByte;
        }
        newData = true;
    }
}

And here is a python example code:

import serial
from struct import * 
import sys


try:
    ser=serial.Serial(baudrate='115200', timeout=.1, port='com8')    #set your port!!!
except:
    print('Port open error')


while True:
    try:
        ser.write(pack ('15l',0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))#the 15l is 15 element, and l char is a long type data
        print(str(ser.readline())) #data is bytes type (b'')
    except KeyboardInterrupt:
        break
    except:
        print(str(sys.exc_info())) #print error
        break
*(ddata + n) = inByte;

Most people would simply writeddata [n] = inByte;Or even ddata [n] = Serial.read(); and skip the inByte stuff.

Does the machine sending 16-bit values use the same byte order as the machine receiving the 16-bit values? If not, each 'int' will have its bytes reversed. Hard to tell when you display them all mashed together.

It looks like you are sending 'long' (32-bit?) values and saving them as 'int' (16-bit) values. The upper half of each 32-bit value is likely to be zero. If you receive them as 32-bit values they may display without the extra zeros. Try changing "int myArray" to "long myArray".

domker:
And here is a python example code:

You are using the wrong PACK character. 'l' is the equivalent of an Arduino long. You need to use 'h' to match an Arduino int.

...R

TheMemberFormerlyKnownAsAWOL:
Most people would simply write

ddata [n] = inByte;

Thanks. I will look at that.

I have said it before that I find the C++ pointer notation extremely confusing.

...R

Thanks all.

johnwasser:
Does the machine sending 16-bit values use the same byte order as the machine receiving the 16-bit values? If not, each ‘int’ will have its bytes reversed. Hard to tell when you display them all mashed together.

I don’t know what is the order. How can I this set?

I correct the data type problem, and the byte addition. 0 arrive not, but the order is false (2,3,4,5…12,0,1). This is the small problem. But the last 4 intiger is disturbed, and I don’t know why. (I test 15 number sending)

domker:
I correct the data type problem, and the byte addition. 0 arrive not, but the order is false (2,3,4,5...12,0,1). This is the small problem. But the last 4 intiger is disturbed, and I don't know why. (I test 15 number sending)

Please post the latest versions of your programs so we can see what you are working with.

...R

TheMemberFormerlyKnownAsAWOL:

*(ddata + n) = inByte;

Most people would simply writeddata [n] = inByte;

I have had a think about this.

Your version compiles in my program and I assume it works, but I have not had a chance to run the program.

However when I got to thinking about it I came to the conclusion that (for me, at least) the style

*(ddata + n) = inByte;

is a lot less confusing.

I have created a variable that holds the address of the start of the struct and I am writing data to successive addresses.

The style

ddata [n] = inByte;

is what I use for arrays and I have not created an array.

Of course if you have a simpler alternative to this gobbledygook it would be a help

byte* ddata = reinterpret_cast<byte*>(&myArray);

…R

Here is the full code:

Python:

import serial
from struct import *
import sys


try:
    ser=serial.Serial(baudrate='115200', timeout=.1, port='com8')
except:
    print('Port open error')


while True:
    try:
        ser.write(pack ('15h',0,1,2,3,4,5,6,7,8,9,10,11,12,13,14))#the 15h is 15 element, and h is an int type data
        dat=ser.readline()
        if dat!=b''and dat!=b'\r\n':
            print(str(dat)) #data is bytes type (b'')
    except KeyboardInterrupt:
        break
    except:
        print(str(sys.exc_info())) #print error
        break

Arduino:

int myArray[15];
byte* ddata = reinterpret_cast<byte*>(&myArray); // pointer for transferData()
size_t pcDataLen = sizeof(myArray);
bool newData=false;

void setup() {
    Serial.begin(115200);//baudrate
}

void loop() {
    checkForNewData();
    if (newData == true) {
      for (int i; i<30;i++){
        Serial.print("The list  ");
        Serial.print(i);
        Serial.print(". element:   ");
        Serial.println(myArray[i]);
      }
      Serial.println();//print a \n and \r character 
        newData = false;
    }
    }

void checkForNewData () {
    if (Serial.available() >= pcDataLen && newData == false) {
        byte inByte;
        for (byte n = 0; n < pcDataLen; n++) {
            ddata [n] = Serial.read();
        }
        newData = true;
    }
}

Thanks!

for (int i; i<30;i++){ Oops

You are genius 8)!

But the order not still good.
My recived data (my python code output):

b'The list  0. element:   3\r\n'
b'The list  1. element:   4\r\n'
b'The list  2. element:   5\r\n'
b'The list  3. element:   6\r\n'
b'The list  4. element:   7\r\n'
b'The list  5. element:   8\r\n'
b'The list  6. element:   9\r\n'
b'The list  7. element:   10\r\n'
b'The list  8. element:   11\r\n'
b'The list  9. element:   12\r\n'
b'The list  10. element:   13\r\n'
b'The list  11. element:   14\r\n'
b'The list  12. element:   0\r\n'
b'The list  13. element:   1\r\n'
b'The list  14. element:   2\r\n'

I think the problem is that your Arduino input has the values 3 to 14 from one message and 0 to 2 from the next message.

How is your Arduino program supposed to know where a message starts?

Try putting a delay in your Python program so it only sends a message once per second and add some code into your Arduino program so it dumps any characters that may still be in the Serial Input Buffer after it has read the 30 bytes - perhaps like this

void checkForNewData () {
    if (Serial.available() >= pcDataLen && newData == false) {
        byte inByte;
        for (byte n = 0; n < pcDataLen; n++) {
            ddata [n] = Serial.read();
        }
        while (Serial.available > 0) { // now make sure there is no other data in the buffer
             byte dumpByte =  Serial.read();
        }
        newData = true;
    }
}

A better system would be for the Python program only to send data when it receives a request from the Arduino.

And another thing. Your Python program should wait for a few seconds (maybe 5 secs) after it opens the Serial port before it starts sending data. This is to allow the Arduino time to reset.

…R

Thanks all! I solve this problem (with yours help), I can array data send for arduino, and arduino data read in python (list type).

Here is the good code, for more persons.
Python (3.8) :

#Arduino forum 2020 - https://forum.arduino.cc/index.php?topic=714968 
import serial
from struct import *
import sys
import time
import random
import ast


try:
    ser=serial.Serial(baudrate='115200', timeout=.5, port='com8')
except:
    print('Port open error')

time.sleep(5)#no delete!
while True:
    try:
        ser.write(pack ('15h',0,1,2,3,4,666,6,7,444,9,10,2222,12,13,random.randint(0,100)))#the 15h is 15 element, and h is an int type data
                                                                    #random test, that whether data is updated
        time.sleep(.01)#delay
        dat=ser.readline()#read a line data
        
        if dat!=b''and dat!=b'\r\n':
            try:                #convert in list type the readed data
                dats=str(dat)
                dat1=dats.replace("b","")
                dat2=dat1.replace("'",'')
                dat3=dat2[:-4]
                list_=ast.literal_eval(dat3) #list_ value can you use in program
                print(dat3)
            except:
                print('Error in corvert, readed: ', dats)
        time.sleep(.05)
    except KeyboardInterrupt:
        break
    except:
        print(str(sys.exc_info())) #print error
        break

#the delays need, that the bytes are good order

And the Arduino program:

//Arduino forum 2020 - https://forum.arduino.cc/index.php?topic=714968


int myArray[15]; //this value is the upgratable data
byte* ddata = reinterpret_cast<byte*>(&myArray); // pointer for transferData()
size_t pcDataLen = sizeof(myArray);
bool newData=false;

void setup() {
    Serial.begin(115200);//baudrate
}

void loop() {
    checkForNewData();
    if (newData == true) {
        newData = false;
    }
    toPy(myArray[0],myArray[1],myArray[2],myArray[3],myArray[4],myArray[5],myArray[6],myArray[7],myArray[8],
    myArray[9],myArray[10],myArray[11],myArray[12],myArray[13],myArray[14],0,0,0,random(100)); //here write the send data
    }

void checkForNewData () {
    if (Serial.available() >= pcDataLen && newData == false) {
        byte inByte;
        for (byte n = 0; n < pcDataLen; n++) {
            ddata [n] = Serial.read();
        }
        while (Serial.available() > 0) { // now make sure there is no other data in the buffer
             byte dumpByte =  Serial.read();
             Serial.println(dumpByte);
        }
        newData = true;
    }
}


void toPy(int a,int b,int c,int d,int e,int f,
          int g,int h,int i,int j,int k,int l,
          int m,int n,int o,int p,int q,int r,int s)//19 datas
{
  //rpidata="[1,2,3,4,5,6,7,8,9,10,111,0]";
String data="["+String(a)+","+String(b)+","+String(c)+","+String(d)+","+String(e)+","+String(f)+","+String(g)+","+String(h)+","+String(i)+","+
String(j)+","+String(k)+","+String(l)+","+String(m)+","+String(n)+","+String(o)+","+String(p)+","+String(q)+","+String(r)+","+String(s)+"]";
  delay(50);Serial.println(data);
}

Thanks all! I’m thankful!

Search tag:
Serial, arduino to python, python to arduino, send array arduino, send list python arduino