Is 2 way communication with PC via serial possible [UNO]?

I have a arduino and a python application. I was hoping to send some data from the python app trough the USB connection (via pyserial) to the arduino. Do some work with the arduino (motors etc) and then when done send data back to the python app. Every guide on the subject matter only handles 1 way communication, either pc to arduino or arduino to pc. When i try to run the pyserial script while the arduino is running i get the “COM3 allready in use”. I was wondering is 2 way communication possible at all this way? Am I missing something here? Is there a alternative?

1 Like

Not only is 2-way communication possible, it is normal.

Have a look at this Simple Python - Arduino demo

The Python code should work on Windows if you edit it to use the Windows style of COM ports.

Make sure that your Python program keeps the serial port open until it is completely finished with the Arduino.

…R

yes I am using Processing

blackwolf23:
I was wondering is 2 way communication possible at all this way? Am I missing something here? Is there a alternative?

Yes, but note that normal USB is only half-duplex. This means you can have 2-way communication as long as only one of the two devices are transmitting at any given time.

Also be aware that you can use the compatible libraries: pySerialTransfer and SerialTransfer.h for fast and reliable serial communication between your Arduino and Python.

pySerialTransfer is pip-installable and cross-platform compatible. SerialTransfer.h runs on the Arduino platform and can be installed through the Arduino IDE’s Libraries Manager.

Both of these libraries have highly efficient and robust packetizing/parsing algorithms with easy to use APIs.

Example Python Script:

import time
from pySerialTransfer import pySerialTransfer as txfer


if __name__ == '__main__':
    try:
        link = txfer.SerialTransfer('COM17')
        
        link.open()
        time.sleep(2) # allow some time for the Arduino to completely reset
        
        while True:
            send_size = 0
            
            ###################################################################
            # Send a list
            ###################################################################
            list_ = [1, 3]
            list_size = link.tx_obj(list_)
            send_size += list_size
            
            ###################################################################
            # Send a string
            ###################################################################
            str_ = 'hello'
            str_size = link.tx_obj(str_, send_size) - send_size
            send_size += str_size
            
            ###################################################################
            # Send a float
            ###################################################################
            float_ = 5.234
            float_size = link.tx_obj(float_, send_size) - send_size
            send_size += float_size
            
            ###################################################################
            # Transmit all the data to send in a single packet
            ###################################################################
            link.send(send_size)
            
            ###################################################################
            # Wait for a response and report any errors while receiving packets
            ###################################################################
            while not link.available():
                if link.status < 0:
                    if link.status == -1:
                        print('ERROR: CRC_ERROR')
                    elif link.status == -2:
                        print('ERROR: PAYLOAD_ERROR')
                    elif link.status == -3:
                        print('ERROR: STOP_BYTE_ERROR')
            
            ###################################################################
            # Parse response list
            ###################################################################
            rec_list_  = link.rx_obj(obj_type=type(list_),
                                     obj_byte_size=list_size,
                                     list_format='i')
            
            ###################################################################
            # Parse response string
            ###################################################################
            rec_str_   = link.rx_obj(obj_type=type(str_),
                                     obj_byte_size=str_size,
                                     start_pos=list_size)
            
            ###################################################################
            # Parse response float
            ###################################################################
            rec_float_ = link.rx_obj(obj_type=type(float_),
                                     obj_byte_size=float_size,
                                     start_pos=(list_size + str_size))
            
            ###################################################################
            # Display the received data
            ###################################################################
            print('SENT: {} {} {}'.format(list_, str_, float_))
            print('RCVD: {} {} {}'.format(rec_list_, rec_str_, rec_float_))
            print(' ')
    
    except KeyboardInterrupt:
        link.close()
    
    except:
        import traceback
        traceback.print_exc()
        
        link.close()

Example Arduino Sketch:

#include "SerialTransfer.h"


SerialTransfer myTransfer;


void setup()
{
  Serial.begin(115200);
  myTransfer.begin(Serial);
}


void loop()
{
  if(myTransfer.available())
  {
    // send all received data back to Python
    for(uint16_t i=0; i < myTransfer.bytesRead; i++)
      myTransfer.txBuff[i] = myTransfer.rxBuff[i];
    
    myTransfer.sendData(myTransfer.bytesRead);
  }
}

On the Arduino side, you can use myTransfer.txObj() and myTransfer.rxObj() to copy values to the library’s RX buffer and parse multi-byte variables out of the library’s TX buffer.

For theory behind robust serial communication, check out the tutorials Serial Input Basics and Serial Input Advanced.

1 Like

When i try to run the pyserial script while the arduino is running i get the "COM3 allready in use".

Not quite sure if I understand this. But only one application on a PC can access a serial port at a time. So if you have serial monitor open, you're python script can't access the port.

Opening the same port inside the application multiple times will also fail unless you close in between.

Robin2:
Not only is 2-way communication possible, it is normal.

Have a look at this Simple Python - Arduino demo

The Python code should work on Windows if you edit it to use the Windows style of COM ports.

Make sure that your Python program keeps the serial port open until it is completely finished with the Arduino.

...R

Yeah I fixed it following your guides. Had serial monitor running at the same time making the channel busy and lacking decoding. Thank you