Go Down

Topic: Nano Timer2 und delay (Read 1 time) previous topic - next topic

1udo1

Feb 28, 2018, 08:56 pm Last Edit: Mar 01, 2018, 12:48 am by uwefed
Hallo,

am PWM-Pin9 des Nano ist ein Servo angeschlossen. Er dreht von links nach rechts in einer whileschleife.

Zum Checken der Anfangspositionen soll das Programm ein paar Sekunden warten, bis der Servo anläuft. Mit delay(5000) funktioniert das Programm nicht mehr. Ohne delay(5000) ist alles o.k.

Meine Frage:

Die Timer sind für Servo und delays wahrscheinlich schon irgendwo vorkonfiguriert. Kann ich die (Header?)-Dateien für die Timer für meine Zwecke editieren?

Für Servo.h ist wohl Timer1 reserviert. Für delay(5000) ist doch Timer0 zuständig, der wahrscheinlich für delay(5000)zur Verfügung steht. Aber die delay(5000) blockt das Programm.

Kann jemand dazu etwas sagen?

Hier der Code
Code: [Select]
// mit delay(5000) in der loop bleibt das Programm hängen

#include <Servo.h>

Servo servo1;  // create servo object to control a servo
volatile int count=0, pos=40;

void setup()
{
  pinMode(9, OUTPUT);
  noInterrupts();    // disable all interrupts
 TCCR2A = 0;
 TIMSK2 |= (1 << TOIE2);   // enable timer2 overflow interrupt
 interrupts();    // enable all interrupts

 servo1.attach(9);  // attaches the servo on pin 9 to the servo object
}

ISR(TIMER2_OVF_vect)
{
   count++;
}

void loop()
{
 digitalWrite(9, LOW);
 //delay(5000);
 digitalWrite(9, HIGH);
 
 while(1)
 {
   if(count==460)
       {
                 if(pos==40)   // links
                 {
                        count=0;
                      pos=140;
                }
                       else
                         {  
                               if(pos==140)
                               {                    
                                count=0;
                                 pos=40;
                               }
                         }
       }//count
                   servo1.write(pos);
 }//while
}

Tommy56

Setze Deinen Sketch bitte in Codetags (</> oben links im Forumseditor), damit er für alle lesbar ist.
Delay blockiert, das hast Du richtig erkannt. Du solltest Dich für Zeitsteuerungen, die nicht blockieren, mit millis() und der Nachtwächtererklärung beschäftigen.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

1udo1

#2
Feb 28, 2018, 10:57 pm Last Edit: Mar 01, 2018, 01:04 am by uwefed
Hi Tommy56,

stimmt .... hatte vergessen den Code mit dem Steuerzeichen abzuschließen. Hier noch einmal

Ich brauche Sekunden. Millisekunden sind zu kurz. Was ist Nachtwächtererklärung? Ein Scherz? Habe ich noch nie gehört. Falls es Tutorialfleiss bedeuten soll, den vollziehe ich permanent, ohne eine Lösung gefunden zu haben.

Also nochmal der Code mit Steuerzeichen:

Code: [Select]
// mit delay(5000) in der loop bleibt das Programm hängen

#include <Servo.h>

Servo servo1;  // create servo object to control a servo
volatile int count=0, pos=40;

void setup()
{
  pinMode(9, OUTPUT);
  noInterrupts();    // disable all interrupts
 TCCR2A = 0;
 TIMSK2 |= (1 << TOIE2);   // enable timer overflow interrupt
 interrupts();    // enable all interrupts

 servo1.attach(9);  // attaches the servo on pin 9 to the servo object
}

ISR(TIMER2_OVF_vect)
{
   count++;
}

void loop()
{
 digitalWrite(9, LOW);
 //delay(5000);
 digitalWrite(9, HIGH);
 
 while(1)
 {
   if(count==460)
       {
                 if(pos==40)   // links
                 {
count=0;
                      pos=140;
                }
                       else
                         {  
                               if(pos==140)
                               {                    
                                count=0;
                                 pos=40;
                               }
                         }
       }//count
                   servo1.write(pos);
 }//while
}

DrDiettrich

Für richtige Darstellung den Code auswählen und dann auf </> klicken, damit der Code so aussieht:
Code: [Select]
   if(count==460)

Wie oft ist count==460?

Das while(1) in loop() ist schon mal ganz schlechter Programmierstil, um nur ein unverständliches Konstrukt zu nennen.

1udo1

ohne while() würde doch  delay(5000)permanent in der loop aufgerufen werden. Die Zeitverzögerung soll nur 1x beim Start des Programms ausgeführt werden, um die Anfangsposition der Servos zu checken.

Code: [Select]
 

void loop()
{

      digitalWrite(9, LOW);
      //delay(5000);
     digitalWrite(9, HIGH);

    while()
   {
       // Steuerung der Servos
   }
}



An meine Ratgeber: Denkt bitte daran, daß es hunderte User gibt, die vieles erst testen und ausprobieren müssen, um zu sehen, ob es funzt oder nicht. Dabei ist es sehr wahrscheinlich, daß der Programmierstil keinen Blumentopf gewinnen kann. Deshalb ist das Forum ja da, um dem Einsteiger auf die Sprünge zu helfen. Wird oft vergessen.

uxomm

Für Dinge die nur einmal beim Start ausgeführt werden sollen wurde beim Arduino setup "erfunden". Bei Loop war wohl die Idee, dass es immer wieder "loopen" soll. :)
Always decouple electronic circuitry.

Tommy56

An meine Ratgeber: Denkt bitte daran, daß es hunderte User gibt, die vieles erst testen und ausprobieren müssen, um zu sehen, ob es funzt oder nicht. Dabei ist es sehr wahrscheinlich, daß der Programmierstil keinen Blumentopf gewinnen kann. Deshalb ist das Forum ja da, um dem Einsteiger auf die Sprünge zu helfen. Wird oft vergessen.
Von den Anfängern wird oft vergessen, dass das Erlernen der Grundlagen ihr Verständnis der angebotenen Hilfe stark verbessert.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

postmaster-ino

Hi
Für Dinge die nur einmal beim Start ausgeführt werden sollen wurde beim Arduino setup "erfunden". Bei Loop war wohl die Idee, dass es immer wieder "loopen" soll. :)
Das soll DIr sagen:
Packe Dein PIN AN und AUS, mit dem delay() ans Ende von Setup - dann wird Das genau 1x, ganz kurz vor loop() aufgerufen und loop kann, wie Deine while-Schleife, unendlich oft durchlaufen werden.

Beim 'normalem' C++-Programm wäre die Haupt-Funktion die main() - dort müsstest Du do einen Kniff wohl einbringen, um diese Funktionalität zu erhalten.
Der Arduino hat diese main() so zu sagen 'onbord', quasi
mail(){
 setup();
 while(1){
   loop();
 }
}
MfG
anscheinend ist Es nicht erwünscht, einen Foren-internen Link als 'Homepage' einzubinden, damit JEDER nur einen Klick von combie's Liste zum Thema State-Maschine entfernt ist.
... dann eben nicht ...

Doc_Arduino

#8
Mar 01, 2018, 08:07 pm Last Edit: Mar 01, 2018, 08:09 pm by Doc_Arduino
Hallo,

auch in der normalen/klassischen µC Programmierung benötigt man dazu keine Kniffe.

Bei Arduino sind das 2 getrennte Funktionen.  

Code: [Select]
void setup()
{
}

void loop()
{
}



Ansonsten ist das while(1) verschachtelt in der main().

Code: [Select]

int main(void)  // setup
{  
   ...
  
      
   while (1) // Hauptprogramm "loop"
   {  
      ...
   }
}



setup entspricht main() und loop() entspricht while(1).  Mehr ist das nicht. Für eine von beiden Varianten muss man sich entscheiden.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Klaus_ww

Quote
Für eine von beiden Varianten muss man sich entscheiden.
Wobei die zweite bei zeitkrischer Verarbeitung schneller ist - habe ich hier im Forum gelernt und kann das bestätigen.
Freizeit-Programmierer mit moderatem Ehrgeiz besseren Code zu schreiben.

1udo1

FUNZT!

Danke allen, die helfen konnten ......

Für die Neueinsteiger, die etwas Ähnliches programmieren wollen. Der Code ist o.k.

Code: [Select]


// Servo Timer2 NANO   

#include <Servo.h>
 volatile int count=0, pos=0;

Servo servo; 
   
void setup()
{
     noInterrupts();   
     TCCR2A = 0;
     TCCR2B = 1 << CS10 | 1 << CS11 |  1 << CS12;  // 1/1024
   
     TIMSK2 = (1 << TOIE2);   
     interrupts();   
     servo.attach(11);
     servo.write(0);
    delay(4000);
  }


ISR(TIMER2_OVF_vect)
{
    count++;
}

void loop()
{
      switch (count)
    {
    case 146: pos=150; servo.write(pos);  break;
    case 292:  pos=50; servo.write(pos);count=0; break;
    }
}

combie

Quote
Der Code ist o.k.
Ist er nicht!

Auf die Variable count, in loop() wird weiterhin nicht atomar zugegriffen.
Das kann dir jederzeit auf die Füße fallen.

Weiterhin wird servo.write(pos), ca 2000 mal nacheinander, innerhalb von 22ms, aufgerufen.
Gut wenn das noch klappt, aber das kann nach einem Library Update schon ganz anders ein

Quote
Für die Neueinsteiger, die etwas Ähnliches programmieren wollen.
Schön, dass du ihn zeigst!
Aber ein gutes Beispiel ist er (noch) nicht.
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

michael_x

#12
Mar 02, 2018, 04:41 pm Last Edit: Mar 02, 2018, 11:44 pm by michael_x
Für die Neueinsteiger, die etwas Ähnliches programmieren wollen (der Servo fährt in festem Rhythmus zwischen zwei Positionen hin und her), wäre dies die übliche Herangehensweise:

Code: [Select]
#include <Servo.h>

Servo servo;
const byte SERVOPIN = 9;
const byte POS_A= 150;
const byte POS_B= 50;
const int DAUER_A = 400;
const int DAUER_B = 800;

unsigned long start;
bool A;

void setup() {
   servo.attach(SERVOPIN);
   servo.write(0);
   delay(5000); // wo soll das Problem liegen ?
   A = false; // fängt mit POS_A an ...
}


void loop() {
 if (A  && (millis() - start >= DAUER_A)) {
   servo.write(POS_B);
   start = millis();
   A = false;
 } else if (!A && (millis() - start >= DAUER_B)) {
   servo.write(POS_A);
   start = millis();
   A = true;
 }

// hier kann noch alles mögliche andere gemacht werden

}
ungetestet

1udo1

Hallo combie,

Danke, daß Du Dich dem Thema so widmest. Ich kann mit Deinem Fachwissen nicht mithalten, weil ich nur wenige Programme im Jahr schreibe.

Würde aber gerne mal zu meinem Verständnis Folgendes wissen.

In der ISR wird "count" ca. alle 22ms hochgezählt. In der switch wird erst bei "count=146" der Motor angesprochen, also 146 mal 22ms. Das sind dann alle 3,2 Sekunden. Du schreibst aber 2000 mal innerhalb von 22ms. Kannst Du mir mal weiterhelfen? Der Motor wirst doch erst im "case" 146 angesprochen, oder?

Wenn es eine längere Erklärung erfordert, dann will ich Dich nicht weiter bemühen.


Code: [Select]



ISR(TIMER2_OVF_vect)
{
    count++; // ca. alle 22ms
}

void loop()
{
      switch (count)
    {
    case 146: pos=150; servo.write(pos);  break; // 146 mal 22ms sind 3,2 Sekunden
    case 292:  pos=50; servo.write(pos);count=0; break;
    }
}

DrDiettrich

In der ISR wird "count" ca. alle 22ms hochgezählt. In der switch wird erst bei "count=146" der Motor angesprochen, also 146 mal 22ms. Das sind dann alle 3,2 Sekunden. Du schreibst aber 2000 mal innerhalb von 22ms.
Dieser Kommentar bezog sich offensichtlich auf Deine ursprüngliche Version.

Go Up