Forum: Mikrocontroller und Digitale Elektronik Arduino Benchmark auf verschiedenen MCUs


von Markus (Gast)


Lesenswert?

Da ja mittlerweile verschiedene MCUs durch die Arduino IDE unterstützt 
werden, möchte ich mal wissen, wie schnell die Peripherie damit ist.

Hier mal der erste Test mit einem Arduino Uno:

digitalWrite speed benchmark
=============================
number of tries: 100000  duration [us]: 519212  ==> speed 
[megaSamples/second] : 0.19

analogRead speed benchmark
=============================
number of tries: 100000  duration [us]: 11200052  ==> speed 
[kiloSamples/second] : 8.93

Knapp 9kHz für den ADC ist fast ein wenig langsam. Jetzt bin ich mal 
gespannt, wie schnell so was auf einem STM wird.

von Stefan F. (Gast)


Lesenswert?

Wenn du die Register direkt ansprichst, geht es VIEL schneller.

Genau genommen hast du da nicht die Performance des µC getestet, sondern 
die Performance des Arduino Frameworks.

von STM Apprentice (Gast)


Lesenswert?

Markus schrieb:
> Knapp 9kHz für den ADC ist fast ein wenig langsam.

Die Ergebnisse sollten einem motivieren mal ins "richtige"
Programmieren überzugehen.

von Markus (Gast)


Lesenswert?

>Die Ergebnisse sollten einem motivieren mal ins "richtige"
>Programmieren überzugehen.

Stell Dir mal vor, wenn Du den Job seit 30 Jahren machst ( so wie ich ) 
und zig Prozessorarchitekturen hinter Dir hast wird es irgendwann mal 
langweilig und zu umständlich sich mit jeder zusätzlich hinzu kommenden 
Architektur zu befassen.
Wenn Du dann einfach nur Problem lösen willst, kommt die Zeit der 
Software Frameworks die eine platformunabhängige und einfache 
Programmierung erlauben.
Mach es einfach mal lange genug, dann wirst Du schlauer.

>Wenn du die Register direkt ansprichst, geht es VIEL schneller.
>Genau genommen hast du da nicht die Performance des µC getestet, sondern
>die Performance des Arduino Frameworks.

Weiß ich. Das war genau die Absicht: Der Test des Gesamtsystems.

von DraconiX (Gast)


Lesenswert?

Markus schrieb:
> Knapp 9kHz für den ADC ist fast ein wenig langsam. Jetzt bin ich mal
> gespannt, wie schnell so was auf einem STM wird.

Selbst 190khz beim digitalWrite ist eigentlich mehr als lächerlich, was 
macht das Framework?! Startet der für jeden Pin-Change den µC neu oder 
warum ist das so miserabel?!

von Markus (Gast)


Lesenswert?

>Selbst 190khz beim digitalWrite ist eigentlich mehr als lächerlich, was
>macht das Framework?! Startet der für jeden Pin-Change den µC neu oder
>warum ist das so miserabel?!
Es abstrahiert den Pin-Zugriff durch eine Pin-Nummer, damit die Software 
auf  Boards mit verschiedenen MCUs läuft. Man kann z.B. einen Arduino 
Uno mit Atmega328 und einen Arduino Due mit ARM-MCU austauschen:

https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_digital.c
( Zeile 138 )

Es gibt schnellere Versionen mittels C++ Templates, aber die wurden 
leider nie in den Main-Zweig aufgenommen.

von Markus (Gast)


Lesenswert?

Hier das Ergebnis mit einem der Arduino-Frameworks auf dem Nucleo-64 ( 
STM32L476 ):

digitalWrite speed benchmark
=============================
number of tries: 100000  duration [us]: 39651  ==> speed 
[megaSamples/second] : 2.52

analogRead speed benchmark
=============================
number of tries: 100000  duration [us]: 3258145  ==> speed 
[kiloSamples/second] : 30.69

Der Pin Zugriff ist hier deutlich schneller, aber der ADC mit 
~30kSamples/s nicht so richtig überzeugend.

von Jörg (Gast)


Lesenswert?

Damit andere auch ihren Spaß haben können, wäre es schön, wenn Du den 
Code posten könntest.

Dann wären die Ergebnisse vergleich- und nachvollziebar.

von STM Apprentice (Gast)


Lesenswert?

Jörg schrieb:
> Dann wären die Ergebnisse vergleich- und nachvollziebar.

Wenn ich weiss dass ich beim AVR im direkten Programmieren
den Faktor 10 beim DigialWrite erreichen kann brauch ich
kein Testprogramm mehr um irgendwas nachzuvollziehen.

Your mileage may vary. Sagte schon immer der Franzose.

von Markus (Gast)


Angehängte Dateien:

Lesenswert?

> Code posten könntest.

Bitteschön ;-)

von Rudolph (Gast)


Angehängte Dateien:

Lesenswert?

Ist halt so, Arduino kostet.

Aber wie viel konkret ist nicht nur von der Plattform, sondern auch von 
der Implementierung abhängig.
Und von dem was man da gerade macht.


Das Bild ist für den Code hier:
1
digitalWrite(D8, LOW);
2
digitalWrite(D4, LOW);

Also im Grunde messe ich da wie lange es dauert einen Pin zu setzen.
Das läuft da gerade auf einem ESP8266 mit 80MHz, die 438ns sind also nur 
35 Taktzyklen was für Arduino schon am unteren Ende der Skala sein 
dürfte.

Andererseits messe ich auch das hier:
1
SPI.transfer(0x55);
2
SPI.transfer(0x55);

Damit sehe ich auf dem Scope zwischen dem Ende des ersten Transfers und 
dem Anfang des nächsten Transfers eine Lücke von 2,3µs, das sind 184 
Taktzklen für was auch immer.

Zusammen sieht das so aus:
1
digitalWrite(D8, LOW);
2
digitalWrite(D4, LOW);
3
SPI.transfer(0x55);
4
SPI.transfer(0x55);
5
digitalWrite(D8, HIGH);
6
digitalWrite(D4, HIGH);

Zwischen Low für D4 und der ersten Flanke auf SCK vergehen 1,7µs, es 
werden also 136 Taktzyklen benötigt um die Daten auf den SPI zu werfen 
und nach dem Transfer noch mal schlapp 50 Zyklen um wieder zurück zu 
kommen.
Ich würde mal vermuten, dass da noch Potential für Optimierungen ist.

Alles nicht schlimm, muss man nur mit rechnen.
Und durch verschiedene Implementierungen auch nicht unbedingt 
vergleichbar.

von Markus (Gast)


Lesenswert?

In Deinem Oszi Bild steht 1/dt=2.28Mhz
Das ist relativ nahe an den 2.52 MSPs aus meinem Benchmark.

Du könntest auch einfach mal den Benchmark laufen lassen.

von 1234567890 (Gast)


Lesenswert?

Markus schrieb:
> tell Dir mal vor, wenn Du den Job seit 30 Jahren machst ( so wie ich )
> und zig Prozessorarchitekturen hinter Dir hast wird es irgendwann mal
> langweilig und zu umständlich sich mit jeder zusätzlich hinzu kommenden
> Architektur zu befassen.
> Wenn Du dann einfach nur Problem lösen willst, kommt die Zeit der
> Software Frameworks die eine platformunabhängige und einfache
> Programmierung erlauben.
> Mach es einfach mal lange genug, dann wirst Du schlauer.

Ja, ich finde die Frameworks auch nicht schlecht. Bei vielen einfachen 
Aufgaben kommt man so schnell zum Ziel.
Leider kommt man auch schnell an die Grenzen und kann mit Framework die 
gewünschte Performance oder den gewünschten niedrigen Energiebedarf 
nicht erreichen.

Weiterhin führen die Frameworks dazu, dass fast jeder ohne 
Expertenwissen schnell zum Ziel kommen kann. Dies wiederum führt in 
einigen Fällen zu einer schlechten Performance, da nicht nur das 
notwendige, sondern das Framework in der Software mitgeschleppt wird. 
Man sieht es bei ganz vielen Anwendungen: Ein 
Klick/Tastendruck/Tipp/Wisch und das Warten geht los. Zügige 
Datenverarbeitung, schnelle Datenanzeige und gutes Reaktionsvermögen auf 
Benutzereingaben schließen sich bei manchen System quasi gegenseitig 
aus.
Zusätzlich lassen Frameworks natürlich aufgrund ihrer einfachen 
Handhabbarkeit auch eine gewisse Betriebsblindheit und eine gewisse 
Faulheit zu. Daher sollte man wachsam bei der Benutzung solcher 
Frameworks sein um nicht nur eine Lösung, sondern auch eine gute Lösung 
zu finden.

Alles in Allem: Frameworks sind eine gute Sache, dennoch sollte man in 
manchen Fällen auf sie verzichten können. Dazu ist es leider notwendig, 
sich in verschiedene Architekturen einzuarbeiten, sofern man für 
verschiedene Architekturen Software schreibt.

von Rudolph (Gast)


Lesenswert?

ESP8266
1
digitalWrite speed benchmark
2
=============================
3
number of tries: 100000  duration [us]: 96273  ==> speed [megaSamples/second] : 1.04
4
  
5
analogRead speed benchmark
6
=============================
7
8
Soft WDT reset
9
10
ctx: cont 
11
sp: 3ffef280 end: 3ffef4c0 offset: 01b0

Tja, nun. :-)

Gibt der "Benchmark" die Zeit für Pin-Wechsel und zurück an? Also 0-1-0?
Gemessen habe ich ja nur 1-0.

Und Watchdog-Reset, tja, mehr als ein paar hundert ms sollte die loop() 
nicht laufen.
Ein freundliches "ESP.wdtDisable();" im Code hat gar nichts bewirkt.

Also weniger Durchläufe:
1
digitalWrite speed benchmark
2
=============================
3
number of tries: 10000  duration [us]: 9648  ==> speed [megaSamples/second] : 1.04
4
  
5
analogRead speed benchmark
6
=============================
7
number of tries: 10000  duration [us]: 1064127  ==> speed [kiloSamples/second] : 9.40

von Einer K. (Gast)


Lesenswert?

Rudolph schrieb:
> Ein freundliches "ESP.wdtDisable();" im Code hat gar nichts bewirkt.
Das darf dich nicht wundern!
Der WDT ist nicht abschaltbar.
Ganz so, wie es bei einem WDT auch sein sollte.

von Markus (Gast)


Lesenswert?

Danke ;-)

>Gibt der "Benchmark" die Zeit für Pin-Wechsel und zurück an? Also 0-1-0?

Eigentlich nicht, es sind 8 digitalWrite in der "unrolled loop":
https://www.mikrocontroller.net/attachment/highlight/327826

Seltsam ....

Gerade eben habe ich eine Template Library für die AVR-Arduinos 
gefunden, die ist extrem gut dokumentiert und sehr schnell: Sie erreicht 
die maximal mögliche Geschwindigkeit für AVR-Prozessoren.

https://github.com/mmarchetti/DirectIO

Leider nur für AVR, die ARMS wären schön ...

von Rudolph (Gast)


Lesenswert?

Arduino F. schrieb:
>> Ein freundliches "ESP.wdtDisable();" im Code hat gar nichts bewirkt.
> Das darf dich nicht wundern!
> Der WDT ist nicht abschaltbar.
> Ganz so, wie es bei einem WDT auch sein sollte.

Warum darf mich das nicht wundern wenn die Funktion genau für sowas in 
das Framework mit eingebaut wurde?

Aber egal, ich benötige die sicher nicht.

Markus schrieb:
> Eigentlich nicht, es sind 8 digitalWrite in der "unrolled loop":
> https://www.mikrocontroller.net/attachment/highlight/327826
>
> Seltsam ....

Tja, aber da glaube ich lieber meinem Oszi. :-)
Wenn das der Overhead durch die Schleife ist, dürfte das auf einem AVR 
auch noch mehr ausmachen.

von Peter D. (peda)


Lesenswert?

Markus schrieb:
> Knapp 9kHz für den ADC ist fast ein wenig langsam.

Ein Blick ins Datenblatt verrät, die Wandlerfrequenz muß im Bereich 
50..200kHz liegen und eine Wandlung dauert 13 Takte.
Damit ergibt sich eine Wandlerrate von 3,8 ... 15kHz.
Der ADC-Teiler kann nur binare Schritte. Wenn also der Quarz unglücklich 
gewählt wurde und es kämen 201kHz raus, mußt Du die nächste Teilerstufe 
nehmen, d.h. 100,5kHz (Wandlerrate = 7,7kHz).
Für 15kHz bräuchtest Du einen 12,8MHz Quarz.

von Einer K. (Gast)


Lesenswert?

Rudolph schrieb:
> Warum darf mich das nicht wundern wenn die Funktion genau für sowas in
> das Framework mit eingebaut wurde?

Ein Blick in den Quellkot offenbart wundersames:
1
void EspClass::wdtDisable(void)
2
{
3
    /// Please don't stop software watchdog too long (less than 6 seconds),
4
    /// otherwise it will trigger hardware watchdog reset.
5
    system_soft_wdt_stop();
6
}

Du kannst mit der Funktion also nur den Software WDT abschalten.
Den Hardware WDT tangiert das nicht.

von STM Apprentice (Gast)


Lesenswert?

Peter D. schrieb:
> Wenn also der Quarz unglücklich
> gewählt wurde und es kämen 201kHz raus, mußt Du die nächste Teilerstufe
> nehmen,

Das ist wie beim Yoghurt:

Wenn nachts um 0:00 Uhr das Verfallsdatum eintritt fängt der
sofort spontan das schimmeln an.

von Chrys (Gast)


Lesenswert?

Peter D. schrieb:
> Ein Blick ins Datenblatt verrät, die Wandlerfrequenz muß im Bereich
> 50..200kHz liegen und eine Wandlung dauert 13 Takte.
> Damit ergibt sich eine Wandlerrate von 3,8 ... 15kHz.

Mit 15kHz kriegst du aber nicht mehr die 10bit Auflösung

Markus schrieb:
> Knapp 9kHz für den ADC ist fast ein wenig langsam

Ist in etwa die maximale Samplingrate für den ADC...

von Peter D. (peda)


Lesenswert?

Markus schrieb:
> Es abstrahiert den Pin-Zugriff durch eine Pin-Nummer

Schlimmer noch, die Pinnummer einer ganz bestimmten Bauform eines ganz 
bestimmten AVR-Typs. Es ist also ein Unterschied, ob der MC im PDIP, 
TQFP oder MLF-Gehäuse ist. Mal ist PD0 Pin 2, 30 oder 26.
Wenn man dann den MC in einer echten Schaltung einbaut und aber im 
Framework irgendwelche Fantasie-Pinnummern findet, kann man sich nur 
noch die Karten legen.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Beim Arduino Framework beziehen sich die Pin-Namen auf die Stiftleisten. 
Genau dafür taugt das sehr gut.

Wer kein Arduino Board verwendet, kann sich ja sein eigenes Mapping 
definieren.

von Rudolph (Gast)


Lesenswert?

Arduino F. schrieb:
> Ein Blick in den Quellkot offenbart wundersames:void
> EspClass::wdtDisable(void)
> {
>     /// Please don't stop software watchdog too long (less than 6
> seconds),
>     /// otherwise it will trigger hardware watchdog reset.
>     system_soft_wdt_stop();
> }
>
> Du kannst mit der Funktion also nur den Software WDT abschalten.
> Den Hardware WDT tangiert das nicht.

Na okay, auch schön, es gibt also zwei Watchdogs und wenn man den einen 
mit dieser Funktion abschaltet hat man ungefähr sechs Sekunden bis der 
andere anspringt.
Ein Aufruf mit 50.000 statt 100.000 könnte also gerade noch so drin 
sein, so zusätzlich zu dem was sonst noch in der loop() ist.

von Markus (Gast)


Angehängte Dateien:

Lesenswert?

Peter Dannegger
>Schlimmer noch, die Pinnummer einer ganz bestimmten Bauform eines ganz
>bestimmten AVR-Typs.
Stefan Us
>>Beim Arduino Framework beziehen sich die Pin-Namen auf die Stiftleisten.
>>Genau dafür taugt das sehr gut.

Um das noch mal etwas besser zu verdeutlichen hier zwei Bilder mit dem 
Arduino Uno und dem Nucleo-64 Board.
Die Pin-Nummern bezeichnen die Nummern des Arduino-Standart Headers.
Auf dem Nucleo steht zwar D0, D1 .. usw meint aber digital Pin 0,1 ...

von Markus (Gast)


Angehängte Dateien:

Lesenswert?

Arduino Uno Pin Header.

von Manfred (Gast)


Lesenswert?

Markus schrieb:
> Stell Dir mal vor, wenn Du den Job seit 30 Jahren machst ( so wie ich )
> und zig Prozessorarchitekturen hinter Dir hast wird es irgendwann mal
> langweilig und zu umständlich sich mit jeder zusätzlich hinzu kommenden
> Architektur zu befassen.
> Wenn Du dann einfach nur Problem lösen willst, kommt die Zeit der
> Software Frameworks die eine platformunabhängige und einfache
> Programmierung erlauben.

"seit 30 Jahren" macht den Unterschied! Zu der Zeit hatte ich den 
68HC805 im Einsatz und in Assembler Zyklen gezählt, weil ich 
Zeitprobleme hatte.

Ganz sicher hast Du über die Zeit ein Gefühl entwickelt, welche 
Geschwindigkeit wirklich notwendig ist.

Du kannst abschätzen, ob Arduino für Deine konkrete Anwendung 
ausreichend Geschwindigkeit bietet oder nicht.

Du weißt, dass Du "Fußpilzebene" könntest und hast es nicht nötig, über 
die Bastler herzuziehen oder den xxx zu verlängern, weil Du per 
Assemblercode länger auf Ereignisse warten kannst.

Jetzt erzeugst Du Benchmarks und schätzt den Gesamtaufwand ab, ob ein 
größerer µC mit Arduino oder ein kleiner in Assembler sinnvoller wäre.

Also: Gute Vorgehensweise, ich habe nichts auszusetzen :-)

von Markus (Gast)


Lesenswert?

>"Fußpilzebene"

loll :-)

>Ist in etwa die maximale Samplingrate für den ADC...

Harspalterisch könnte ich mich jetzt darauf versteifen, dass der ATMEGA 
ADC auch auf 150kHz übertackted werden kann. Das funktioniert in der 
Praxis gar nicht so schlecht.
Auf was ich eher hinaus wollte war aber, dass der schnellste ADC des 
STM32L467 eigentlich 5MSPs kann ( wenn ichs in den Specs richtig 
überflogen habe ) aber im Benchmark nur 30kSps erreicht werden.
Aber vielleicht haben sie sich ja auch am Arduino-Uno grob orientiert.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.