{"id":696,"date":"2017-01-26T09:44:08","date_gmt":"2017-01-26T08:44:08","guid":{"rendered":"http:\/\/moba.noethlich.info\/?page_id=696"},"modified":"2017-01-26T09:57:08","modified_gmt":"2017-01-26T08:57:08","slug":"programmieren-ohne-delay","status":"publish","type":"page","link":"http:\/\/moba.noethlich.info\/?page_id=696","title":{"rendered":"Programmieren ohne &#8218;delay&#8216;"},"content":{"rendered":"<p>Eines der einfachsten Programme f\u00fcr einen Mikroprozessor ist der \u201eBlink\u201c-Sketch, der dementsprechend f\u00fcr die meisten Einsteiger Grundlage der ersten eigenen Programme ist:<\/p>\n<p><code>\/\/ the setup function runs once when you press reset or power the board<br \/>\nvoid setup() {<br \/>\n&nbsp; \/\/ initialize digital pin LED_BUILTIN as an output.<br \/>\n&nbsp; pinMode(LED_BUILTIN, OUTPUT);<br \/>\n}<br \/>\n\/\/ the loop function runs over and over again forever<br \/>\nvoid loop() {<br \/>\n&nbsp; digitalWrite(LED_BUILTIN, HIGH);&nbsp;&nbsp; \/\/ turn the LED on (HIGH is the voltage level)<br \/>\n&nbsp; delay(1000);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ wait for a second<br \/>\n&nbsp; digitalWrite(LED_BUILTIN, LOW);&nbsp;&nbsp;&nbsp; \/\/ turn the LED off by making the voltage LOW<br \/>\n&nbsp; delay(1000);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ wait for a second<br \/>\n}<\/code><\/p>\n<p>Eine LED wird im Sekunden-Takt ein- und ausgeschaltet, die Befehlskette lautet einfach<\/p>\n<ul>\n<li>&nbsp;LED einschalten<\/li>\n<li>&nbsp;1000 Millisekunden warten<\/li>\n<li>&nbsp;LED ausschalten<\/li>\n<li>&nbsp;1000 Millisekunden warten \u2026<\/li>\n<\/ul>\n<p>&nbsp;Danach geht\u00b4s wieder von vorne los.<\/p>\n<p>Versucht der Programmier-Einsteiger nun, dieses Programm z.B. um weitere LEDs zu erweitern, so st\u00f6\u00dft er schnell auf die Problematik der Abh\u00e4ngigkeit und erh\u00e4lt auf seine Fragen die lapidare Antwort \u201eschau\u00b4 Dir &#8218;BlinkWithoutDelay an&#8216; \u2013 da ist das Prinzip erkl\u00e4rt\u201c.<\/p>\n<p>Zwar ist m.E. im zugeh\u00f6rigen Tutorial <a href=\"https:\/\/www.arduino.cc\/en\/Tutorial\/BlinkWithoutDelay\" target=\"_blank\">https:\/\/www.arduino.cc\/en\/Tutorial\/BlinkWithoutDelay<\/a> das Prinzip tats\u00e4chlich recht anschaulich erkl\u00e4rt \u2013 der Einsteiger h\u00e4lt den Aufwand aber zun\u00e4chst nicht f\u00fcr gerechtfertigt, denn das Problem l\u00e4sst sich ja vielleicht auch mit mehreren &#8218;delay&#8216;-Befehlen l\u00f6sen:<\/p>\n<p>Anstelle der Befehlskette<\/p>\n<ul>\n<li>Pizza in die Mikrowelle<\/li>\n<li>10 Minuten warten<\/li>\n<li>Pizza aus der Mikrowelle holen<\/li>\n<li>eMail pr\u00fcfen<\/li>\n<\/ul>\n<p>pr\u00fcft man z.B. alle 2 Minuten die eMails und kommt zu der Befehlskette<\/p>\n<ul>\n<li>Pizza in die Mikrowelle<\/li>\n<li>eMail pr\u00fcfen<\/li>\n<li>2 Minuten warten<\/li>\n<li>eMail pr\u00fcfen<\/li>\n<li>2 Minuten warten<\/li>\n<li>eMail pr\u00fcfen<\/li>\n<li>2 Minuten warten<\/li>\n<li>eMail pr\u00fcfen<\/li>\n<li>2 Minuten warten<\/li>\n<li>eMail pr\u00fcfen<\/li>\n<li>2 Minuten warten<\/li>\n<li>Pizza aus der Mikrowelle holen<\/li>\n<\/ul>\n<p>Wenn man sich das bildlich vorstellt, wird schnell klar, dass so niemand arbeitet und dass das sp\u00e4testens dann nicht mehr funktioniert, wenn tats\u00e4chlich eine eMail kommt, oder man parallel dazu noch eine Tasse Tee (drei Minuten) zubereiten m\u00f6chte.<\/p>\n<p>Schon in dem einfachen &#8218;Blink&#8216;-Programm steht als Kommentar \u201ethe loop function runs over and over again forever\u201d \u2013 und genau darum geht es: Die Ausf\u00fchrung des Programms nicht anzuhalten, sondern ganz gezielt Befehle auszuf\u00fchren, wenn sie dran sind. Man stellt die Pizza in die Mikrowelle und merkt sich die Startzeit, gie\u00dft den Tee auf und merkt sich die Startzeit und pr\u00fcft regelm\u00e4\u00dfig, ob die 10 Minuten f\u00fcr die Pizza oder die 3 Minuten f\u00fcr den Tee abgelaufen sind.<\/p>\n<p>Genau das macht &#8218;BlinkWithoutDelay&#8216; nun f\u00fcr die LED \u2013 es pr\u00fcft endlos, ob die Zeit bis zum n\u00e4chsten Umschalten abgelaufen ist und wenn das Ergebnis \u201eja\u201c lautet, wird es ausgef\u00fchrt:<\/p>\n<p><code>void loop() {<br \/>\n&nbsp;&nbsp;unsigned long currentMillis = millis();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ aktuelle Zeit bestimmen<br \/>\n&nbsp;&nbsp;if (currentMillis - previousMillis &gt;= interval) {&nbsp;&nbsp; \/\/ Zeitintervall abgelaufen ?<br \/>\n&nbsp;&nbsp;previousMillis = currentMillis; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Schaltzeitpunkt speichern<br \/>\n&nbsp;&nbsp;if (ledState == LOW) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ LED umschalten<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;ledState = HIGH;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;else{<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;ledState = LOW;<br \/>\n&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;digitalWrite(ledPin, ledState);<br \/>\n&nbsp;&nbsp;}<br \/>\n}<\/code><\/p>\n<p>Beim Blinken einer LED sieht man nun leider tats\u00e4chlich keinerlei Vorteil \u2013 das Programm erscheint dem Einsteiger nur viel un\u00fcbersichtlicher. Ich habe es daher mal f\u00fcr 5 LEDs an einem ATtiny85 erweitert. F\u00fcr den Einsatz auf einem Arduino sind nat\u00fcrlich auch mehr als 5 LEDs m\u00f6glich und die Portnummern anzupassen. Das Programm ist nur unwesentlich gr\u00f6\u00dfer, kann aber nun 5 LEDs unabh\u00e4ngig mit verschiedenen Frequenzen und unsymmetrisch (High-Low-Verh\u00e4ltnis) blinken lassen, weil pausenlos nacheinander f\u00fcr alle LEDs gepr\u00fcft wird, ob sie geschaltet werden m\u00fcssen \u2013 das ist mit Verwendung von &#8218;delay&#8216; so nicht mehr zu realisieren.<\/p>\n<p><code>int ledZahl = 5;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Anzahl der LEDs<br \/>\nint ledPin[] = {0, 1, 2, 3, 4};&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Pins der LEDs<br \/>\nunsigned long currentMillis = 0;<br \/>\nunsigned long previousMillis[] = {0, 0, 0, 0, 0};<br \/>\nint interval[] = {750, 800, 850, 950, 1000};&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Blink-Intervalle<br \/>\nint highlowq[] = {5, 5, 5, 2, 2};<br \/>\nvoid setup() {<br \/>\n&nbsp;&nbsp;for (int i = 0; i &lt; ledZahl; i++) {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;pinMode(ledPin[i], OUTPUT);<br \/>\n&nbsp;&nbsp;}<br \/>\n}<br \/>\nvoid loop() {<br \/>\n&nbsp;&nbsp;currentMillis = millis();<br \/>\n&nbsp;&nbsp;for (int i = 0; i &lt; ledZahl; i++) { &nbsp;&nbsp;&nbsp;&nbsp;if(currentMillis - previousMillis[i] &gt; interval[i]) {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;previousMillis[i] = currentMillis;<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digitalWrite(ledPin[i], HIGH);<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;else if(currentMillis - previousMillis[i] &gt; interval[i]\/highlowq[i]) {<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digitalWrite(ledPin[i], LOW);<br \/>\n&nbsp;&nbsp;&nbsp;&nbsp;}<br \/>\n&nbsp;&nbsp;}<br \/>\n}<\/code><\/p>\n<p>Der prinzipielle Aufbau eines Programms ohne &#8218;delay&#8216; unterscheidet sich also grundlegend von Befehlsketten mit &#8218;delay&#8216; \u2013 und deshalb kann man ein Programm auch kaum \u201emal eben umschreiben\u201c. Bei der Erstellung eines Programms ist es also sinnvoll, schon von Anfang an m\u00f6glichst ohne &#8218;delay&#8216; zu arbeiten \u2013 sowohl um das Prinzip zu lernen, als auch um sp\u00e4ter bei Erweiterungsw\u00fcnschen nicht wieder komplett von vorne beginnen zu m\u00fcssen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Eines der einfachsten Programme f\u00fcr einen Mikroprozessor ist der \u201eBlink\u201c-Sketch, der dementsprechend f\u00fcr die meisten Einsteiger Grundlage der ersten eigenen Programme ist: \/\/ the setup function runs once when you press reset or power the board void setup() { &nbsp; \/\/ initialize digital pin LED_BUILTIN as an output. &nbsp; pinMode(LED_BUILTIN, OUTPUT); } \/\/ the loop [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":662,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-696","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=\/wp\/v2\/pages\/696","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=696"}],"version-history":[{"count":7,"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=\/wp\/v2\/pages\/696\/revisions"}],"predecessor-version":[{"id":704,"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=\/wp\/v2\/pages\/696\/revisions\/704"}],"up":[{"embeddable":true,"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=\/wp\/v2\/pages\/662"}],"wp:attachment":[{"href":"http:\/\/moba.noethlich.info\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=696"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}