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.
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.
Markus schrieb: > Knapp 9kHz für den ADC ist fast ein wenig langsam. Die Ergebnisse sollten einem motivieren mal ins "richtige" Programmieren überzugehen.
>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.
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?!
>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.
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.
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.
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.
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.
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.
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.
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 |
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.
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 ...
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.
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.
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.
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.
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...
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
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.
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.
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 ...
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 :-)
>"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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.