0

I'm trying to send numerical data from inertial sensors from my Arduino to a Python script via serial (PySerial). I found that if I continuously send the data from the Arduino without stopping, the serial buffer fills up quickly and the sensor measurements that the Python reads becomes delayed.

To fix this, I thought of having the Python script send over a transmit command to the Arduino when it needs data. I'm sending a char 't' to signify this command, but the delay between Python sending the command and the Arduino sending the data is too large.

I'm wondering if there's a 'proper' way of doing this, as I'm sure it's probably been done before?

  • 3
    You should be able to get an instantaneous response to your commands. You must be doing something wrong in your code. – Majenko Aug 4 at 22:15
  • 1
    You're not trying to use readString on the Arduino to read one character from python are you? – Delta_G Aug 4 at 23:55
  • ok, thinking about what you said ... it makes makes perfect sense to learn how to use a transmit command ... but it makes no sense to actually use it ... if the buffer overflows on Python side, then it will overflow on Arduino side if you pause comms .... does it really matter if some of the readings are lost? ... if lost data is not an issue, then frame data packets and simply ignore incomplete packets when they arrive on Python side – jsotola Aug 5 at 1:13
  • I'm reading strings on both sides Python and Arduino. I can't let the Arduino's output buffer overflow, because the buffer doesn't clear until I read from it on the Python side. I need the most recent sensor values (gyro, accel IMU), so if I let the buffer overflow and start reading from it, I'll get sensor data that is a few cycles old. – ejk Aug 5 at 3:01
  • I'm wondering if it's possible that the baud rate I'm using is too high (19200-115200) for the IMU sensor? Maybe I'm reading data faster than the sensor can provide? – ejk Aug 5 at 3:59
1

This is not a complete answer to your problem, but currently you seem to have some misconceptions, that prevent you from pin pointing the actual problem.

The data transmission from the sensor, over the Arduino to your python script on the PC has multiple places, where a bottleneck can appear. The total data rate will then be at maximum as large, as the smallest bottleneck allows it to be.

First you have a potential bottleneck in the communication between sensor and Arduino. You haven't stated, what kind of IMU chip you have and how it communicates. Typical IMU chips like the MPU series are interfaces via I2C or SPI. SPI can be sped up rather greatly, while I2C is not that easy to speed up. But it depends greatly on the capabilities of the used chip. You can find information about that in the corresponding datasheet of the chip.


The next interface is the Serial (UART) interface between Arduino and PC. This interface has a fixed baudrate. When you use Serial.write() or its siblings, you simply fill the send buffer of the Serial library. The data will then be send out automatically at the correct timing for your baudrate. The transmission always happens, if the python script is reading or not. The transmission also happens, when the serial buffer of the script is full. The Arduino does not know about the buffer being full. So in this case the data is not delayed, but lost.


The last - and probably most important - potential bottleneck is how you read and send the data on Arduino and in the python script. Here I'm covering the Arduino side.

You should not use functions like Serial.readString(), as they work with a timeout, which will slow down your code drastically. Instead you should read the Serial data byte by byte into a buffer, delimiting your message with a special character (for example the newline character \n). You check, if there is any data Serial.available(), and if yes, you read one byte into a char array, which is your own buffer. You are doing that repeatedly, until you read the delimiting character. Then you process the complete message. That way will give you some important improvements:

  • You can do things in the meantime (for example reading new data from your sensor)
  • It works without any arbitrary timeout, thus not slowing down your code unnecessaryly
  • The delimiting character frames a full message, so that you can distinguish two different messages from each other and thus easier process them

Considering the above, you should make the requirements clearer:

  • How much latency between the actual sensor measurements and the receiving in the python script is ok for you, meaning: How old can the measurements be, that the python script gets? (You just stated, that it is too large, but you have not mentioned how large)

  • Do you need continuous data transmission, or just one or a few sets of the IMU data?

Then you can check for the needed speed and data rate. Check, if all involved interfaces and codes can really handle your requirements.

Also it would be easier for us to help you, when you show your current code in your question.

| improve this answer | |
  • 1
    Note that for single character commands you do not need message framing and buffering. – Edgar Bonet Aug 5 at 8:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.