Hallo,
ich experimentiere ein bißchen mit Arduinos. Ich lese oft das ein in C
programmiertes Aduinoboard ein Programm viel schneller ausführt wie ein
mit der Arduinoprogrammiersprache. Hat das jemand mit dem entsprechendem
Meßequipment mal probiert, z.B. ein Programm:
Loop
PinX = 1
PinX = 0
Welche Taktfrequenz hat ein Signal an PinX mit Arduino programmiert,
welche mit C programmiert?
Ich hoffe die Frage war nicht zu blöd.
MfG
Hans
Hans L. schrieb:> Ich hoffe die Frage war nicht zu blöd.
doch ist sie.
Arduino ist C
Es wird kein unterschied geben. Bei Arduino ist das Problem viel mehr,
das viele Versteckt wird und man nicht weis was im Hintergrund passiert.
Hans L. schrieb:> Ich lese oft das ein in C> programmiertes Aduinoboard ein Programm viel schneller ausführt wie ein> mit der Arduinoprogrammiersprache.
Hast du mal einen Link? Oder mehrer, wenn du das oft gelesen hast?
Oliver
digitalWrite() und digitalRead() sind keine Geschwindigkeitswunder, aber
ansonsten, ist die Aussage:
Hans L. schrieb:> Ich lese oft das ein in C> programmiertes Aduinoboard ein Programm viel schneller ausführt wie ein> mit der Arduinoprogrammiersprache
Wohl ein Märchen.
> Wohl ein Märchen.
Sicher?
Ich erinnere mich an eine Diskussion hier im Forum, wo jemand
digitalWrite() mit direkten Portzugriffen der Art PORTB |= (1<<PB3)
verglich und ganz erstaunt war, dass die Arduino Library in diesem Punkt
100x mal langsamer war.
Damals wurde hier der generierte Assembler Code verrissen und viele
Telnehmer meinten, dass sie genau deswegen niemals etwas mit Arduino
Software zu tun haben wollen.
Stefan U. schrieb:> Ich erinnere mich an eine Diskussion hier im Forum, wo jemand> digitalWrite() mit direkten Portzugriffen der Art PORTB |= (1<<PB3)> verglich und ganz erstaunt war, dass die Arduino Library in diesem Punkt> 100x mal langsamer war.
aber es zwingt doch niemand digitalWrite zu verwenden. Ich kann auch in
C mir eine langsame Variante von digitalWrite einfallen lassen.
Es hängt also nicht direkt am Arduino wenn etwas langsam ist, sondern
daran wie man ein Problem umsetzt.
eine Uhr wird (hoffentlich) mit C auch nicht schneller sein.
Stefan U. schrieb:> dass die Arduino Library in diesem Punkt> 100x mal langsamer war.
Nichts anderes habe ich doch gesagt.....
Vielleicht nicht so deutlich.....
Siehe:
Ulrich F. schrieb:> digitalWrite() und digitalRead() sind keine GeschwindigkeitswunderStefan U. schrieb:> Sicher?
Ja!
Peter II schrieb:> Es hängt also nicht direkt am Arduino wenn etwas langsam ist, sondern> daran wie man ein Problem umsetzt.
Natürlich hängt es genau daran. Wenn du auf die Arduino Seite gehst,
wirst du in der Doku nämlich genau diese Funktionen finden. Beim
direkten Portzugriff benutzt man die Bibliothek gar nicht mehr.
avr schrieb:> Natürlich hängt es genau daran. Wenn du auf die Arduino Seite gehst,> wirst du in der Doku nämlich genau diese Funktionen finden.https://www.arduino.cc/en/Reference/PortManipulation
also ich finde dort beides. Und dort steht auch das der direkte Zugriff
schneller ist und man ihn verwenden sollte wenn es sehr schnell gehen
soll.
Hans L. schrieb:> Loop> PinX = 1> PinX = 0
die Zuweisungen sind nicht von Arduino
da verwendet man DigitalWrite, das kostet zum einen Zeit,
zum anderen braucht das Loop auch länger als wenn du eine
Schleife direkt in C++ programmierst.
Die Taktfrequenz mit der das ganze abgearbeitet wird habe ich
auch schon Mal gesucht, war unter den ersten Treffern bei google ...
Peter II schrieb:> also ich finde dort beides. Und dort steht auch das der direkte Zugriff> schneller ist und man ihn verwenden sollte wenn es sehr schnell gehen> soll.
hm, tatsächlich. Das widerspricht eigentlich der
Plattformunabhänigigkeit. Besser wäre es über Templates... Da frage mich
eigentlich, wo der Vorteil von Arduino liegen soll wenn es nicht mehr
plattformunabhängig ist? Dann kann man es eigentlich gleich lassen.
avr schrieb:> Peter II schrieb:> also ich finde dort beides. Und dort steht auch das der direkte Zugriff> schneller ist und man ihn verwenden sollte wenn es sehr schnell gehen> soll.>> hm, tatsächlich. Das widerspricht eigentlich der> Plattformunabhänigigkeit. Besser wäre es über Templates... Da frage mich> eigentlich, wo der Vorteil von Arduino liegen soll wenn es nicht mehr> plattformunabhängig ist? Dann kann man es eigentlich gleich lassen.
Das steht dort als Nachteil.
Die "Arduino Programmiersprache" ist C/C++ mit einer HAL (hardware
abstraction layer, deutsch Hardwareabstraktionsschicht)
Durch die HAL sind die ganzen Hardwarezugriffe versteckt, das
vereinfacht zwar die Programmierung aber ist sehr viel langsamer, da
viele Sachen zusätzlich abgefragt oder berücksichtig werden, auch wenn
sie an der Stelle gar nicht relevant sind.
Ein PortX |= 0x01; dauert nur einen Takt
Ein Aufruf über digitalWrite() dauert im vergleich dazu ewig.
Erstmal muss nachgeschaut werden welcher Pin das überhaupt ist, dann
werden alternative Funktionen des Pins (z. B. PWM) deaktiviert,
Direktion Register gesetzt und dann wird endlich der Pin gesetzt.
Vielen Dank für alle Beiträge. Ich habe geschrieben das ich mit den
Arduinos jetzt etwas experimentiere, d. h. ich bin ein Anfänger. Wenn
ich ein entsprechendes Frequenzmeßgerät hätte würde ich es selbst
probieren. Hat es jemand schon mal selbst ausprobiert wie die
Ausgabefrequenz bei den verschiedenen Programmiersprachen ist, oder habt
alle ihr alle es auch nur irgendwo gelesen? Das hätte ich mit Google
auch hinbekommen. PinX soll natürlich nur stellvertretend für die
entsprechende Anweisung stehen.
MfG
Hans
Christian K. schrieb:> Erstmal muss nachgeschaut werden welcher Pin das überhaupt ist, dann> werden alternative Funktionen des Pins (z. B. PWM) deaktiviert,> Direktion Register gesetzt
wenn Digitalwrite das Direktion Reg setzt, dann braucht man die Funktion
Pinmode ja gar nicht???
Hans L. schrieb:> Das hätte ich mit Google> auch hinbekommen.
und warum machst du es dann nicht?
>PinX soll natürlich nur stellvertretend für die> entsprechende Anweisung stehen.
und wie lautet die entsprechende Anweisung,
DigitalWrite
oder
PORTB |= 1
Die libraries sind nicht überall so viel langsamer. Das setzen einzelner
Bits ist schon so etwas wie ein worst case Beispiel. Bei vielen
einfachen Rechenfragen gibt es gar keinen Unteschied zu normalem C Code.
Bei so etwas wie UART / I2C kann man es von Hand auch schlechter
impementieren als in den Libs.
Fazit,
keiner hat die Taktfrequenz bei den verschiedenen Programmiersprachen
selbst gemessen.
Ich kaufe mir ein Frequenzmeßgerät und probiere es selbst.
MfG
Hans
Hans L. schrieb:> Hat das jemand mit dem entsprechendem> Meßequipment mal probiert
dazu brauchst du kein Equipment.
einfach dein Programm z.B. 10000x laufen lassen und die vor und nachher
die Zeilt per millis geben lassen.
Wenn du die Differenzzeit durch 10000 teilst, hast du die Zeit für einen
Durchlauf
Christian K. schrieb:> Ein PortX |= 0x01; dauert nur einen Takt
Check das noch mal, das ist ein Read-Modify-Write.
Dicht dran, sehr dicht dran, aber auch nicht richtig. :-)
Sowas finde ich lästig:
val = analogRead(analogPin); // read the input pin
Serial.println(string);
lcd.print("hello, world!");
Das ist komplett blockierend, die Funktionen kommen erst zurück wenn das
Ergebnis da ist.
Im Falle vom analogRead() werden also mal eben um 100µs sinnlos
verbrannt.
Und da wundern sich unsere Azubis, warum der Arduino nur eher sporadisch
auf Eingaben reagiert...
Rudolph R. schrieb:> Das ist komplett blockierend, die Funktionen kommen erst zurück wenn das> Ergebnis da ist.> Im Falle vom analogRead() werden also mal eben um 100µs sinnlos> verbrannt.
Tja, das ist halt das Grundmerkmal von 98% der Mikrocontroller-Libraries
wie eben auch Arduino, dass jede Funktion blockiert. Das ist ja so
allgegenwärtig, dass sich da kein Mensch mehr Gedanken drüber macht.
Asynchrone Programmierung auf Interrupt-Basis versteht ja keiner...
Rudolph R. schrieb:>> Ein PortX |= 0x01; dauert nur einen Takt>> Check das noch mal, das ist ein Read-Modify-Write.> Dicht dran, sehr dicht dran, aber auch nicht richtig. :-)
---
PORTB |= 0x01;
80: 28 9a sbi 0x05, 0 ; 5
---
Na okay, der Compiler ist noch schlauer.
Dr. Sommer schrieb:> Asynchrone Programmierung auf Interrupt-Basis versteht ja keiner...
Das kann man so auch nicht sagen...
Dr. Sommer schrieb:> dass jede Funktion blockiert
Das gilt für Serial.println(string); nicht unbedingt. Das blockiert
erst, wenn der Buffer voll ist.
Dr. Sommer schrieb:> dass sich da kein Mensch mehr Gedanken drüber macht
Außerdem ist das in vielen Fällen vollkommen egal, ob eine Funktion ein
paar mS blockiert.
Rudolph R. schrieb:>> Ein PortX |= 0x01; dauert nur einen Takt>> Check das noch mal, das ist ein Read-Modify-Write.> Dicht dran, sehr dicht dran, aber auch nicht richtig. :-)
Ein PORTA |= (1<<0);
wirt zu zur kürzest möglichen ASM-Anweisung sbi kompiliert, die braucht
auf normalen AVRs 2 Takte, auf den tinyAVRs ("Number of clock cycles for
Reduced Core tinyAVR") einen Takt.
Hallo,
Dr. Sommer schrieb:> Tja, das ist halt das Grundmerkmal von 98% der Mikrocontroller-Libraries> wie eben auch Arduino, dass jede Funktion blockiert. Das ist ja so> allgegenwärtig, dass sich da kein Mensch mehr Gedanken drüber macht.> Asynchrone Programmierung auf Interrupt-Basis versteht ja keiner...
Prinzipiell hast Du recht und das ist auch das Problem "Arduino".
Es wird aber auch niemand gehindert, es selbst zu machen. Dann ist es
eben nicht mehr so leicht portabel, aber schneller und nicht
blockierend.
Ja, digitalWrite() und seine Abkömmlinge sind lahm. Für einen sauberen
Multiplex meiner Anzeige z.B. zu lahm. Na und? Wird eben ein freier
Timer initialisiert und der Kram selbst erledigt.
Andererseits speiel ich mit den ESP8266 rum, da bin ich dankbar für
digitalWrite(), die Doku des Espressif ist nämlich umfangreich, manchmal
fragwürdig oder unvollständig.
Abhängig vom Vorhaben ist es mir auch egal, wielange digitalWrite()
braucht, ich gewinne nichts wenn es schnell ist ohne daß es eine Rolle
spielt. Der AVR wartet dann eben länger oder die loop() wird 30x statt
10x nutzlos durchlaufen bis wieder was passiert.
Es wird bei Arduino-Displays gern die u8g-Lib empfohlen. Vorteil ist,
sie kennt fast jeden Displaycontroller mit fast jeder Ansteuerung. Sie
hat fast jede Funktion, die man irgendwie brauchen kann.
Gut, der Mega328 ist fast voll, wenn man die einbindet, nimmt man eben
den Mega2560. Gereicht hätte für die komplette Aufgabe allerdings auch
ein Mega88.
Wie schreibt hier jemand gern: einen Tod muß man sterben...
Gruß aus Berlin
Michael
@ Rudolph R. (rudolph)
>> Ein PortX |= 0x01; dauert nur einen Takt
2, da wird ein sbi draus.
>Check das noch mal, das ist ein Read-Modify-Write.
Meistens nicht.
>val = analogRead(analogPin); // read the input pin>Serial.println(string);>lcd.print("hello, world!");
Vollkommen OK.
>Das ist komplett blockierend, die Funktionen kommen erst zurück wenn das>Ergebnis da ist.
Was sollen sie sonst tun? Anfänger mit Call back Funktionen un RTOS
verwirren?
>Im Falle vom analogRead() werden also mal eben um 100µs sinnlos>verbrannt.
Was in 90% aller Arduino-Anwendung kein Problem ist.
>Und da wundern sich unsere Azubis, warum der Arduino nur eher sporadisch>auf Eingaben reagiert...
Ach so, weil sie 100us waren müssen? Soso!
Nicht immer nur rumjammern, wenn schon Kritik, dann substantiell!
Falk B. schrieb:>>Im Falle vom analogRead() werden also mal eben um 100µs sinnlos>>verbrannt.>> Was in 90% aller Arduino-Anwendung kein Problem ist.
Ich gehe eher von 69% aus, die Zahl ist genau so willkürlich gewählt.
:-)
>>Und da wundern sich unsere Azubis, warum der Arduino nur eher sporadisch>>auf Eingaben reagiert...>> Ach so, weil sie 100us waren müssen? Soso!
Nein, durch die Kombination von allem was denen so einfällt.
Zum Beispiel in jedem Schleifen-Durchlauf die Strings erneut an das
Display schicken, am Besten noch mehrere übereinander.
Natürlich gespickt mit delay() das Ganze.
> Nicht immer nur rumjammern, wenn schon Kritik, dann substantiell!
War doch konstruktiv, was denn noch?
Fakt ist, das ist alles blockierend mit mehr oder weniger starken
Auswirkungen.
Mein Kommentar dazu war jetzt nicht, dass das Scheisse ist, sondern
lediglich, dass ich das lästig finde.
@ Rudolph R. (rudolph)
>> Ach so, weil sie 100us waren müssen? Soso!>Nein, durch die Kombination von allem was denen so einfällt.>Zum Beispiel in jedem Schleifen-Durchlauf die Strings erneut an das>Display schicken, am Besten noch mehrere übereinander.>Natürlich gespickt mit delay() das Ganze.
AHA! Da kommen wir der Sache schon näher!
>> Nicht immer nur rumjammern, wenn schon Kritik, dann substantiell!>War doch konstruktiv, was denn noch?
Nö, nur Gejammer über eine normale Sequenz, also ob man nur mit
Interrupts und asynchronen Schikanen programmieren könnte. Das stimmt
nicht!
>Fakt ist, das ist alles blockierend mit mehr oder weniger starken>Auswirkungen.
Ich behaupte mal, auch mit den meist blockierenden Arduino-Funktionen
kann man gute, flüssige Programme schreiben. Auch wenn es mit "richtigem
C" sicher noch besser geht und man noch ne ganze Ecke mehr rausholen
kann.
>Mein Kommentar dazu war jetzt nicht, dass das Scheisse ist, sondern>lediglich, dass ich das lästig finde.
Der entscheidende Punkt ist, dass man den Lehrlingen die richtigen
Konzepte vermitteln muss und nicht rumjammern, daß sie es bis jetzt noch
nicht kapiert haben. Alle können und wollen es so oder so nicht
verstehen.
Hans L. schrieb:> Wenn ich ein entsprechendes Frequenzmeßgerät hätte würde ich es selbst> probieren.
Ein Frequenzmeßgerät ist für Messungen an einem µC nun wirklich fast die
ungünstigste Lösung. Kauf dir besser einen kleinen Logikanalysator für
weniger als 8€. Da hast du wesentlich mehr von.
Die Laufzeit so kurzer Dinge kann man ggf. auch noch gut im Simulator
ablesen. Einfach beak points setzen und den Simulator Takte Zählen
lassen.
Der Faktor 100 (durch die nun doch 2 Zyklen für ein SBI nur noch 50)
sieht groß aus, aber in der Regel kommt da noch viel anderer Code dazu,
so dass der Unterschied in der kompletten routine gar nicht mehr so
auffällt.
Wenn man wirklich Zeitkritische Teile hat, wie etwa Bitbanging - kann
man auch beim Arduino direkt auf die Register zugreifen - das ist aber
eher die Ausnahme.
Falk B. schrieb:> Der entscheidende Punkt ist, dass man den Lehrlingen die richtigen> Konzepte vermitteln muss und nicht rumjammern, daß sie es bis jetzt noch> nicht kapiert haben. Alle können und wollen es so oder so nicht> verstehen.
Gannz genau sehe ich es auch so!
Wenn wir also über Arduino und Codgeschwindigkeiten reden, sollten wir
ganau diese Dinge ausdrücklich vor Augen halten :-)
...Arduino wurde ja gerade für Künstler und nichtprogrammierer
entwickelt!
Dem Entwickler sei Dank... erfreuen sich viele User darüber,dass
es diesen Plattform gibt.
Gerade weil es hier nicht um ein,bis in die Perfektion hochgeputschtes
Spezies handelt, eignet sich diese Familie bestens für Lernzwecke.
Und Lernen gehört nunmal dazu, neues Wissen anzuegnen.
In diesem Sinne freue ich mich persönlich sehr darüber, dass es
eine preiswerte "universelle" Möglichkeit gibt, C, C++ Arduino-C
oder wie auch es heißen mag Sprache kennenzulernen und
paralell dazu darüber,die Theorie sofort in die Praxis umsetzen zu
können.
Ob die Code-geschwindigkeiten zufriedenstellend sind, hängt hier
im Größtenteil doch davon ab, wie weit ich mit meinem Wissen
gekommen bin ?!
Die Fortgeschrittenen setzen Assembler ein, die Anfänger eher die
Arduino-C, das eine schließt aber das Andere nur in einer Richtung
aus :-)
MfG
Hallo,
warum sollte man rumhacken?
Die Meinungen werden da ohnehin beliebig weit auseinandergehen.
Ich kann nur für mich reden. Es ist bei mir reines Hobby, das heißt, daß
Ergebnis soll ohne wenn und aber funktionieren, es spielt aber keine
wirkliche Rolle, wenn ein Projekt scheitert und ich es beerdige.
Ich quäle auch keine µC, allerdings ist Multitasking z.B. auch keine
µC-Domäne, zumindest nicht in der 8Bit-Klasse.
Keis meiner Projekte in den etlichen Jahren verfolgte die Absicht in
Serie zu gehen, nichtmal direkt nachbaubar mußte es sein. Trotzdem
wurden einge Sachen erfolgreich nachgebaut, die vor Jahren mal hier ins
Forum gestellt hatte.
Selbstverständlich löse ich Probleme durch Nutzung von Interrupts wenn
es das Mittel der Wahl ist. Bin ja mit Z80 und 6502 groß geworden und
habe nach Jahren Pause die kleinen AVR für mich entdeckt.
Natürlich ist es auch privat immer ein Entscheidungsfaktor, ob man den
AVR wechselt oder die Plattform oder ob man seinem Ehrgeit folt "das muß
gehen".
Ich trau mir allerdings die Erfahrung zu, zeitig zu merken, wenn Grenzen
auftauchen.
Wenn da die Frage kommt: ich will wav-Dateien mit meinem Arduino
abspielen (wurde woanders gefragt), könnte ich fragen welche. 8Bit 22kHz
Mono ist machbar ohne sich die Ohren zu brechen von SD-Karte oder
externem Flash.
44,1kHz 16Bit Mono mit externem SPI-Flsdh und externem 12Bit-SPI-DAC
kein Problem, selbst schon gemacht.
Allerdings würde ich fürchten, daß das mit den fertigen Arduino-ich kann
alles aber nichts sonderlich schnell-Libs nicht klappt.
Ist es nun µC quälen, wenn ich sowas dann lieber "zu Fuß" in C schreibe?
Oder in ASM weil mir das Spaß macht und ich es kann?
Ist es quälrn, wenn ich da dann bei einer bestimmten Routine die Takte
zähle damit es klappt? Wenn ich dabei merke daß es nicht gehen kann,
dann wechsle ich eben die Plattform. Ich werde nicht fragen, ob es einen
Geheimbefehl im AVR gibt, der ein PortBit in einem halben CPU-Takt
setzt.
Ich bastle gerade eine kleine Kiste, die letztlich die Daten meiner
Sensoren auf einer Webseite anzeigt. Habe ich schon seit Jahren erst mit
einem AVR-NetIO, dann auf einem RasPi bis es dessen SD-Card zerlegt hat.
Jetzt eben mit ESP8266. Natürlich darf der jetzt im Interrupt den RFM12
bedienen (ist nur als Empfänger). Macht er auch. Mit meinen 5 Jahre
alten C-Sourcen von Mega8 in der ArduinoIDE. Da stört auch digitalWrite
nicht, der 80MHz ESP ist auch mit (hier eher trotz) WLAN schnell genug
dafür.
Die Firmware-Entwicklungszeit ist zweitrangig, es ist Hobby und muß
nicht morgen fertig sein.
Natürlich gint es Probleme, wenn jemadn gerade auf dem neuen Arduino-UNO
eine LED zum Blinken gebracht hat und als nächtes Projekt eine
Quadcopter plant oder einen selbstfahrenden Roboter mit Home-Funktion.
Der schnelle Erfolg mit dem Blinken verführt zu der Meinung "Hurra, ich
kann programmieren".
Allerdings war das wor Jahrzehnten auch nicht anders. Wenn ich jemanden
soviel Basi auf dem C64 beigebracht hatte, daß er eine Uhr programmeiren
konnte, war di nächte Frag auch "und jetzt zeig mir mal schnell, wie man
ein schönes Ballerspiel mit Scrolling in beiden Achsen programmiert".
Damals gab es nur noch kein Internet. :-)
Gruß aus Berlin
Michael
Das Thema mit der "Zikluszeit" beim Arduino
hatte mich auch mal interessiert,
deshalb habe ich aus dem web jetzt ausgegraben...
Hier geht es darum, und Beispielcode ist auch dabei;
http://forum.arduino.cc/index.php?topic=292794.0
MfG
@ Michael U. (amiga)
>Ich quäle auch keine µC, allerdings ist Multitasking z.B. auch keine>µC-Domäne, zumindest nicht in der 8Bit-Klasse.
Quark. Jedes halbwegs komplexere Programm macht Multitasking. Das
geht auch ohne Linux und Win10!
Michael U. schrieb:> warum sollte man rumhacken?
Ich finde es nicht so!
Glaube, dieses Forum lebt davon Meinungen zu eußern und
Erfahrungen auszutauschen.
Es liegt in der Natur der Dinge (oder im Wissenstand) wie und was
die User zum Thema beitragen.
Ich persönlich bin sogar sehr froh drüber, gerade unterschiedliche
Meinungen zu lesen, die geben mir oft einen Anstoß, mich im
web weiter zu informieren und neues aufzuschnappen :-)
...und Lustige Bemerkungen lockern die Athmosphäre.....
Jetzt habe ich nach hinein doch ein schlechtes Gewissen den Beitrag
voreilig zurück gezogen zu haben, nachdem sich der Ulrich so viel Mühe
machte darauf einzugehen. Dachte beim Nachlesen ein paar Minuten später,
ist vielleicht doch nicht so das Thema und drückte den Panikknopf.
Sorry.
Grüße,
Gerhard
>Wenn wir also über Arduino und Codgeschwindigkeiten reden, sollten wir>ganau diese Dinge ausdrücklich vor Augen halten :-)>...Arduino wurde ja gerade für Künstler und nichtprogrammierer>entwickelt!
Hier im Forum gab es mal einen Thread über C++ auf uC. Der war ewig
lang, aber irgendwo hatte einer der C++ Experten Pin-Funktionen, die den
Arduinofunktionen sehr ähnlich waren, mit Templates realisiert. Die
waren genauso schnell wie in Assembler geschrieben.
Eigentlich müsste jemand nur diese Templates in die Arduino-Lib
einarbeiten, dann hätte sich das Problem erledigt.
Kennt Ihr das: Jemand müsste mal .....
JoJoBa schrieb:> Die Fortgeschrittenen setzen Assembler ein, die Anfänger eher die> Arduino-C
Ui, das ist aber ein ganz schmales Brett. Ich kenne keinen
Fortgeschrittenen, der noch in Assembler programmiert.
Der Arduino in C ist eine perfekte Lösung, damit kann man auch bei
größeren Projekten einfach weitermachen.
Man muß nur noch das Programmieren lernen, also weg vom Spaghetticode
und hin zum strukturierten Programmieren (vor dem Coden
Programmablaufplan erstellen).
chris_ schrieb:> Eigentlich müsste jemand nur diese Templates in die Arduino-Lib> einarbeiten, dann hätte sich das Problem erledigt.>> Kennt Ihr das: Jemand müsste mal .....
Dann müssten die Leute aber eine neue Syntax lernen, denn Templates
sehen halt ein bisschen anders aus => Daher wird das wohl auch keinen
Einzug bei Arduino finden.
Es ist eben für Anfänger und als professionelles HAL nicht zu
gebrauchen.
Bei uns in der Firma musste letztes Jahr für einen Kunden seine alte
Hardware einmalig modernisiert werden, in vierzigfacher Ausführung, und
unter strenger Kosteneinhaltung und Lieferungsfrist modernisiert werden
weil der alte Hersteller nicht mehr seine Geräte unterstützen wollte und
es keinen Ersatz auf dem Markt gibt. So wurde auf Arduino MEGA2560 und
eine in-house gemachter Shield zurückgegriffen. Das war eine
komplizierte Anwendung mit viel Communication und Real-time Steuerung
von Motoren und anderer HW und Analogmessungen, PID Schleifen, etz.
Kurz und gut, alles lief Bestens und das Projekt wurde locker
rechtzeitig fertig. Der MEGA2560 hatte keine Probleme sich den
Echtzeitsanforderungen zu stellen. Die FW wurde von einem erfahrenen
Kollegen erstellt und machte überhaupt keine Probleme. Ich schätze, an
die 30-50K Lines an Source Code enstand dabei. Der FLASH des AVR war zu
60% gefüllt. Ich hatte nichts damit zu tun, so, weiß ich das jetzt nicht
genau. Allerdings wurde nicht zu viel Arduino Library Resourcen genutzt.
Viel C++ war in den Modulen dabei.
Das einzige Problem war die Timing wegen des ungenauen Keramik
Resonators den wir durch einen externen XTAL Oszillator ersetzen mußten.
Ein Timer mußte auf 1s in zwei Stunden genau arbeiten und der Keramik
Resonator ist da einfach nicht gut genug dafür.
Gerhard
Gerhard O. schrieb:> Ich schätze, an> die 30-50K Lines an Source Code enstand dabei.
Und die wurden alle in der Arduino IDE getippt? Bei der Vorstellung
graust es mir. Die Arduinos kann man ja normalerweise nicht mal
step-by-step debuggen...
Dr. Sommer schrieb:> Und die wurden alle in der Arduino IDE getippt?
Natürlich nicht. Programmer's Notepad oder Code Blocks, glaube ich,
wars.
Es gibt im IDE nämlich eine Einstellung die es ermöglicht einen externen
Text Editor zu verwenden mit automatischem Check ob sich der Timestamp
ändert. Dann braucht man nur wie üblich auf Build/Load drücken.
Abgesehen davon waren da an die 40+ Source und Header Dateien. Das
Arduino IDE hat ja auch Tabs, wenn auch nicht sehr komfortabel. Aber man
braucht das IDE ja für nicht mehr wie das Bauen der App und Bootloader.
Und dafür reicht's ja.
>Die Arduinos kann man ja normalerweise nicht mal>step-by-step debuggen...
Sooo schlimm war das auch wieder nicht. So viel ich weiß, war nicht viel
debuggen notwendig.
Du machst wirklich aus einem Maulwurfshügel einen Mt. Everest;-)
Fakt ist, daß alle Anforderungen in der erlaubten Zeit erfüllt worden
sind und alles einwandfrei funktionierte. Was mehr kann man erwarten?
Ist mal etwas Anderes um zum Ziel zu kommen. Das Resultat zählt.
mfg,
Gerhard
Gerhard O. schrieb:> Du machst wirklich aus einem Maulwurfshügel einen Mt. Everest;-)
Ich weiß nicht, ich habe die Debugging Funktion der Cortex-M sehr zu
schätzen gelernt, jedes mal wenn ich doch mal einen AVR benutze fluche
ich dass ich nicht hinein schauen kann.
Wenn ihr dir Arduino IDE nur noch zum Kompilieren benutzt, hat sich
deren Sinn doch auch erübrigt, und man kann auch in der jeweils
verwendeten IDE kompilieren & flashen. Und dann kann man auch ein
nicht-Arduino-Board nehmen welches normal geflasht wird, weil man dann
nicht mehr den Einschränkungen der Arduino IDE unterliegt.
Wenn man die Arduino Library und die Arduino IDE nicht mehr wirklich
verwendet, hat man quasi alle "Vorteile" abgelegt und kann Arduino auch
ganz bleiben lassen, oder? Wenn man sowieso eine eigene Platine (euer
Shield) entwickelt, kann man da auch noch nen uC drauf designen.
Dr. Sommer schrieb:> Gerhard O. schrieb:>> Du machst wirklich aus einem Maulwurfshügel einen Mt. Everest;-)>> Ich weiß nicht, ich habe die Debugging Funktion der Cortex-M sehr zu> schätzen gelernt, jedes mal wenn ich doch mal einen AVR benutze fluche> ich daß ich nicht hinein schauen kann.
Ich doch auch. Wenn ich mit STM32s arbeite, weiß ich das schon zu
schätzen. Ist ja klar.
>> Wenn ihr dir Arduino IDE nur noch zum Kompilieren benutzt, hat sich> deren Sinn doch auch erübrigt, und man kann auch in der jeweils> verwendeten IDE kompilieren & flashen. Und dann kann man auch ein> nicht-Arduino-Board nehmen welches normal geflasht wird, weil man dann> nicht mehr den Einschränkungen der Arduino IDE unterliegt.
Naja. Ich war ja nicht fürs Projekt verantwortlich. Mein Kollege wird
natürlich schon einen Grund zu seinem Vorgehen gehabt haben.
Ich habe mal versuchshalber ein Projekt mit CodeVisionAVR gemacht und
man kann von diesem IDE direkt auch den Arduino Boot Loader verwenden.
Also, die ARDUINO IDE ist nicht notwendig. Man kann halt nur die
Hardware nehmen.
AVRDude geht auch unabhängig leicht mit Kommandozeile zu gebrauchen.
Aber das ist je eh ein alter Hut.
>> Wenn man die Arduino Library und die Arduino IDE nicht mehr wirklich> verwendet, hat man quasi alle "Vorteile" abgelegt und kann Arduino auch> ganz bleiben lassen, oder? Wenn man sowieso eine eigene Platine (euer> Shield) entwickelt, kann man da auch noch nen uC drauf designen.
Stimmt alles. Ich verwende die ARduino IDE/LIBS auch nur für Open Source
Projekte von denen ich weiß, daß Arduino gefragt ist. Der Hardware ist
das wurscht solange die SPI Schnittstelle an der Platine zugänglich ist.
Gerhard
Schneller Test, folgendes Programm in der Arduino 1.6.5-IDE:
1
/*
2
Arduino Lib vs C
3
Measure speed of Arduino's digitalWrite()
4
vs direct bitmanipulation
5
*/
6
7
#define USE_ARDUINO
8
9
// the setup function runs once when you press reset or power the board
10
voidsetup(){
11
// initialize digital pin 13 as an output.
12
pinMode(13,OUTPUT);
13
// this part is non critical for the test, thus keep it simple and stupid.
14
// Pin D13 is actually PB5.
15
}
16
17
// the loop function runs over and over again forever
18
voidloop(){
19
#ifdef USE_ARDUINO
20
digitalWrite(13,HIGH);// turn the LED on (HIGH is the voltage level)
21
digitalWrite(13,LOW);// turn the LED off by making the voltage LOW
22
#endif
23
24
#ifndef USE_ARDUINO
25
PORTB^=(1<<PB5);// toggle PB5.
26
#endif
27
}
... aus Faulheit einfach den Blink-Beispiel-Sketch umgestrickt.
Siehe Oszilloskop:
- 500kHz mit Bitmanipulation
- 100kHz via digitalWrite(). (Wohl den Trigger falsch gesetzt wegen 5µs
Periode erkannt.)
Der Preis der Abstraktion und der Abprüfung zahlreicher Nebenbedingungen
in der Arduino-Lib.
Und die Frage aller Fragen: Wenn das 2 Takte braucht, wieso stehen da
nicht 8MHz beziehungsweise 4MHz für die volle Periode? ;)
Dirk K. schrieb:> Und die Frage aller Fragen: Wenn das 2 Takte braucht, wieso stehen da> nicht 8MHz? ;)
Jetzt müsste man mal testen wie sich das hier im Vergleich schlägt:
http://avr.myluna.de/doku.php
Dirk K. schrieb:> Und die Frage aller Fragen: Wenn das 2 Takte braucht, wieso stehen da> nicht 8MHz? ;)
Weil die loop() nicht einer while(1)entspricht.
Aber auch die kleinste Schleife wird Zeit benötigen.
Und Exklusiv-Oder wird dann eher nicht zu sbi optimiert.
Probier mal "PINB = (1<<PB5);" zum toggeln.
Rudolph schrieb:> Und Exklusiv-Oder wird dann eher nicht zu sbi optimiert.> Probier mal "PINB = (1<<PB5);" zum toggeln.
Du meinst wahrscheinlich |= ? So blinkt da wohl eher nichts. ;)
Oder gar, der Fairness halber:
PINB |= (1<<PB5);
PINB &= ~(1<<PB5);
... um dasselbe Konstrukt zu nutzen wie mit digitalWrite()?
LunaAVR? Musste erst nachgucken, was das sein soll: Modernes Basic. Da
schaudert es mich. Basic habe ich seit 1985 nicht mehr angefasst - da
gab es auf dem C=64 für uns Kinder vom Lande noch nichts anderes und war
gleich eingebaut. So etwas rühre ich nicht mehr an. (Zumal da dransteht,
nur für Windows und Linux. Ich nutze Mac OS X.)
Dirk K. schrieb:> Du meinst wahrscheinlich |= ? So blinkt da wohl eher nichts. ;)
nein, er meinte schon das, beachte dass da PINB (!!) und nicht PORTB
steht
Dein Programmvergleich ist auch nicht korrekt,
bei einem machst du in einem loop-DUrchlauf eine Operation,
beim anderen zwei. Dadurch hast du beim ersten den doppelten
Loop-Overhead
Ok, ich stricke heute Abend nach der Arbeit noch mal weiter.
PINB vs PORTB ist schon klar, aber wenn ich einfach den Pin auf 1 setze,
ohne beispielsweise NOT oder ähnlichem, vermute ich, dass da nichts
umspringt. Hier ist aber grad noch der Zustand ENOCOFFEE, nachher mit
klarerem Kopf noch mal ...
Dirk K. schrieb:> PINB vs PORTB ist schon klar, aber wenn ich einfach den Pin auf 1 setze,> ohne beispielsweise NOT oder ähnlichem, vermute ich, dass da nichts> umspringt.
doch, das ist ein Befehl den die neueren AVR haben:
durch Schreiben auf PINB toggelt der Ausgang
Dirk K. schrieb:> void loop() {> #ifdef USE_ARDUINO> digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage> level)> digitalWrite(13, LOW); // turn the LED off by making the voltage> LOW> #endif>> #ifndef USE_ARDUINO> PORTB ^= (1<<PB5); // toggle PB5.> #endif> }
Das ist Apfel mit Birnen vergleichen.
Warum willst Du den Loop Overhead mitmessen und einmal gleich doppelt?
1
voidloop(){
2
for(;;){
3
#ifdef USE_ARDUINO
4
digitalWrite(13,HIGH);// turn the LED on (HIGH is the voltage level)
5
digitalWrite(13,LOW);// turn the LED off by making the voltage LOW
Dirk K. schrieb:> Lese ich so aus dem Datenblatt zum> ATmega328 nicht raus. Nettes Feature.
Kapitel 14.2.2 Toggling the Pin
---
Writing a logic one to PINxn toggles the value of PORTxn, independent on
the value of DDRxn. Note that the SBI instruction can be used to toggle
one single bit in a port.
---
Hallo Falk,
Falk B. schrieb:> @ Michael U. (amiga)>>>Ich quäle auch keine µC, allerdings ist Multitasking z.B. auch keine>>µC-Domäne, zumindest nicht in der 8Bit-Klasse.>> Quark. Jedes halbwegs komplexere Programm macht Multitasking. Das> geht auch ohne Linux und Win10!
naja, die auf einem 8Bit-AVR wäre wohl auch ein klein wenig
problematisch.
Ich habe das so gesagt, weil relativ selten ein OS auf dem 8Bit AVR
läuft.
Wenn Multitasking nur sagen soll, daß mehrere Sachen scheinbar
gleichzeitig bearbeitet werden sollen, dann ist selbst BlinkWithoutDelay
auf dem Arduino bereits Multitasking.
Gruß aus Berlin
Michael
Michael U. schrieb:> naja, die auf einem 8Bit-AVR wäre wohl auch ein klein wenig> problematisch.> Ich habe das so gesagt, weil relativ selten ein OS auf dem 8Bit AVR> läuft
Dir ist aber schon klar, dass es verschiedene Level an Multitasking
gibt?
Den einfachen Scheduler den ich immer benutze um einfaches kooperatives
Multi-Tasking mit typisch vier Tasks zu machen würde ich nicht als
Betriebs-System beschreiben.
Und nein, Interrupts zähle ich nicht zu den "Tasks".
@ Michael U. (amiga)
>Ich habe das so gesagt, weil relativ selten ein OS auf dem 8Bit AVR>läuft.
Das sag es aber EXPLIZIT!
>Wenn Multitasking nur sagen soll, daß mehrere Sachen scheinbar>gleichzeitig bearbeitet werden sollen, dann ist selbst BlinkWithoutDelay>auf dem Arduino bereits Multitasking.
Das ist es auch! Für Multitasking braucht man nicht unbedingt ein OS
oder RTOS.
Falk B. schrieb:> Für Multitasking braucht man nicht unbedingt ein OS> oder RTOS.
Umgekehrt wird da ein Schuh draus.
Es macht Sinn wenn ein OS Multitasking kann.
Was ist überhaupt ein OS?
Ab wann kann man es als solches Bezeichnen?
Ist RTOS schon ein OS?
Die AVRs bringen keinerlei Hardwareunterstürzung für Multitasking mit.
Kein Speicherschutz, nix.
Kooperatives Multitasking in der AVR Welt sieht wohl mehr nach Polling
aus. Klar kann man das sich den Mist schön reden, wird er aber nicht.
Eine Höllenarbeit, jeden Algorithmus so zu zerrupfen, dass er in kleinen
Häppchen abgearbeitet werden kann. Aber wenigstens hat man den
Algorithmus nach dem Umbau verstanden.
Lesbarer wird ein solches Programm, durch die Kur, nicht.
Also: Notwendig, ja, aber schön..?
Ulrich F. schrieb:> Die AVRs bringen keinerlei Hardwareunterstürzung für Multitasking mit.> Kein Speicherschutz, nix.
Was hat Speicherschutz mit Multitaskung zu tun?
Klar ist das hübsch und sicher, aber keine Grundvorraussetzung.
AmigaOS war 1985 auch Multi-Tasking und gänzlich ohne MMU.
Da war es auch ohne Probleme möglich das System zu übernehmen oder
abstürzen zu lassen, Multi-Tasking war das trotzdem.
> Kooperatives Multitasking in der AVR Welt sieht wohl mehr nach Polling> aus. Klar kann man das sich den Mist schön reden, wird er aber nicht.
Kooperatives Multitasking bedeutet, dass ein Task die Kontrolle wieder
abgeben muss, die wird ihm nicht entzogen.
Polling bedeutet, solange zu warten bis ein Ereignis eintritt.
Multitasking wäre jetzt jedesmal auf das Eintreten des Ereignisses zu
prüfen wenn der Task aufgerufen wird.
Hallo,
ich habe es irgendwie geahnt, daß es zur Grundsatzdiskussion wird...
@Ulrich F.: ich stimme Dir und Deinen Fragen voll zu.
Multitasking ist ein Begriff der bestimmte Bedingungen erfüllt.
Die erfüllen die Ansätze auf dem AVR ohne OS nicht.
Für Multitasking ist das OS verantwortlich, es stellt den Scheduler zur
Verfügung, es ist für Kommunikation zwischen den Prozessen
verantwortlich usw.
Speicherschutz ist wichtig, aber nicht zwingend. Musterbeispiel ist das
alte AmigaOS. Preemptives Multitasking, Semaphorenverwaltung usw.
Natürlich konnte jeder Amok laufende Task das ganze System zerlegen...
Trotzdem hat es Spaß gemacht, da zu programmieren.
Polling ist üblich auf kleinen AVR, (Timer-)Interruptgesteuerte
Abarbeitung auch, erinnert mehr an die alten TSR-Programme von MS-DOS.
Letztlich diskutieren wir aber dann darüber, welchen Namen das Kind
bekommen soll.
BlinkWithoutDelay z.B. ist kein Multitasking, die Prozesse sind nicht
unabhängig voneinander, man hat den Prozessor während der Abarbeitung
NICHT für sich allein. Das wäre für mich aber Bedingung, wenn es
Multitasking heißen soll.
Gruß aus Berlin
Michael
@ Ulrich F. (combie)
>> Für Multitasking braucht man nicht unbedingt ein OS>> oder RTOS.>Umgekehrt wird da ein Schuh draus.>Es macht Sinn wenn ein OS Multitasking kann.
Das war gar nicht die Ausgangsfrage.
>Ist RTOS schon ein OS?
Logisch, das steckt ja schon in der Abkürzung drin!
>Die AVRs bringen keinerlei Hardwareunterstürzung für Multitasking mit.>Kein Speicherschutz, nix.
Wozu auch, in der Liga braucht man das nicht!
>Kooperatives Multitasking in der AVR Welt sieht wohl mehr nach Polling>aus.
Nö. Es ist und bleibt kooperatives Multitasking.
> Klar kann man das sich den Mist schön reden, wird er aber nicht.
Jaja.
>Eine Höllenarbeit, jeden Algorithmus so zu zerrupfen, dass er in kleinen>Häppchen abgearbeitet werden kann.
Das machen teilweise sogar die Profis und das sehr gern. Stichwort
Testbarkeit und Determiniertheit.
> Aber wenigstens hat man den>Algorithmus nach dem Umbau verstanden.
Siehst du!
>Lesbarer wird ein solches Programm, durch die Kur, nicht.
Ansichtssache ;-)
>Also: Notwendig, ja, aber schön..?
Doch. Denn auch präemtive Tasks müssen sich meist in State Machines
organisieren.
Universelle Routinen, insbesondere wenn sie auf mehereren
Controllerfamilien laufen sollen, müssen halt Kompromisse machen. Und
wenn I/O Routinen Port und Pin als Variablen erlauben sollen, wirds auf
vielen Plattformen schnell haarig. Bis auf PIC (PIC-Assembler kann ich
noch nicht) und PowerPC (Pins sind sowieso einzeln adressierbar) habe
ich mir schnelle ASM-Routinen dafür geschrieben. Dafür läuft der
folgende Code mit kleinen Anpassungen (Pins, PLL_Setting) inzwischen auf
7 verschiedenen Controllerfamilien (ohne Interrupts sind es noch mehr).
1
#include"board.h"
2
3
#define LED_RED PORT_B,3
4
#define LED_GREEN PORT_D,2
5
6
voiduser_tick()
7
{
8
9
}
10
11
12
main()
13
{
14
intstate=0;
15
16
set_clock(CLOCK_8_16);//PLL setting
17
enable_tick(16000);//1ms Tick interrupt
18
enable_interrupts();
19
set_portpin_output(LED_RED);
20
set_portpin_output(LED_GREEN);
21
22
for(;;)
23
{
24
set_portpin_level(LED_RED,state);
25
set_portpin_level(LED_GREEN,1-state);
26
wait_ticks(500);
27
state=1-state;
28
set_portpin_level(LED_RED,state);
29
set_portpin_level(LED_GREEN,1-state);
30
wait_ticks(500);
31
state=1-state;
32
}
33
}
PORT_B ist dann z.B. eine Konstante, die als Offset auf eine
Registertabelle im Flash verwendet wird. Ebenso mache ich das mit den
Pin-Nummern, für die es eine Tabelle mit meist 8 Maskenwerten gibt. Die
ursprüngliche C-variante war ein Mehrfaches langsamer als eine direkte
I/O-Byte Zuweisung und auch die ASM-Variante braucht noch ca. 5-10x
soviel Takte. Aber damit kann ich leben...
Jörg
@ Michael U. (amiga)
>Multitasking ist ein Begriff der bestimmte Bedingungen erfüllt.
Welche denn?
>Die erfüllen die Ansätze auf dem AVR ohne OS nicht.
Ohne sie zu nennen, kann man die Frage wohl kaum beantworten ;-)
>Für Multitasking ist das OS verantwortlich, es stellt den Scheduler zur>Verfügung, es ist für Kommunikation zwischen den Prozessen>verantwortlich usw.
Nö, das ist eine spezielle Form davon. Ganz allgemein hat das mit einem
OS rein GAR NICHTS zu tun!
>Speicherschutz ist wichtig, aber nicht zwingend. Musterbeispiel ist das>alte AmigaOS.
Weil es damals (tm) technisch nicht verfügbar war.
> Preemptives Multitasking, Semaphorenverwaltung usw.>Natürlich konnte jeder Amok laufende Task das ganze System zerlegen...
Alles richtig, aber alles schon speziell.
>Trotzdem hat es Spaß gemacht, da zu programmieren.
In ASM! Cool!
>Letztlich diskutieren wir aber dann darüber, welchen Namen das Kind>bekommen soll.
Nein, welche Eigenschaft zu Multitasking in seiner Minimalform benötigt
werden.
>BlinkWithoutDelay z.B. ist kein Multitasking, die Prozesse sind nicht>unabhängig voneinander,
Doch.
> man hat den Prozessor während der Abarbeitung>NICHT für sich allein.
Aber sicher! Ausserdem haben das präemtive Tasks auch nur für kurze
Zeit!
>Das wäre für mich aber Bedingung, wenn es>Multitasking heißen soll.
Also ist für dich Multitasking nur auf Mehrkern-CPUs möglich. Damit war
alles davor, auch Win2K etc. KEIN Multitasking. Komische Definition.
Gefällt mir keine Sekunde.
Falk B. schrieb:> @ Michael U. (amiga)>>>Multitasking ist ein Begriff der bestimmte Bedingungen erfüllt.>> Welche denn?>>>Die erfüllen die Ansätze auf dem AVR ohne OS nicht.>> Ohne sie zu nennen, kann man die Frage wohl kaum beantworten ;-)>>>Für Multitasking ist das OS verantwortlich, es stellt den Scheduler zur>>Verfügung, es ist für Kommunikation zwischen den Prozessen>>verantwortlich usw.>> Nö, das ist eine spezielle Form davon. Ganz allgemein hat das mit einem> OS rein GAR NICHTS zu tun!
Ich sage doch, wir befassen uns damit, dem Kind einen Namen zu geben.
Wenn wir davon reden, daß auf einem System irgendwie mehrere Sachen
scheinbar gleichzeitig bearbeitet werden, stimme ich Dir zu.
Ich habe aber die allgemeine Definition von Multitasking nicht erfunden
und die sagt etwas anderes.
Die Frage, was ein OS ist, lassen wir mal außen vor.
Irgendeine Verwaltungseinheit kümmert sich um das Zusammenspiel, der
Scheduler. Egal, wie simple der ist.
Auch beim kooperativen Multitasking entscheider der (und nur der)
welcher Task nach Priotitäten oder Reihenfolge als nächster dran ist.
Jeder Task hat die CPU in dieser Zeit komplett für sich alleine im
eigenen Kontext. Der Scheduler muß sich darum kümmern, alles zu sichern,
was dem vorigen Task gehört (Register, Stackframe usw.).
>> Preemptives Multitasking, Semaphorenverwaltung usw.>>Natürlich konnte jeder Amok laufende Task das ganze System zerlegen...>> Alles richtig, aber alles schon speziell.
Darunter liegt nur noch das alte Windows mit seinem koperativen
Multitasking, anderes OS habe ich jetzt nicht in Erinnerung bzw. bin
nicht damit in Berührung gekommen.
>>Trotzdem hat es Spaß gemacht, da zu programmieren.>> In ASM! Cool!
Nur kurz, 68k-ASM war mir damsl für meine Projekte zuviel Einarbeitung,
also wurde es schlimmer: AmigaE...
>>Letztlich diskutieren wir aber dann darüber, welchen Namen das Kind>>bekommen soll.>> Nein, welche Eigenschaft zu Multitasking in seiner Minimalform benötigt> werden.>>>BlinkWithoutDelay z.B. ist kein Multitasking, die Prozesse sind nicht>>unabhängig voneinander,>> Doch.>> man hat den Prozessor während der Abarbeitung>>NICHT für sich allein.>> Aber sicher! Ausserdem haben das präemtive Tasks auch nur für kurze> Zeit!
Richtig. Bei BlinkWithoutDelay aber nur, weil der Compiler sich darum
kümmert, ein spezielles Stück Software einzubauen, daß die konkret
beutzen Register einer aufgerufenen Funktion rettet und wiederherstellt
usw.
Wenn ich auf einem Multitasking-"OS" einen neuen Task brauche, rufe ich
CreateTask() auf und bekomme mein eigenes Umfeld "von oben".
Natürlich macht eine Abfrage in einer main-loop, ob was zu tun ist und
fer Funktionsaufruf funktionell ähnliches, eigentlich beschreibt aber
Multitasking gerade die organisatorische Trennung dieser Ebenen.
Eigentlich ist das alles nicht meine Schiene, ich nehme da, was für
meine Anwendung am besten passt und frage mich nicht, ob das nun schon
Multitasking in irgendeinem definierten Sinn ist. ;-)
>>>Das wäre für mich aber Bedingung, wenn es>>Multitasking heißen soll.>> Also ist für dich Multitasking nur auf Mehrkern-CPUs möglich. Damit war> alles davor, auch Win2K etc. KEIN Multitasking. Komische Definition.> Gefällt mir keine Sekunde.
Selbstberständlich ist das Multitasking auch in meinem Sinn, es gibt
einen Task-Scheduler, der sich um den Verwaltungskram kümmert, und meine
Software, die ich als Task einhänge und nutze.
Mich kümmert in diesem Momant aber nicht, was da sonst alles im
Hintergrund läuft, ich muß es nichtmal wissen. Auch beim AmiagOS nicht.
Gruß aus Berlin
Michael
Falk B. schrieb:> Also ist für dich Multitasking nur auf Mehrkern-CPUs möglich.
Multitasking in seinen verschiedensten Ausprägungen.
Multithreading.
Prozesse und Prozessorkerne.
Weit über ein 1/2 Jahrhundert Erfahrung und Entwicklungen, auf dem
Gebiet.
Und wie viel haben wir davon auf den kleinen AVRs?
Faustkeile...
Steinzeit, in Sachen Multitasking!
Mehr geben die Ressourcen einfach nicht her.
Einfach mal compilieren und das erzeugte .lss File checken:
PORTB |= (1<<PB2);
80: 2a 9a sbi 0x05, 2 ; 5
PINB = (1<<PB2);
82: 94 e0 ldi r25, 0x04 ; 4
84: 93 b9 out 0x03, r25 ; 3
PORTB ^= (1<<PB2);
86: 85 b1 in r24, 0x05 ; 5
88: 89 27 eor r24, r25
8a: 85 b9 out 0x05, r24 ; 5
Natürlich mit Optimierung, ich habe -Os drin.
Und wie man sieht gewinnt die erste Variante unter C sogar.
Dann eben doch so:
PINB |= (1<<PB2);
82: 1a 9a sbi 0x03, 2 ; 3
Dann bekommt der Compiler das auch richtig optmiert.
Michael U. schrieb:> PINx erfordert nur einen Schreibzugriff, PORTx ist ein> read-modify-write.
Also ist mit PINx schneller?
und warum ist es nur ein schreibzugriff?
weil bei PINx mach ich ja auch ne verODERung....
oder dauert ein XOR länger?
Wolfsente schrieb:> und warum ist es nur ein schreibzugriff?
weil die Hardware das "toggeln" übernimmt. Es muss halt nicht in
Software gemacht werden.
Das ist wie die Betätigung eines Tasters. Bei einen Schalter muss du
vorher nachschauen ob das Licht an oder Aus ist, ein Taster kannst du
einfach drücken.
vielen dank!
Find sowas immer richtig interessant. Ich sollte mich mal mehr mit
assembler beschäftigen, dann könnte man sich sowas auch selber denken :D
Rudolph R. schrieb:> Und wie man sieht gewinnt die erste Variante unter C sogar.>> Dann eben doch so:>> PINB |= (1<<PB2);> 82: 1a 9a sbi 0x03, 2 ; 3
Naja, da ist eigentlich nichts gewonnen. Bei normalen AVRs dauert
sbi/cbi 2 Takte. Also genau so lange wie ein ldi+out. Mit out ist man am
schnellsten Wenn der Compiler das entsprechende CPU-Register außerhalb
der Schleife setzt.
Ein einzelnes Bit an einem Port zu setzen oder löschen, ohne die andern
zu verändern, geht aber nicht per ldi+out. Ist daher zwar genauso
schnell, aber falsch.
Oliver
Laut Datenblatt geht das aber schon - mit diesem speziellen Register.
Habe den Hinweis oben geprüft, steht tatsächlich im ATmega328-DB unter
14.2.2. Toggle Pin.
@Michael U. (amiga)
>> Nö, das ist eine spezielle Form davon. Ganz allgemein hat das mit einem>> OS rein GAR NICHTS zu tun!>Ich sage doch, wir befassen uns damit, dem Kind einen Namen zu geben.
Den Namen haben wir schon, nämlich Multitasking! Die Frage ist, welche
Eigenschaften damit MINDESTENS verbunden sind!
>Wenn wir davon reden, daß auf einem System irgendwie mehrere Sachen>scheinbar gleichzeitig bearbeitet werden, stimme ich Dir zu.
Gut.
>Ich habe aber die allgemeine Definition von Multitasking nicht erfunden>und die sagt etwas anderes.
Und WAS genau?
>Die Frage, was ein OS ist, lassen wir mal außen vor.
Gut.
>Irgendeine Verwaltungseinheit kümmert sich um das Zusammenspiel, der>Scheduler. Egal, wie simple der ist.
Gut.
>Auch beim kooperativen Multitasking entscheider der (und nur der)>welcher Task nach Priotitäten oder Reihenfolge als nächster dran ist.>Jeder Task hat die CPU in dieser Zeit komplett für sich alleine im>eigenen Kontext.
OK.
> Der Scheduler muß sich darum kümmern, alles zu sichern,>was dem vorigen Task gehört (Register, Stackframe usw.).
Nö, das macht schon der Compiler, so weit muss man da praktisch nicht
runter.
>> In ASM! Cool!>Nur kurz, 68k-ASM war mir damsl für meine Projekte zuviel Einarbeitung,>also wurde es schlimmer: AmigaE...
Sachen gibt . . . ;-)
>> Aber sicher! Ausserdem haben das präemtive Tasks auch nur für kurze>> Zeit!>Richtig. Bei BlinkWithoutDelay aber nur, weil der Compiler sich darum>kümmert, ein spezielles Stück Software einzubauen, daß die konkret>beutzen Register einer aufgerufenen Funktion rettet und wiederherstellt>usw.
Das macht er bei jeder 08/15 Funktion! Du bist schon wieder auf dein
präemtives OS fixiert!
>Wenn ich auf einem Multitasking-"OS" einen neuen Task brauche, rufe ich>CreateTask() auf und bekomme mein eigenes Umfeld "von oben".
Sicher, aber das ist ein fortgeschrittener Spezialfall!
>Natürlich macht eine Abfrage in einer main-loop, ob was zu tun ist und>fer Funktionsaufruf funktionell ähnliches, eigentlich beschreibt aber>Multitasking gerade die organisatorische Trennung dieser Ebenen.>Eigentlich ist das alles nicht meine Schiene, ich nehme da, was für>meine Anwendung am besten passt und frage mich nicht, ob das nun schon>Multitasking in irgendeinem definierten Sinn ist. ;-)
Damit hast du aber keine belastbare Definition von "Multitasking".
Meine, ganz allgemein und grundlegende ist die hier.
https://www.mikrocontroller.net/articles/Multitasking#Einleitung
"Multitasking bedeutet ein scheinbar paralleles Ausführen von mehreren
Prozessen auf einem Prozessor"
Ob nun kooperativ, präemtiv oder sonstwas ist egal, das sind spezielle
Umsetzungen des grundlegenden Gedankens! So wie BMW und Mercedes
spezielle Autos sind! Auch der Trabbi ist ein Auto!
@ Ulrich F. (combie)
>Multitasking in seinen verschiedensten Ausprägungen.>Multithreading.>Prozesse und Prozessorkerne.
Sicher, das war aber gar nicht die Frage.
>Weit über ein 1/2 Jahrhundert Erfahrung und Entwicklungen, auf dem>Gebiet.>Und wie viel haben wir davon auf den kleinen AVRs?>Faustkeile...>Steinzeit, in Sachen Multitasking!>Mehr geben die Ressourcen einfach nicht her.
Das war auch nicht die Frage. Sondern ob es auf einem 8 Bit (AVR)
überhaupt angewendet wird. Und das wird es, sehr oft (wenn gleich nicht
bei den "Patienten" des Forums ;-)
Multitasking ohne OS ist gar nicht kompliziert. Man muß nur seine
Programmsicht ein klein wenig umstellen. Immer, wenn auf irgendwas
gewartet werden soll, tut man das nicht direkt, sondern kehrt zum Main
zurück, Und die Stelle, an der man gerade war, merkt man sich als State
(switch/case).
Dafür wird man dann auch belohnt mit mehr Übersichtlichkeit und
Vorhersehbarkeit. Man braucht kein umständlichen Lock-Mechanismen und
Datenübergaben, da jede Task ganz genau weiß, wann sie unterbrochen
werden kann und das nicht dem Zufall überlassen muß.
Endlich Feierabend - Hund geschwenkt, und ran an das Oszilloskop :D
Leicht erweiterter Code, ich denke, da sind jetzt alle Varianten drin:
1
/*
2
Arduino Lib vs C
3
Measure speed of Arduino's digitalWrite()
4
vs direct bitmanipulation
5
*/
6
#define IS_POPE_CATHOLIC 1
7
//#define USE_ARDUINO
8
//#define USE_PINx
9
#define USE_PORTx
10
11
// the setup function runs once when you press reset or power the board
12
voidsetup(){
13
// initialize digital pin 13 as an output.
14
pinMode(13,OUTPUT);
15
// this part is non critical for the test, thus keep it simple and stupid.
16
// Pin D13 is actually PB5.
17
}
18
19
// the loop function runs over and over again forever
20
voidloop(){
21
22
while(IS_POPE_CATHOLIC){
23
#ifdef USE_ARDUINO
24
digitalWrite(13,HIGH);
25
digitalWrite(13,LOW);
26
#endif
27
28
#ifdef USE_PINx
29
PINB=(1<<PB5);// toggle PB5.
30
#endif
31
32
#ifdef USE_PORTx
33
PORTB|=(1<<PB5);
34
PORTB&=~(1<<PB5);
35
#endif
36
}
37
}
Screenshots im Anhang.
1) Arduino-Lib/digitalWrite(): 100 kHz.
2) Bitmanipulation/PINx-Toggle: 2,6 MHz.
3) Bitmanipulation/PORTx: 2,6 MHz. Duty-Cycle der resultierenden PWM ist
geringer als beim "Hardware-gesteuerten Toggle" via PINx.
Also wenn soltest Du das toggle auch zwei Mal machen.
1
#ifdef USE_PINx
2
PINB=(1<<PB5);// toggle PB5.
3
PINB=(1<<PB5);// toggle PB5.
4
#endif
Der einzige Unterschied der da noch bleibt ist das man vorher nicht
wissen muss, wie das Bit stand.
Dirk K. schrieb:> 3) Bitmanipulation/PORTx: 2,6 MHz. Duty-Cycle der resultierenden PWM ist> geringer als beim "Hardware-gesteuerten Toggle" via PINx.
Logisch, da ist ja immer noch die Schleife mit drin.
Beim Toggle auch, nur eben im Moment doppelt.
Das hätte ich nicht erwartet. PINx-Toggle zweimal am Stück - zack, da
sind die 4 MHz :)
Aus Spaß auch noch die XOR-PORTx-Variante abgeprüft: 2 MHz, also wie vom
Assembler-Compilat oben zu erwarten die tatsächlich langsamste Variante
- aber noch immer Welten vor Arduino-Lib.
Hallo,
@Falk Brunner (falk):
naja, ich sehe da keinen direkten Widerspruch.
Dieser Satz steht da ja auch drin:
Das Herz jedes Multitasking-Systems ist der Scheduler. Dies ist ein
Programm, das nach bestimmten Algorithmen überprüft, welcher Prozess als
nächstes die CPU (also Rechenzeit) zugeteilt bekommt. Es gibt
verschiedene Schedulingstrategien: usw.
Die while(1)-Loop ist der Scheduler, hier eben reines kooperatives
Multitasking. Der Scheduler wartet, bis der ausgeführte Task ihm die
Kontrolle zurückgibt.
Eigentlich hatte Rudolph R.(rudolph) um 12:41 schon die beste Definition
geliefert, habe ich wohl übersehen:
> Polling bedeutet, solange zu warten bis ein Ereignis eintritt.> Multitasking wäre jetzt jedesmal auf das Eintreten des Ereignisses zu> prüfen wenn der Task aufgerufen wird.
Beim angesprochenen BlinkWithoutDelay wäre da auch genau der
Unterschied:
ist die Abrfage mach den vergangenen ms in der loop() und diese schaltet
bei Erreichen des Wertes die LED ist es Polling.
Wird eine blink() aufgerufen und dort wird entschieden, was passiert,
ist es kooperatives Multitasking, zumindest, wenn alle Funktionen in der
loop() so behandelt werden. Dann ist das der Scheduler.
Natürlich kann man das beliebig mischen, aber spätestens dann wird die
Beriffsbestimmung eben ein Problem.
Darauf habe ich mich bezogen: nicht alles, was "gleichzeitig" auf einem
AVR gemacht wird, ist Multitasking. Das hat zwingend mit OS u.ä. nichts
zu tun.
Gruß aus Berlin
Michael
>Das hätte ich nicht erwartet. PINx-Toggle zweimal am Stück - zack, da sind die 4
MHz :)
Das nennt sich loop unrolling. Wenn man die Asymmetrie in Kauf nimmt,
geht da noch mehr.
chris schrieb:> Das nennt sich loop unrolling. Wenn man die Asymmetrie in Kauf nimmt,> geht da noch mehr.
Jain, das Ziel war eher Symmetrie im Test und sowieso macht es keinen
Sinn für den Vergleich der Zugrife die Schleife mit drin zu haben.
1
digitalWrite(13,HIGH);
2
digitalWrite(13,LOW);
3
PINB=(1<<PB5);// toggle PB5.
4
PINB=(1<<PB5);// toggle PB5.
5
PORTB|=(1<<PB5);
6
PORTB&=~(1<<PB5);
Das ist soweit äquivalent.
Und wenn man jetzt wissen will, wie schnell die einzelnen Blöcke für
sich sind, dann sollte man sie mehrere Male hintereinander ausführen um
den Einfluss der Schleife los zu werden.