Search code examples
pythoncarduinoatmega

collecting 'double' type data from arduino


I'm trying to send floating point data from arduino to python.The data is sent as 8 successive bytes of data (size of double) followed by newline character ('\n').How to collect these successive bytes and convert it to proper format at python end (system end)

void USART_transmitdouble(double* d)
{
    union Sharedblock
    {
        char part[sizeof(double)];
        double data;

    }my_block;
    my_block.data = *d;
    for(int i=0;i<sizeof(double);++i)
    {
        USART_send(my_block.part[i]);
    }

    USART_send('\n');
}

int main()
{
    USART_init();
    double dble=5.5;
    while(1)
    {
       USART_transmitdouble(&dble);
    }
    return 0;
}

python code.Sure this wouldn't print the data in proper format but just want to show what i have tried.

import serial,time

my_port = serial.Serial('/dev/tty.usbmodemfa131',19200)
while 1:
    print my_port.readline(),
    time.sleep(0.15)

Update:

my_ser = serial.Serial('/dev/tty.usbmodemfa131',19200)

while 1:
    #a = raw_input('enter a value:')
    #my_ser.write(a)
    data = my_ser.read(5)
    f_data, = struct.unpack('<fx',data)
    print f_data
    #time.sleep(0.5)

Using struct module as shown in the above code is able to print float values. But,

50% of the time,the data is printed correctly.But if I mess with time.sleep() or stop the transmission and restart it,incorrect values are printed out.I guess the wrong set of 4 bytes are being unpacked in this case.Any idea on what we can do here??


Solution

  • On Arduino, a double is the same as float, i.e. a little-endian single-precision floating-point number that occupies 4 bytes of memory. This means that you should read exactly 5 bytes, use the little-endian variant of the f format to unpack it, and ignore the trailing newline with x:

    import struct
    ...
    
    data = my_port.read(5)
    num, = struct.unpack('<fx', data)
    

    Note that you don't want to use readline because any byte of the representation of the floating-point number can be '\n'.

    As Nikklas B. pointed out, you don't even need to bother with the newline at all, just send the 4 bytes and read as many from Python. In that case the format string will be '<f'.