Hab mal paar "Experiemte" mit dem Arduino Mega gemacht. Dabei interessierte mich, wie schnell ein Portpin in Software zu toggeln ist. Ein einfacher "Sketch" brachte es auf 78,7 KHz. Bei 16MHz viel zu wenig. Vergleichsweise schafft man es in Assembler auf 2,6667MHz, in C ebenso. Hier der Arduino "Pseudocode": //Ardurino Pin 12 so schnell wie möglich in Software toggeln int port = 12; void setup() { pinMode(port, OUTPUT); } void loop() { digitalWrite(port, HIGH); digitalWrite(port, LOW); } Dafür braucht die CPU 630.400 Zyklen????? In Assembler: .INCLUDE "m2560def.inc" rjmp main main: ldi R16,0xFF out DDRB,R16 ldi R16,0xFF out PORTB,R16 sbi portb,6 cbi portb,6 rjmp PC-2 Ein Durchlauf benötigt 6 Zyklen. Benutz man stattdessen in der Schleife nur "SBI PINB,6" (der Mega 2560 kann das, dann sind es 8, also genau 2 MHz. Was bremst den Arduino-Code so aus? Was macht "DigitalWrite" alles noch?
> Was bremst den Arduino-Code so aus?
Das SDK. Klücklicherweise muss man das nicht nutzen.
Nachtrag: andere Portpins schaffen es auf 100KHz..
Kuck doch einfach mal rein in digitalWrite(). Ist ja OpenSource. Hatte es neulich gemacht. Kann mich noch dran erinnern, dass der Pin auch als PWM Pin und anderes benutzt werden kann.
Daniel schrieb: > Ein einfacher "Sketch" brachte es auf 78,7 KHz. > Bei 16MHz viel zu wenig. Nicht für einen Arduino. > Was bremst den Arduino-Code so aus? Was macht "DigitalWrite" alles noch? feststellen welcher Pin zu '12' gehört und den dann je nachdem ob du High oder Low haben willst, schalten. Danach: den return aus loop() machen. Beim Aufrufer dann die Buchhaltung durchführen, loop() wieder aufrufen und den nächsten digitalWrite machen.
:
Bearbeitet durch User
1 | void digitalWrite(uint8_t pin, uint8_t val) |
2 | {
|
3 | uint8_t timer = digitalPinToTimer(pin); |
4 | uint8_t bit = digitalPinToBitMask(pin); |
5 | uint8_t port = digitalPinToPort(pin); |
6 | volatile uint8_t *out; |
7 | |
8 | if (port == NOT_A_PIN) return; |
9 | |
10 | // If the pin that support PWM output, we need to turn it off
|
11 | // before doing a digital write.
|
12 | if (timer != NOT_ON_TIMER) turnOffPWM(timer); |
13 | |
14 | out = portOutputRegister(port); |
15 | |
16 | uint8_t oldSREG = SREG; |
17 | cli(); |
18 | |
19 | if (val == LOW) { |
20 | *out &= ~bit; |
21 | } else { |
22 | *out |= bit; |
23 | }
|
24 | |
25 | SREG = oldSREG; |
26 | }
|
Wen wundert es dass es länger dauert...
... oder anders ausgedrückt: Die Wolle, der eierlegenden Wollmilchsau, ist nicht die Feinste und die Eier könnten etwas größer sein. Auch ohne je in die Bibliotheken geschaut zu haben, sollte das obige Ergebnis eigentlich vorhersehbar sein - wenn auch vielleicht nicht in der aufgezeigten Größenordnung.
Sind natürlich bei 78,8KHz "nur" ca 101 Zyklen für einen Umschaltvorgang. Das ist ja irre...
Daniel schrieb: > Sind natürlich bei 78,8KHz "nur" ca 101 Zyklen für einen > Umschaltvorgang. Das ist ja irre... Nö. Nicht für einen Umschaltvorgang. Für einen kompletten Turnaround von einem Aufruf von loop() zum nächsten, vergehen 203 Takte. Und das ist dann ein bischen was anderes. Oder denkst du, dass du zb eine Systemuhr gratis kriegst?
:
Bearbeitet durch User
ein Umschaltvorgang ist doch von 0->1 oder umgekehrt. Dabei vergehen 101 Take. 2 Umschaltvorgänge sind dann ein (kompletter)Zyklus. Oder was meinst du mit Systemuhr?
Wenn man aber von, oft sehr unrealistischen Megaherzphantasien herunterkommt: Ist das wirklich zu langsam? Oder anders ausgedrückt: Wie realistisch ist die obige Schleife mit, völlig unrealistischen 6 bzw. 8 Taktzyklen? Das Minimum der obigen Schleife enthält eine - wie auch immer geartete - Zählerabfrage. Also nix mit 6/8 Taktzyklen. Meine Aktivitäten in Sachen Pin setzten folgten bisher immer dem Chema: ... Grübel, grübel Pin an Grübel, grübel Pin aus ... Das Minimum war das Abholen von Messwerten und einfache Vergleiche. Das Maximum waren komplexe Rechnungen und Spaziergänge quer durch die Fließkommabibliotheken. Irgendwann werden dann plötzlich zusätzliche 203 Takte zu einem Nichts, oder man stellt fest, dass der Prozessor ungeeignet ist.
>Irgendwann werden dann plötzlich zusätzliche 203 Takte zu einem Nichts,
Mach mal ein Software SPI oder PWM. Dann wird ganz schnell klar
warum das nichts taugt.
Mir ging es primär gar nicht darum irgendwelche MHz Orgien zu veranstalten. Dafür gibt es Fast PWM & Co. Wollte einfach nur wissen, ob der so unschuldig aussehende "DigitalWrite" Befehl wirklich nur den Pin - so wie im Assembler-Beispiel - ohne weitere Verzögerung umschaltet. Tut er nicht, ok. Damit ist er ungeeignet, wenn es mit dem Timing mal wirklich knapp zugeht. Möchte garn nicht wissen, was die anderen Adruino Makros so alles veranstalten. Schon die kompilierte Codegröße hat mich stutzig gemacht.
@Holger >Mach mal ein Software SPI oder PWM. Dann wird ganz schnell klar >warum das nichts taugt. Stimmt, aber ... @Daniel >Damit ist er ungeeignet, wenn es mit dem Timing mal wirklich knapp >zugeht. Möchte garn nicht wissen, was die anderen Adruino Makros so >alles veranstalten. Macht’s wie ich. Bisher habe ich drei Arduinos verwendet. Bei Zweien habe ich, wenn auch aus anderen Gründen, die Entwicklungsumgebung beiseitegeschoben und das "normale" Studio rangelassen. ISP bringt’s. Ein Grund für den Arduino blieb nämlich: Es ist ein relativ günstiges und gut dokumentiertes Stück Elektronik, welches in zwei Fällen, die gesamte benötigte Elektronik enthielt. Im dritten Fall war der Micro ein, die gesamte Schaltung vereinfachendes, "IC".
holger schrieb: >>Irgendwann werden dann plötzlich zusätzliche 203 Takte zu einem Nichts, > > Mach mal ein Software SPI oder PWM. Dann wird ganz schnell klar > warum das nichts taugt. Warum sollte man SPI oder PWM mit digitalWrite() machen? Schließlich ist das ja eine der (har har) Stärken von Arduino, daß man SPI und PWM als Fertigteil bekommt, das man nur noch einstöpseln muß. Dein Argument ist in etwa auf dem Niveau, daß sich Ytong-Steine schlecht als Bauklötze eignen, weil die damit gebauten Projekte so schlecht ins Kinderzimmer passen. XL
Daniel schrieb: > ein Umschaltvorgang ist doch von 0->1 oder umgekehrt. Dabei vergehen > 101 Take. 2 Umschaltvorgänge sind dann ein (kompletter)Zyklus. > Oder was meinst du mit Systemuhr? Nein. Ich meine, dass das Arduino System(!) im Hintergrund auch noch andere Sachen macht. Deine Endlosschleife ist eben nicht dasselbe, wie die Funktion loop(). Denn da gibt es auch noch einen Aufrufer, der loop() ständig aufruft und zwischen den Aufrufen auch noch Dinge erledigt. Ich würde durchaus soweit gehen und dem Arduino System bereits Eigenschaften eines kleines Betriebssystems zusprechen. Kurz gesagt: du vergleichst in einem gewissen Sinne Äpfel mit Birnen.
:
Bearbeitet durch User
Ist zwar langsam, dafür ist es einfach. Wenn ich vergleiche, was da sonst für Bitfriemeleien notwendig sind, (30% der Post hier gehen ja um solche Probleme beim Ansprechen eines Ports) So ist das halt im Leben: -- schnell, und es wird hart -- einfach, und es dauert eben. Für die meisten Anwendungen reichen die 70 KHz doch aus.
Meine Fresse, da ist ja sogar Java (ohne JIT Compiler) besser. Ich habe bisher noch nie mit der Arduino Software gearbeitet, aber spätestens jetzt ist sicher, dass ich es auch niemals tun werde. Falls da mal ein Job-Angebot kommt: Nein Danke.
> Meine Fresse, da ist ja sogar Java (ohne JIT Compiler) besser.
Dann lass mal Java auf ner 16MHz CPU laufen ...
PittyJ schrieb: > Ist zwar langsam, dafür ist es einfach. > Wenn ich vergleiche, was da sonst für Bitfriemeleien notwendig sind, Wenn man weiß wie, geht es auch schnell und einfach: Beitrag "Re: Makros versus Funktionen"
Timmo H. schrieb: > void digitalWrite(uint8_t pin, uint8_t val) Warum werden dann in den Arduino-Beispielen immer 16 Bit (int) übergeben? Wozu diese Verschwendung auf nem 8-Bitter? Timmo H. schrieb: > uint8_t timer = digitalPinToTimer(pin); > uint8_t bit = digitalPinToBitMask(pin); > uint8_t port = digitalPinToPort(pin); > ... > if (timer != NOT_ON_TIMER) turnOffPWM(timer); > out = portOutputRegister(port); Schonmal 5 Unterfunktionsaufrufe, kein Wunder, daß da heftig Laufzeit zustande kommt.
Da gibts aber noch mehr tücken beim Arduino Sketch: kopiert von: http://vpapanik.blogspot.gr/2012/08/arduino-thank-you-and-bye-bye.html digitalWrite() takes 56 cycles to execute (well, I measured 400). At least it is easy to find out why and switch to direct port access (the second thing to change, after the IDE). Generally, Arduino is not very friendly for time-efficient coding. You cannot (at least, easily) disable the default hardware serial library, in order to take over the TX and RX interrupts, no matter if it has been started or not ! There's a overflow timer ISR firing every 16K clock cycles in the background. This is for servicing millis() and micros() functions, even when they're not used at all ! An empty Arduino project takes 466 bytes on an Arduino UNO and 666 bytes on an Arduino Mega 2560. I dislike overheads a lot. I also dislike seeing warnings during compiling of the above.
Mal wieder viel Beitraege zu denen man nur sagen kann: "Wenn man keine Ahnung hat, einfach mal Fresse halten!". Immer wieder erschreckend, wie viel Energie in's Bashing und wie wenig in's KnowHow gesteckt wird.
>> Meine Fresse, da ist ja sogar Java (ohne JIT Compiler) besser. >Dann lass mal Java auf ner 16MHz CPU laufen ... Bei Lego Mindstorms klappt das ganz gut mit 32Mhz.
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.