-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: SainSmart Arduino UNO R3 Timer

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    05.05.2013
    Beiträge
    8

    SainSmart Arduino UNO R3 Timer

    Anzeige

    Hallo,

    es geht um folgendes: Ich möchte gerne mit dem Arduino das Signal von einem IR-Empfänger dekodieren. Hierzu nutze ich den Timer vom Arduino (das Board hat den Mega328p), da die millis Funktion eine zu geringe Auflösung hat. Das Problem ist jetzt, dass ich nicht verstehe, wie ich ausrechne wie lang ein Signal ist.

    Ich habe folgendes Testprogramm geschrieben, um den Timer besser zu verstehen. Eigentlich sollte alle 10 Sekunden eine Meldung per Serial übertragen werden. Leider geht das hinten und vorne nicht auf:

    Code:
    void setup() {
      Serial.begin(9600);
      setup_timer();
    }
    
    unsigned long x;
    
    void loop() {
      // count 10 seconds
      TCNT1 = 0;
      
      while(TCNT1 < 50000);
      x++; // 50000 = 0,025s
      
      if(x >= 400) { // 10 / 0,025 = 10sec
        Serial.println(x);
        x = 0;
      }
    }
    
    void setup_timer() {
      TCNT1 = 0; // reset the counter
      TIMSK1 = 0; // disable overflow interrupt
      
      // set the registers of the 16 bit timer
      // mode = normal; divide clock by 8
      // this will also start the timer
      TCCR1A = 0;
      TCCR1B = 0x5; // 00000101b
    }
    Wie ich das verstehe:

    TCCR1B = 0x5 heißt, dass die Frequenz des Counters die Frequenz des Quartzes auf dem Board / 8 erhöht wird.
    Auf dem Quarz steht 16000; ich geh mal davon aus, dass die kHz sind und somit das Quartz mit 16000000 Hz läuft.

    1.) 16000000 Hz / 8 = 2000000 Hz
    2.) 1 / 2000000 Hz = 0,0000005 s = 0,5us
    3.) Wenn der Counter = 50000 ist, heißt das es sind 50000 * 0,0000005s = 0,025s vergangen
    4.) 10s / 0,025s = 400

    Heißt also, alle 10 Sekunden sollte der Wert von x auf Serial ausgegeben werden. Ist aber nicht so; was mache ich falsch?

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Hi,

    deine Anfangsberechnungen sind richtig, allerdings machst du einen Fehler, weil ein Timer im AVR nicht von 0 - xxx sondern von xxx - max. Wert ( 8- od. 16Bit) zählt.
    Also:
    1) 16MHz / 8 = 2MHz
    2) 1 / 1MHz = 0.5µs
    3) (65536-50000)*0.5µs = 7768µs = 7.768ms = 0.007768s
    4) 10s / 7768µs = 1287

    Gruß
    Chris

    EDIT:
    Deine Vorangehensweise ist übrigens IMHO auch nicht ganz richtig. Normalerweise benutzt man den Interrupt von einem Timer, um eine bestimmte Aktion auszuführen. Du könntest beim Ovf in eine Sub springen, dort dann x inkrementieren und das dann im Main-Loop abfragen. Oder du multiplizierst die schon vergangen Timer-Ticks mit einer Variable / Konstante. Wenn das Ergebnis dann einen bestimmten Wert erreicht oder überschreitet, kannst du wieder eine Aktion durchführen.
    Geändert von Che Guevara (05.05.2013 um 11:12 Uhr)

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    05.05.2013
    Beiträge
    8
    Hi,

    danke für die Antwort. Zu deinem Hinweis mit dem Interrupt: Ich nutze den Timer um einen IR-Sensor zu dekodieren. Meine Vorgehensweise habe ich mir aus verschiedenen Quellen zusammengeholt.

    Beispiel Start-Bit nach NEC:

    9000µs HIGH, 4500µs LOW

    Anfangs hatte ich etwas in der Art wie:

    Code:
    unsigned long startTime, highPulsTime, lowPulsTime;
    
    void waitForStartSequence() {
      startTime = millis();
    
      while(IsIrHigh); // call macro which checks if ir is high
      
      highPulsTime = millis();
    
      while(IsIrLow);
    
      lowPulsTime = millis();
    
      lowPulsTime -= highPulsTime;
      highPulsTime -= time;
    
      if(highPulsTime >= THE_VALUE_FOR_9600us  IsAlmostEqual(lowPulsTime , THE_VALUE_FOR_4500us, TOLERANCE))
         Serial.println("X");
    }
    Das hat zur Erkennung des Start-Bits soweit funktioniert. Um dann aber die weiteren bits auszulesen scheint millis nicht akkurat genug zu sein. Wie könnte da eine saubere Lösung aussehen?

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Hi,

    also ich würde das Signal auf einen ext. Interrupt-Pin legen (zur Not ginge auch PinChange). Dann würde ich den Timer so initialisieren, dass er alle 10ms (als Beispie) einen Ovf hat. Wenn jetzt dein ext. Interrupt getriggert wird, liest du den aktuellen Zählerstand aus und setzt den Timer wieder auf 0, sodass der nächste Interrupt wieder erst nach 10ms kommen würde. Der ausgelesene Wert enthält dann die Information, wie lange eine Flanke gedauert hat. Wenn nötig müsstest du noch in einem Flag speichern, ob der Pegel high oder low ist.

    Gruß
    Chris

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    05.05.2013
    Beiträge
    8
    Ich komme da echt nicht weiter... Ich habe es jetzt wie folgt versucht:

    Code:
    void setup()
    {
      Serial.begin(9600);
    	
      noInterrupts();
    	
      OCR1A = 0xFFFF - 3000; // Der Wert scheint völlig egal zu sein!
      TCCR1A = 0;
      TCCR1B = 4 | 5; // Mode 4, CTC on OCR1A; divide by 1024
      TIMSK1 = 2;     //Set interrupt on compare match for OCIE1A
      TCNT1 = 0;
    
      interrupts();
    }
    
    ISR(TIMER1_COMPA_vect) {
      Serial.println("X");
    }
    
    void loop()
    {
    }
    In der Zeile OCR1A = 0xFFFF - 3000; habe ich verschiedenste Werte eingetragen, trotzdem wird nur etwa alle 4 Sekunden etwas auf Serial ausgegeben... Wieso ist das so?

    EDIT: Ich habe übrigends das Dingen: http://www.sainsmart.com/arduino-com...no-uno-r3.html

    Leider scheint es dazu kein Datenblatt zu geben...
    Geändert von SACO (05.05.2013 um 18:09 Uhr)

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Hi,

    also zunächst mal, es gibt mit SICHERHEIT ein DB vom ATMega328(p).
    Dann wäre es hilfreich, wenn du das ganze Programm einstellst und nicht nur Ausschnitte. Du rufst nirgends die Setup-Funktion auf.
    Du musst außerdem den Timer nach jedem OVF new vorladen, da sonst nur der erste OVF richtig getimed ist. Ich weiß nicht, was noInterrupts() bzw. Interrupts() bedeutet. Sind das Makros die cli() bzw. sei() beinhalten? Ansonsten fehlt das auch.

    Gruß
    Chris

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    05.05.2013
    Beiträge
    8
    1. Es ging um das Datenblatt des Boards
    2. Ich habe bereits den gesamten Programmcode inkl. setup-Funktion gepostet
    3. Wieso muss ich den Timer nach einem OVF neu laden, wenn ich mit CTC arbeite?

    Ja das sind macros für cli und die andere Funktion. Sind schon in der IDE vorhanden.

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    24
    Beiträge
    1.544
    Von dem Board wirst du wohl kein DB finden, sowas gibts glaube ich nicht. Da gibts dann wohl nur ein paar Schaltpläne und Layout unso.. Wenn du Glück hast.
    Es ist sicherlich nie verkehrt, die Quarzfrequenz ins Programm einzutragen, das erleichtert auch das Lesen / Verständnis durch andere
    Dass du CTC-Mode benutzt hab ich wohl überlesen, dann stimmt das schon so!
    Die Setup-Funktion wird nie aufgerufen!?

    Gruß
    Chris

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    05.05.2013
    Beiträge
    8
    Hm, ok. Auf dem Quarz steht JT 16.000 wenn ich mich nicht irre.

    "Die Setup-Funktion wird nie aufgerufen!? "

    Keine Ahnung. Ich gehe schwer davon aus, dass Sie aufgerufen wird. Standard Aufbau von Arduino Programmen sind halt die beiden Funktionen setup und loop.
    setup wird am Anfang einmal aufgerufen. Und loop unendlich oft. Selber muss man die nicht aufrufen.

    P.S.: Die Setup Funktion ist oben im Code vorhanden. Die Funktion ISR(TIMER1_COMPA_vect) {
    Serial.println("X");
    }

    wird halt immer nur alle 4 Sekunden aufgerufen, egal, was ich in OCR1A schreibe.

  10. #10
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.186
    Hier findest du das Schaltbild des UNO-SMD http://arduino.cc/en/Main/ArduinoBoardUnoSMD
    Mehr gibt es von den Dingern nicht.

    Wenn du in die Zeile OCR1A = 0xFFFF - 3000; das so eingibst, kann ich mir vorstellen das es nicht funktioniert. Du willst von einer hex-Zahl eine dezimal-Zahl abziehen.
    Schreib mal 15625 hinein ohne dem 0xFFFF, dann solltest du jede Sekunde eine ISR bekommen. In der ISR zählst du dann bis 10 und machst dann deine Ausgabe.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. SainSmart uno r3-atmega328
    Von Droggelbecher im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 18
    Letzter Beitrag: 04.01.2013, 12:57
  2. Arduino Uno .... [GELÖST]
    Von Jonas15 im Forum Arduino -Plattform
    Antworten: 0
    Letzter Beitrag: 27.03.2012, 22:08
  3. Arduino Uno mit BASCOM
    Von uddo im Forum Arduino -Plattform
    Antworten: 0
    Letzter Beitrag: 14.02.2012, 20:22
  4. Arduino uno ... need help
    Von Leftbehindesp im Forum Arduino -Plattform
    Antworten: 3
    Letzter Beitrag: 09.02.2012, 12:46
  5. [ERLEDIGT] [ARDUINO] 2 Motoren + Servo mit dem Arduino Uno steuern
    Von Torrentula im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 31.08.2011, 17:31

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •