Softwareserial timing considerations

Not quite a newb, but I'm learning as I go, and this is getting into unfamiliar territory...

My project is a multicopter flight controller. I have gotten to the point, that it is taking so long to read from the various I2C devices, that I am exceeding my 4 millisecond cycle time (250Hz) including 2ms for doing all of the calculations and sending the esc pulses. On top of that, I am adding a GPS, which is strictly serial.

I decided to split the duties between an Uno (for handling the RX inputs, calculating PID's, sending motor control signals, etc.) and a Pro Mini for reading the Gyro, Accel, Mag, Pressure, GPS, etc., data over serial and I2C.

The Pro Mini is reading data in from an Adafruit 10DOF board, via I2C and a 28 byte block of UBLOX protocol from a Neo 6M GPS, over serial. In the future, I hope to add inputs from sonic sensors.

I have the code written to read all of the sensors and I'm working on keeping the cycle time well under the maximum 4ms (even with Serial.prints in the loop, as I get setup). But, I have found that, whether I am reading data from the GPS, or not, the SoftwareSerial serial.begin(9600) consumes about 10 cycles, every 100ms (10Hz), which corresponds to the refresh rate of the GPS. The GPS data is 28 bytes read in with a while ( Serial.available() ).

  1. Are there ways to shorten this enormous pause, to read 28 bytes of data?
  2. If not, it seems the best alternative is to read the gyro and accelerometer at 250 Hz, directly with the UNO and leave the rest of the reading to the Pro Mini. How do I ensure that the Uno and Pro Mini are able to play nice, as they are both reading from the same I2C wires? And, how do I do all of this in a way that the Uno is able to read the Gyro/Accel and read the data from the Pro Mini as fast as possible?
  1. Are there ways to shorten this enormous pause, to read 28 bytes of data?

Use a higher Baud rate. However, Softwareserial doesn't work at over 38400 Baud, and maybe not even that. If you can, use the hardware serial port to read the GPS at a much higher Baud rate.

Also, there are several alternatives to Softwareserial and most perform better.

Use Arduino Micros which have a spare hardware serial port.

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data.


there are several alternatives to Softwareserial NeoSWSerial. SoftwareSerial is really awful for what you're doing, because it blocks interrupts for an entire character time, recevied or sent. At 9600, that's 1ms per char. :stuck_out_tongue: NeoSWSerial does not block on receive, and can work at 9600, 19200 and 38400.

Of course, I must also mention my GPS library, NeoGPS. It is smaller and faster than all other libraries, and can be configured to parse only the fields and messages that you really use.

You can also use NeoGPS with the Neo--Serial libraries to handle serial data during the RX interrupt (see the NMEA_isr.ino or NMEASDlog.ino examples). This can guarantee rock-solid GPS receipt, even if your sketch is busy doing other things. The ublox-specific example actually requires the ISR version, and can also accommodate the GPS/UTC leap seconds difference and the ms Time-of-week conversion to UTC.

I would also suggest reading the NeoGPS Troubleshooting page, as it describes common timing problems... and their solutions. :smiley:


Thanks to all for the responses!
I've ditched software serial and connected to the hardware serial at pins 0 and 1. It's a pain to unplug during every sketch upload, but once I have the code stabilized, that shouldn't be a problem. I measured the time it takes to read and it is down to a nice 368us, (at 9600 baud).

I may play around with the baud setting at some point, but for now, I am turning my attention to preparing the data packet for transmission to the Uno, via I2C. Can anyone point me to a tutorial, or good description of doing a Master Reader communication with large/complex data sets? It's one thing to transmit "Hello ". I suspect I'm looking at somehow loading a series of registers with bits, reading them and reconstructing with bitshift operations, as I've been doing with my I2C devices. Or, is it completely different between Arduino devices?

Does the Micro truly have a second serial port (I don't see that mentioned in the literature)? Or are you referencing the USB? A Micro may be overkill for this project with its pin count, but I would keep it in mind for future, if it means not having to unplug a device to free up the RX/TX for sketch loading.

Thank you /dev, I will have a look at those.


The Micro does not use pins 0 and 1 for USB communication and they are available as Serial1 for other communication. The Micro is a small Leonardo.