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 Geschwindigkeitswunder Stefan 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.
> Loop > PinX = 1 > PinX = 0 kann es sein das du nicht Arduino sondern BASCOM meinst?
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.
:
Bearbeitet durch User
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.
Das hatten wir hier: Beitrag "Ist Arduino verpönt?" wenn ich mich recht erinnere, brauchte der Arduino-code 150 takte, wo hardwarenahes C 2 brauchte.
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
:
Bearbeitet durch User
@ 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
:
Bearbeitet durch User
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).
Aus den Foren hier kenne ichs nicht, aber das hier habe ich selber schon ausprobiert; http://www.breadboarding.de/arduino-c-befehle/ MfG
Und eine sehr interessante Lektüre, die zu diesem Thread passt ist hier; http://www.uni-koeln.de/phil-fak/muwi/ag/praktikum/assembler_arduino.pdf Gruß!
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
Dr. Uninformed schrieb >Und die wurden alle in der Arduino IDE getippt? http://playground.arduino.cc/Code/Eclipse
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 | void setup() { |
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 | void loop() { |
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? ;)
:
Bearbeitet durch User
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()?
:
Bearbeitet durch User
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.)
:
Bearbeitet durch User
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
Muss man wissen, war mir unbekannt! Lese ich so aus dem Datenblatt zum ATmega328 nicht raus. Nettes Feature.
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 | void loop() { |
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 |
6 | #else
|
7 | PORTB |= (1<<PB5); |
8 | PORTB &= ~(1<<PB5); |
9 | #endif
|
10 | }
|
11 | }
|
@Peter: Das erwähnte ich selbst schon hier: Beitrag "Re: Geschwindigkeit Arduino > C" Aber Danke für die Bestätigung.
:
Bearbeitet durch User
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".
>wo gibt es einen Logikanalyser für 8,-EUR? Nicht ganz 8€ http://www.amazon.de/Saleae-Analyzer-8Channel-saleae-support/dp/B00EEWBPU4
@ 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 | void user_tick() |
7 | {
|
8 | |
9 | }
|
10 | |
11 | |
12 | main() |
13 | {
|
14 | int state=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.
Was ist denn schneller zum toggeln? PINx |= 1<<3; oder PINB ^= 1<<3; oder bleibts sich gleich? Gruß Wolfsente?
Hallo, PINx erfordert nur einen Schreibzugriff, PORTx ist ein read-modify-write. Gruß aus Berlin Michael
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.
Ich habe gerade 6.3us für digitalWrite(13,x) auf einem Arduino Nano gemessen.
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 | void setup() { |
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 | void loop() { |
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.
1 | digitalWrite(13, LOW); |
2 | delayMicroseconds(10); |
3 | |
4 | digitalWrite(13, HIGH); |
5 | digitalWrite(13, LOW); |
6 | digitalWrite(13, HIGH); |
7 | digitalWrite(13, LOW); |
8 | digitalWrite(13, HIGH); |
9 | digitalWrite(13, LOW); |
10 | |
11 | delayMicroseconds(10); |
1 | digitalWrite(13, LOW); |
2 | delayMicroseconds(10); |
3 | |
4 | PINB = (1<<PB5); |
5 | PINB = (1<<PB5); |
6 | PINB = (1<<PB5); |
7 | PINB = (1<<PB5); |
8 | PINB = (1<<PB5); |
9 | PINB = (1<<PB5); |
10 | |
11 | delayMicroseconds(10); |
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.