Arduino Sammelthread

  • Hallo,


    nachdem hier im Forum recht selten Beiträge zum Arduino erscheinen, mache ich den Versuch, diese Beiträge hier zusammenzufassen, damit jeder sie ohne großes Suchen finden kann..


    Es geht hier erstmal um die Funktion


    pulseIn()


    Diese liest ein Rechtecksignal ein und gibt die Flankenbreite des Signals in Mikrosekunden zurück (1 Millionstel Sekunden).


    Da liest man in vielen Foren, daß diese Funktion den Programmablauf zeitverzögert genau wie delay(), weil sie wartet, bis das auszulesende (Rechteck- oder Sinus-) Signal in voller Frequenzbreite durchgegangen ist. Ein Fernsteuerungs-Sender hat eine Flankenbreite von ca. 1-2 ms, jedoch einen Signalabstand von 20 ms. Damit ist das Programm bei jedem Aufruf der Funktion für 20 ms lahmgelegt. Gewöhnlich folgt die Empfehlung, daher mit Interrupts zu arbeiten. Hier ist dazu eine viel einfachere Lösung, die viel unnötige Prozessorzeit einspart:


    long schlepp=0;
    void loop()
    {
    if (schlepp<=0)
    {
    sendersignal=pulseIn(2,HIGH);
    motorspeed=errechne_motorspeed(sendersignal);
    schlepp=50000;
    fahrtregler.write(motorspeed);
    }
    schlepp--;
    }


    ERklärung:
    Das Signal des Senders wird einmal ermittelt und durchgegeben, damit der Motor anläuft. Danach wird das Signal nur noch alle 50.000 Programmdurchläufe neu eingelesen und aktualisiert. Bei den 50000 ist mit einer MPX Smart SX Fernsteuerung und einem RX5 Mlink Empfänger mit bloßem Auge keine Zeitverzögerung erkennbar. Der Motor reagiert sofort auf den Knüppel. Erst weit jenseits von 50000 setzen merkliche Verzögerungen ein.


    Was bringt das jetzt?


    Ich hab dazu mit dem mC Messungen durchgeführt unter Benutzung der Funktion millis(). Es wurden zunächst mal jeweils 1000 Programmdurchläufe gemessen.


    a) pulseln() und Reglersignal bei jedem Programmdurchgang aufgerufen


    Benötigte Zeit: 21 Sekunden = 21.000 ms. Das entspricht dem zu erwartenden Wert für den Signalabstand von 20 ms.


    b) pulseln() und Reglersignal einmal aufgerufen, danach in eine Zählschleife mit 1000 gepackt und das Programm 1000 mal durchlaufen lassen.


    Benötigte Zeit ca 6-15 ms (das ist auch das Intervall für die Aktualisierung des Reglers. Bei 10 ms wären das pro Sekunde 100 neue Signale).


    Das sind 20 Sekunden weniger als ohne Schleife.


    Anders gesagt, wenn der Sender 21 Sekunden aktiv ist, benötigen die Funktionsaufrufe von pulseIn() davon ca. 95% für sich, in denen das Programm nicht auf andere Dinge ansprechbar ist (Ausgangsproblem).


    50.000 Durchgänge wollte ich nicht hochrechnen, die wurden nochmal neu gemessen.


    Ergebnis bei 50000 Programmdurchläufen:


    Messung 1: Funktionsaufruf mit Schleife 50000: = 148 ms. Bedeutet, daß der Fahrtregler ca 6-7 mal pro Sekunde neue Signale empfängt.


    Messung 2: Funktionsaufruf bei jedem Durchgang (also 50000 mal): über 1 Mio. ms oder 17 Minuten 30 Sekunden.


    Das Verhältnis dieser genaueren Messung (weil mehr Meßwerte) beträgt 1055700/148=7000:1;


    Die Laufzeitumgebung wird also um den Faktor 7000 entlastet.


    Anders gesagt, läuft das Programm 7000mal schneller, um andere Aufgaben zu erledigen.


    Mit einer Schleife von 1000 ist der Faktor, zurückgerechnet, 140:1.


    Mit einer Schleife von 50000 ist der Faktor 7000:1.


    Im Vergleich mit der Interrupt-Lösung (bei der das SIgnal ja trotzdem unnötig oft ausgelesen wird, also am Grundproblem gar nichts geändert wird) gewinnt man hier echte Prozessor-Zeit, in der sich das Programm um andere Dinge kümmern kann.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!