ADC performance of MicroPython boards

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
User avatar
rcolistete
Posts: 352
Joined: Thu Dec 31, 2015 3:12 pm
Location: Brazil
Contact:

ADC performance of MicroPython boards

Post by rcolistete » Sun Nov 20, 2016 7:12 pm

ADC performance tests of MicroPython boards :

- 'ADC_timedtimer_Pyboard.py' as only Pyboard has "ADC.read.timed()" method to ADC read burst into buffer in high speed. Test with 20 thousand readings, mean speed in ksample/s :
* Pyboard v1.1 (12 bits ADC) with MicroPython v1.8.6 : 1,604;
* Pyboard Lite v1.0 (12 bits) with MicroPython v1.8.6 : 899.6;

- 'ADC_loop' (download here for different boards) with 20 thousand readings, mean speed in ksample/s :
* Pyboard v1.1 (12 bits ADC) with MicroPython v1.8.6 : 34.9;
* Pyboard Lite v1.0 (12 bits) with MicroPython v1.8.6 : 20.1;
* WiPy 1.0 (12 bits) with MicroPython v1.8.2-103 : 62.5;
* ESP8266 (10 bits) with MicroPython v1.8.6-7 : 5.44 (80 MHz) / 7.34 (160 MHz);
* BBC Micro:bit (10 bits) with MicroPython v1.7.9 : 6.51;
* LoPy (12* bits) with MicroPython 0.9.6.b1 : 21.2.
* WiPy2 (12* bits) with MicroPython 0.9.6.b1 : 21.3.
* Teensy 3.2 (16 bits) with MicroPython v1.8.6 : 59.6;
* Teensy 3.5 (16 bits) with MicroPython v1.8.6 : 62.3;
* Teensy 3.6 (16 bits) with MicroPython v1.8.6 : 107.
(*) : this firmware is limiting the ADC to only 10 bits, 0-1V.
For example, "ADC_loop_Pyboard.py" :

Code: Select all

# ADC_loop_Pyboard.py
# Reads the Pyboard ADC and measures the time and speed to read 20000 samples.
import pyb
def ADCloopBenchmark():
    adc = pyb.ADC('X1')
    adcread = adc.read
    t1=pyb.micros()
    for i in range(20000):
        val = adcread()
    t2=pyb.micros()
    print("20000 ADC readings done after %u us." %(t2-t1))
    print("Mean time for each ADC reading = %15.13f us" % ((t2-t1)/20000.0))
    print("ADC reading = %15.13f ksamples/s" % (1000/((t2-t1)/20000.0)))
ADCloopBenchmark()
Pyboard (v1.1) is the champion MicroPython board, with 1.6 Msamples/s, for ADC burst reading ! :shock: Followed by Pyboard Lite with 0.9 Msamples/s in this mode.

For continuously ADC reading inside a loop, Teensy board and WiPy 1.0 are the fastest, followed by the Pyboard's. BBC Micro:bit surprised me, as its MCU is nRF51822 with ARM Cortex-M0 @ 16MHz.
My "MicroPython Samples". My "MicroPython Firmwares" with many options (double precision, ulab, etc).

User avatar
rcolistete
Posts: 352
Joined: Thu Dec 31, 2015 3:12 pm
Location: Brazil
Contact:

Re: ADC performance of MicroPython boards

Post by rcolistete » Sun Nov 27, 2016 4:24 am

Updated the ADC benchmark on LoPy and WiPy 2 using firmware 0.9.6.b1.

See historic evolution of these benchmarks for LoPy and WiPy 2.
My "MicroPython Samples". My "MicroPython Firmwares" with many options (double precision, ulab, etc).

cadcam
Posts: 2
Joined: Thu Dec 08, 2016 3:45 pm

Re: ADC performance of MicroPython boards

Post by cadcam » Thu Dec 08, 2016 4:12 pm

the use of micropython as the basis of a multi-channel datalogger is really interesting, however most effort.benchmarking seems to have been done for single channel aquisition. I may have missed it but has anyone being working on a general system that will allow simple acquisition of multiple channels with logging syncronously to buffers[ straight/dual or ring]/flash/sd card or even to usb/uart/wifi?

Ideally a series of simple set up calls to

a) Allocate channels to pins
e.g. adc_channel_pins(12,13,8,6...)
b) Which channels to log , destination, dataformat, datarate, n_samples
e.g. adc_log([1,2,4,5], buf, H,1000,50000) or adc_log([1,2,4,5]. sd/data.csv,csv,500,10000)

Of course other ideals would be a trigger/pretrigger, DMA (where available) + possibly warning message re predicted jitter, for a particular system, time stamping [To allow interleaving with other data from I2C etc]

Obviously a large number of ideals but there seems to have been some previous work on various aspects however I haven't seen a plan for a standard set of routines or have I missed it (many apologies if I have)


Regards

ckuehnel
Posts: 8
Joined: Sat Feb 02, 2019 3:09 pm
Location: Altendorf, Schweiz
Contact:

Re: ADC performance of MicroPython boards

Post by ckuehnel » Sun Feb 10, 2019 2:47 pm

Here is the ADC performance for an ESP32_Core_board v2:

20000 ADC reading done after 995697 us.<br/>
Mean time for each ADC reading = 49.7848510742188 us<br/>
ADC reading = 20.0864315032959 ksamples/s</t>

[code]
# ADC_loop_ESP32.py
# Reads the ESP32 ADC and measures the time and speed to read 20000 samples.
# based on http://www.robertocolistete.net/MicroPy ... C_loop.zip

import machine
from machine import Pin
from machine import ADC
import time

def ADCloopBenchmark():
adc = machine.ADC(Pin(32))
adcread = adc.read()
t1 = time.ticks_us()
for i in range(20000):
adcread = adc.read()
t2 = time.ticks_us()
print("20000 ADC readings done after %u us." %(t2-t1))
print("Mean time for each ADC reading = %15.13f us" % ((t2-t1)/20000.0))
print("ADC reading = %15.13f ksamples/s" % (1000/((t2-t1)/20000.0)))

ADCloopBenchmark()
[/code]

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: ADC performance of MicroPython boards

Post by Roberthh » Sun Feb 10, 2019 3:10 pm

Did the same on a ESP32 without SPIRAM with PyCom's WiPy firmware. Some figures:
- Simple loop as yours, ~60 µs iteration. If you deduct the time the loop control and assignment, the net time is ~52µs. The ESP32 runs at 160MHz
- Stuffing the loop with code to store the data in a ring buffer: Loop iteration take ~72µs.
Still, this kind of code is not useful for sampling any signal beyond 1 kHz, given that in real code a significant jitter has to be expected.

These are raw values, precise enough for the purpose.

sibir
Posts: 9
Joined: Tue Jan 17, 2017 1:18 pm

Re: ADC performance of MicroPython boards

Post by sibir » Wed Apr 08, 2020 3:56 pm

The PyBoard's ADC.read.timed() should not have jitter since it's timer based.
But because it's blocking you cannot use it for sustained data logging.
For an oscilloscope-like application where you only need one trace at a time it should be sufficient however.

Can anyone with a D-series PyBoard and/or a Teensy 4.0 run these tests and report back?

P@T
Posts: 33
Joined: Tue Nov 06, 2018 2:37 pm

Re: ADC performance of MicroPython boards

Post by P@T » Thu Apr 09, 2020 7:59 pm

Hi all,

Beware of the adc of esp32 they are bad
-7 +7 LSB
That's huge

Thank you for the test

sibir
Posts: 9
Joined: Tue Jan 17, 2017 1:18 pm

Re: ADC performance of MicroPython boards

Post by sibir » Thu May 21, 2020 2:33 am

Here is a sawtooth sampled with ESP32. Note the non-linearity:
ESP32.png
ESP32.png (10.48 KiB) Viewed 10567 times
The same looks better (more linear and less noisy) on the ESP8266
ESP8266.png
ESP8266.png (11.08 KiB) Viewed 10567 times
But in both cases there are periodic outliers.
One could probably run slightly faster by optimizing the code. I simply used:

Code: Select all

for i in range(1000): data.append(adc.read())

User avatar
tve
Posts: 216
Joined: Wed Jan 01, 2020 10:12 pm
Location: Santa Barbara, CA
Contact:

Re: ADC performance of MicroPython boards

Post by tve » Thu May 21, 2020 3:56 am

To be fair: MP doesn't use the esp32's IDF calibration routines...

machdisk
Posts: 16
Joined: Sun May 22, 2016 1:35 am

Re: ADC performance of MicroPython boards

Post by machdisk » Tue Nov 17, 2020 10:36 pm

Report on the Pyboard-D SF3W running Micropython 1.13-173:

With machine.freq(48000000) the code at http://www.robertocolistete.net/MicroPy ... Pyboard.py yields sample rates that vary between 435 and 477 kSps.

@ machine.freq(216000000) the script yeilds rates that hover just around 2147 kSps.

The standard loop script (i.e. the ADC benchmark loop): 36.6 kSps

With that said, running the PYBD with the readtimed function appears to be quite impressive. I will throw in a waveform and report back later.

Post Reply