How to choose the Arduino MCU for fast and double precision data
processing
Giovanni Carrera, 17/02/2025
In some applications it is necessary to perform
calculations in double precision, such as in the coordinate conversion of a
GNSS receiver. This problem arises when I want to interface a satellite
receiver with Arduino compatible boards.
At the moment it seems that floating point
calculations performed with MicroPython are single precision only.
Google Maps wants the latitude and longitude in
decimal degrees, so it is necessary to extract the substrings of the prime
minutes from the coordinates of the NMEA sentences, and convert them into float
numbers and then in tenths of a degree.
Operating with single precision variables, that
is with 6-7 significant digits, you get about five decimal digits on decimal
degrees, this leads to a horizontal resolution of about one meter, lower than
the error of a common GNSS receiver. But if I want to do statistical
calculations or work with RTK receivers this resolution is no longer
acceptable. The RTK differential receivers, that work on the carrier phases,
have a centimetre accuracy and provide the coordinates with 6-7 decimal digits
on minutes, like the ones I used in my program. For these considerations it is
necessary to use an MCU (Micro Controller Unit) that has a true double
precision math.
For some MCUs it is not always clear how the
floating point arithmetic is actually calculated, so I wrote a test program for
the conversion from degrees and minutes in decimal degrees.
First I wrote my program on PC, in Matlab which
operates in double precision. I started from the coordinates expressed in
string, I convert the degrees and minutes into numbers, then in decimal
degrees.
Lats = '4221.0081996';
Longs = '01321.4740622';
lat = str2double(Lats(1:2)) +
(str2double(Lats(3:end))/60);
long = str2double(Longs(1:3))+
(str2double(Longs(4:end))/60);
fprintf('latitude = %s \n',Lats);
fprintf('longitude = %s \n',Longs);
fprintf('latitude (dec) = %12.9f°\n',lat);
fprintf('longitude (dec) = %12.9f°\n',long);
With the coordinates indicated it gave the
following results:
latitude = 4221.0081996
longitude = 01321.4740622
latitude (dec) = 42.350136660°
longitude (dec) =
13.357901037°
So I wrote the following Arduino IDE program to
evaluate the numerical results and processing times of the various MCUs on
which I performed the test.
/* program
doubletest.ino
test double precision of MCU
Giovanni Carrera, 14/10/2019*/
const String Lats = "4221.0081996";
const String Longs =
"01321.4740622";
void setup(void) {
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect
}
delay(100);
Serial.println("MCU double precision
test");
// convert Lat&Long in decimal format
unsigned long
ti= micros();
String minuts = Lats.substring(2);// latitude
minutes
double minutes = minuts.toFloat();// convert
it to float
double decdeg = minutes/60.0;
String Latdegs = Lats.substring(0,2);
double Latd = Latdegs.toFloat() + decdeg;//
latitude in decimal format (double)
minuts = Longs.substring(3);// longitude
minutes
minutes = minuts.toFloat();// convert it to
float
decdeg = minutes/60.0;
String Longdegs = Longs.substring(0,3);
double Longd = Longdegs.toFloat() + decdeg;//
longitude in decimal format (double)
unsigned long
tf= micros();
Serial.print("Latitude (dec) = ");
Serial.println(Latd,8);
Serial.print("Longitude (dec) = ");
Serial.println(Longd,8);
Serial.print("elaboration time [us] =
");
Serial.println(tf-ti);
} // end of setup
void loop() {
}
I tried this program also on 8 bit processors
like the Arduino Uno to verify that the double
precision is simulated and also on Teensy v3.2 that mount a 32-bit MCU type
ARM Cortex-M4 at 72 MHz but that does not have a true 64-bit mathematics. So I
narrowed down the study to six types of MCUs that yielded the same numerical
results.
ESP8266
This module uses a 32-bit MCU clocked at 80
MHz. I ran the test program on a ESP8266 type Wemos D1 mini which features an
ESP-12F module, with the results:
MCU double precision test
Latitude (dec) = 42.35013666
Longitude (dec) =
13.35790103
elaboration time [us] = 388
Correct numerical
results even if processed with relatively high times.
ESP32
This
interesting and versatile module uses a single/dual-core 32-bit LX6 Xtensa MCU
clocked at up to 240 MHz. I ran the test program on a Node MCU development
board with ESP32 WROOM.
MCU double precision test
Latitude (dec) = 42.35013666
Longitude (dec) =
13.35790103
elaboration time [us] =
152
Numerically correct values with very good
processing times. I also obtained similar results with an ESP32 WROVER.
Arduino Due
I used an original Arduino board, the first to
mount a 32-bit processor, using an Atmel SAM3X8E ARM Cortex-M3 clocked at 84
MHz.
MCU
double precision test
Latitude
(dec) = 42.35013666
Longitude
(dec) = 13.35790103
elaboration
time [us] = 141
Correct results and with the best execution
times.
Arduino Zero
For this test I used a Maduino A9G board, an
Arduino Zero compatible, which mounts a 32 bit MCU type ATSAMD21G18 clocked at
48MHz and an A9G module that combines a GPRS / GSM terminal and a GPS / BDS
satellite receiver on which I developed also a data logger program for
satellite data
MCU
double precision test
Latitude
(dec) = 42.35013666
Longitude
(dec) = 13.35790103
elaboration
time [us] = 250
Teensy 4.0
Teensy
4.0 has a 600 MHz ARM Cortex-M7 processor, an NXP iMXRT1062 chip, and is the
fastest microcontroller available at the moment.
MCU double precision test
Latitude (dec) = 42.35013666
Longitude (dec) = 13.35790103
elaboration time [us] = 5
Arduino Uno R4
This
recent board mounts a Renesas R7FA4M1AB3CFM#AA0 processor type Arm® Cortex®-M4.
at 48 MHz.
MCU double precision test
Latitude (dec) = 42.35013666
Longitude (dec) = 13.35790103
elaboration time [us] = 184
Conclusions
The following table summarizes my test results.
board |
MCU |
CPU clock
[MHz] |
time [µs] |
Arduino Due |
Atmel SAM3X8E ARM Cortex-M3 |
84 |
141 |
ESP32 WROOM |
Xtensa single-/dual-core 32-bit LX6 |
240 |
152 |
Arduino Zero |
ATSAMD21G18 |
48 |
250 |
Wemos D1 mini |
ESP8266EX, Tensilica L106 |
80 |
388 |
Teensy 4.0 |
ARM Cortex-M7 |
600 |
5 |
Arduino Uno R4 |
Arm Cortex-M4 |
48 |
184 |
The system that gave the best results is Teensy
4.0, followed by Arduino Due, which I had already used in the past for GNSS RTK
data processing. Considering the performance/price ratio, the ESP32 is
certainly the best system.