-         

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

Thema: counter Problem (SRF05 Ultraschallsensor C code)

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    27.03.2009
    Beiträge
    96

    Beitrag counter Problem (SRF05 Ultraschallsensor C code)

    Anzeige

    Hallo,

    Ich habe vor den srf05 ultraschall sensor an meinen Asuro zu bauen. Das hat mit Bascom auch schon wunderbar funktioniert aber mit c will es nicht so wie ich es möchte.

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <avr/io.h>
    #include <inttypes.h>
    #include <util/delay.h>
    #include "asuro.h"
    
    int main(void)
    {
    
      Init();
      
      uint16_t ergebnis;
      char buffer [20];
      ergebnis = 0;
     
    
      while (1)
      {     
    
         DDRC |= (1<<PC3);              // PC3 Ausgang
         PORTC |= (1<<PC3);             // PC3 High
         _delay_us(20);                 // warte 20 µSekunden
         PORTC &= ~(1<<PC3);           // PC3 Low
         DDRC &= ~(1<<PC3);            // PC3 Eingang
         while(!(PINC & (1<<PC3)));   // tue solange PC3 nicht 1 ist nichts
         TCNT0 = 0;                    // setze Timer0 auf 0
         TCCR0 = (1<<CS01);            // starte timer Prescaler 8
         while((PINC & (1<<PC3)));    // tue solange PC3 auf 1 ist nichts
         TCCR0 = (0<<CS01);           // Stoppe timer
         
         ergebnis = TCNT0;              //setze Timerergebnis in Variable ergebnis 
         
         SerPrint("\n\r Ergebnis: \n\r"); 
         itoa(ergebnis, buffer, 10); //übersetze (int)ergebnis in ASCII
         SerPrint(buffer);              //übertragung des Ergebnisses über RS232
         _delay_ms(500);            //warte 500ms
      }
    }
    Der Timer müsste nach meinem Verständnis von 0 bis 256 zählen wenn das echo signal startet und wenn das Echo signal aufhört gibt der Timer seinen Wert an die Variable 'ergebnis'. Allerdings weiß ich das der timer wenn er die 256 erreicht hat wieder von 0 beginnt. Das ist wahrscheinlich auch der Grund warum ich wirre Werte von 0 bis 256 im Hyperterminal erhalte. Denn das Echo Signal kann ja länger anhalten als ein ?Overflow? des Timers. Ich hoffe mir kann jemand erklären wie ich feststellen kann wie häufig ein Overflow statt gefunden hat.

    P.s.: Ich habe schon die Suche benutzt und auch code gefunden, aber jeder dieser codes funktionierte mit dem Timer im normalen Modus.

    Ich hoffe ich habe jetzt nicht zu viel schwachsinn geschrieben

    MfG Maxtronik

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Zitat Zitat von Maxtronik Beitrag anzeigen
    Der Timer müsste nach meinem Verständnis von 0 bis 256 zählen
    8Bit geht von 0..255
    Das hat sich aber in Bascom nicht anders verhalten, Du musst es dort doch auch gelöst haben, wenn's funktionieren sollte.
    Denn das Echo Signal kann ja länger anhalten als ein ?Overflow? des Timers.
    Möglich, Du machst ja keine Angaben zur Taktfrequenz, aber bei einem Takt von 8MHz käme der Schall 8,5cm weit bis zum Overflow.
    Ich hoffe mir kann jemand erklären wie ich feststellen kann wie häufig ein Overflow statt gefunden hat.
    Indem Du eine Overflow ISR einbaust und dort eine Variable erhöhst. Pollen des Timeroverflowflags im letzten "while" würde auch gehen.
    mit dem Timer im normalen Modus.
    Was ist "normal" in diesem Zusammenhang, bzw. warum sollte der Timerbetrieb hier un-normal sein ?

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    27.03.2009
    Beiträge
    96
    Danke erstmal,

    Pollen des Timeroverflowflags im letzten "while" würde auch gehen.
    Ich hoffe ich habe deinen Tipp richtig verstanden und umgesetzt. Der Code funktioniert so weit, allerdings bin ich mit der geringen Auflösung nicht ganz zufrieden.

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <avr/io.h>
    #include <inttypes.h>
    #include <util/delay.h>
    #include "asuro.h"
    
    int main(void)
    {
    
      Init();
      
      uint16_t ergebnis;
      char buffer [20];
      ergebnis = 0;
     
    
      while (1)
      {     
    
         DDRC |= (1<<PC3);              // PC3 Ausgang
         PORTC |= (1<<PC3);             // PC3 High
         _delay_us(20);                 // warte 20 µSekunden
         PORTC &= ~(1<<PC3);           // PC3 Low
         DDRC &= ~(1<<PC3);            // PC3 Eingang
         while(!(PINC & (1<<PC3)));   // tue solange PC3 nicht 1 ist nichts
         TCCR1B = (1<<CS11);            // starte timer Prescaler 8 (Quarz 8Mhz)
         TCNT1 = 0;                    // setze Timer0 auf 0
         while((PINC & (1<<PC3)))
         {
             if (TIFR & (1<<TOV1))
             {
                 ergebnis = ergebnis + 1;
                 TIFR = (1<<TOV1);
             }
         }
         TCCR1B &= ~(1<<CS11);           // Stoppe timer
         
         itoa(ergebnis, buffer, 10); //übersetze (int)ergebnis in ASCII
         ergebnis = 0;
         SerPrint("\n\r Wen Ergebnis: \n\r"); 
         SerPrint(buffer);              //übertragung des Ergebnisses über RS232
         _delay_ms(500);            //warte 500ms
      }
    }
    Ich habe mich auch im Wiki über Overflow ISR schlau gemacht. Das bedeutet doch, dass eine Variable in einem Interrupt die Overflows zählt? Ich dachte mir, dass es so wie ich es jetzt gemacht habe einfacher ist.

    Was ist "normal" in diesem Zusammenhang, bzw. warum sollte der Timerbetrieb hier un-normal sein ?
    Der Timer könnte doch auch im CTC Modus laufen. Wenn der Timer im CTC modus läuft, bedeutet das dann, dass ich eine Zahl vorgeben kann bis der Overflow passiert. Zum Beispiel so, dass der Timer von 0 - 500 zählt bis ein Overflow geschieht? (Da bin ich noch ein wenig verwirrt)

    MfG Maxtronik

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Hmmm, warum jetzt plötzlich Timer1 ?
    Das bedeutet doch, dass eine Variable in einem Interrupt die Overflows zählt? Ich dachte mir, dass es so wie ich es jetzt gemacht habe einfacher ist.
    Ist anders auch nicht kompliziert.
    Der Code funktioniert so weit, allerdings bin ich mit der geringen Auflösung nicht ganz zufrieden.
    Verständlich, da Du vergessen hast den Zähler mit auszuwerten.
    Ansonsten muss man noch Race-Conditions vermeiden. Stell Dir vor die Auswertung fällt gerade so, dass bei 65535 die while verlassen wird und bis zur Auswertung der Zähler dann 0 wird, dann stimmt das Ergebnis nicht mehr.
    Der Timer könnte doch auch im CTC Modus laufen. Wenn der Timer im CTC modus läuft, bedeutet das dann, dass ich eine Zahl vorgeben kann bis der Overflow passiert. Zum Beispiel so, dass der Timer von 0 - 500 zählt bis ein Overflow geschieht?
    Ja, aber das macht hier doch keinen Sinn, denn man möchte ja am liebsten die maximale und zusammenhängende Zählerbreite haben, bis man per Software einen Overflow behandeln muss.

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    27.03.2009
    Beiträge
    96
    Danke nochmal
    Race-Conditions.... so heißt das also Schon wieder was dazu gelernt.
    Aber wo genau siehst du da denn eine Race-Condition? Ich meine der Zähler hört doch nach der while schleife auf zu zählen und die Variable 'ergebnis' enthält einen Maximalen Wert von etwa 60 (liegt am Ultraschallsensor).

    Die Auswertung des Timers ist mir auch schon in den Kopf gegangen:
    Code:
        
     while((PINC & (1<<PC3)))
         {
             if (TIFR & (1<<TOV1))
             {
                 ergebnis = ergebnis + 1;    //ergebnis1
                 TIFR = (1<<TOV1);
             }
         }
         TCCR1B &= ~(1<<CS11);           // Stoppe timer
         ergebnis2 = TCNT1;                  //ergebnis2
    Aber so wirklich schön finde ich das nicht. Hat auch nicht wirklich funktioniert.
    Hast du da vielleicht noch einen Tipp/Codeschnipsel

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    27.03.2009
    Beiträge
    96
    So, habs jetzt doch geschaft

    Code:
         
    while((PINC & (1<<PC3)))
         {
             if (TIFR & (1<<TOV1))
             {
                 ergebnis = ergebnis + 255;
                 TIFR = (1<<TOV1);
             }
         }
         ergebnis = ergebnis + TCNT1;
         TCCR1B &= ~(1<<CS11);           // Stoppe timer

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Zitat Zitat von Maxtronik Beitrag anzeigen
    Danke nochmal
    Bitte.
    Aber wo genau siehst du da denn eine Race-Condition? Ich meine der Zähler hört doch nach der while schleife auf zu zählen und die Variable 'ergebnis' enthält einen Maximalen Wert von etwa 60 (liegt am Ultraschallsensor).
    Im letzten Code war nur noch Init() zu sehen, da war nicht erkennbar welcher Precaler verwendet wird.
    Jeder Befehl benötigt mindestens einen oder mehrere Takte, der Compiler setzt das ja intern in Maschinenbefehle um.
    Dafür z.B.
    Code:
    TCCR1B &= ~(1<<CS11);
    muss er das Register laden, ver-unden und zurück speichern, wird um die 3 Takte dauern, der vorherige Test auf den gesetzten Pin dauert auch noch ein paar Takte, lass es mal 2 sein, sind also 5.
    Wenn der Prescaler 8 ist, dann hat er noch nicht weiter gezählt, bis der Zähler tatsächlich steht. Ist der Prescaler aber 1, dann ist er schon weiter.
    War er gerade an der Grenze, dann ist er nachher vielleicht bei Stand 1, nur wurde der Overflow nicht mitgezählt, damit stimmt dann das Ergebnis nicht mehr.
    Die Auswertung des Timers ist mir auch schon in den Kopf gegangen:
    Die Overflows sind ein Vielfaches der Timergröße, man muss das natürlich zum Schluss zusammenrechnen, also das Eine multiplizieren und das Andere addieren.
    Hat auch nicht wirklich funktioniert.
    Wie erkennst Du das ?
    Hast du da vielleicht noch einen Tipp/Codeschnipsel
    Das hier ist ein typischer Anwendungsfall für die Input Capture Fähigkeit, die der Timer1 Deines µC möglicherweise hat.
    Kannst ja mal danach suchen, ist aber ein wenig komplexer als das hier.

    Allerdings wäre, im Falle dass Timer1 ein 16Bit-Timer ist, ein besseres Ergebnis bereits erreichbar, wenn man den Prescaler auf 1 setzt, denn 16Bit bei 8MHz entsprechen einer Strecke von ca. 2,70m, also 1,35m einfach, bis ein Overflow auftritt.
    Keine Ahnung wie weit diese Sensoren messen können, aber 1,35m wäre schon mal ok.
    Wenn man einfach den 16Bit Zählbereich ausnutzt und bei einem Overflow das Ergebnis verwirft weil als zu weit betrachtet, kann man sich einiges sparen.

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    27.03.2009
    Beiträge
    96
    Allerdings wäre, im Falle dass Timer1 ein 16Bit-Timer ist, ein besseres Ergebnis bereits erreichbar, wenn man den Prescaler auf 1 setzt, denn 16Bit bei 8MHz entsprechen einer Strecke von ca. 2,70m, also 1,35m einfach, bis ein Overflow auftritt.
    Aha!
    So funktionieren dann wahrscheinlich auch die ganzen Beispielcodes.
    Ja, also ich habe es mal so gemacht wie du es mir gesagt hast. Aber ich glaube, das der Controller den Prescaler nicht auf 1 setzt, denn er liefert nur Werte von ca.10 bis 250. Habe es so gemacht:

    TCCR1B = (1<<CS10); // starte timer Prescaler 1

    Werden die Prescaler Bits eigentlich beim ausschalten des Controllers gelöscht, könnte ja sein das CS11 noch gesetzt ist?

  9. #9
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Der 16 Bit Timer reicht für Ultraschall (in Luft) auch ohne Überlauf. Das Limit bei 1,35 m gilt für Prescaler 1 und eine entsprechend sehr hohe Auflösung. Auch mit Prescaler 8 oder ggf. auch 64 sollte die Auflösung reichen und die maximale Strecke ist dann schon 8 bzw. 64 mal so groß. Schon die Abfrage per Polling in der While schleife gibt eine Unsicherheit von vermutlich mehr als 8 Zyklen - eine Prescaler unter 8 ist also nicht wirklich sinnvoll. Wenn man es mit so hoher Auflösung braucht, dann ist ICP die Lösung, braucht aber einen passenden PIN.

    Im RN-Wissen ist unter timer (AVR) ein Beispiel zum ICP und auch wie man die Race-conditon abfängt mit drin.

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Zitat Zitat von Besserwessi Beitrag anzeigen
    Schon die Abfrage per Polling in der While schleife gibt eine Unsicherheit von vermutlich mehr als 8 Zyklen
    Nicht wirklich. Da ohne Test auf Overflow die Bedingung einfacher ist, beträgt die Laufzeit minimal 1 und maximal 3 Zyklen, also ein Jitter von 2 Zyklen.
    Code:
    SBIC      0x13,3;  ATM32, PC3, Opt. -Os
    RJMP      PC-0x0001
    Nachfolgender Code ist in der Laufzeit konstant und kann eingerechnet werden, es stellt sich aber wirklich die Frage, warum man auf 1,35m / 2^16 = 0,00002 = 2 Hundertstel Millimeter auflösen sollte.
    Zitat Zitat von Maxtronik Beitrag anzeigen
    Werden die Prescaler Bits eigentlich beim ausschalten des Controllers gelöscht, könnte ja sein das CS11 noch gesetzt ist?
    Ja, bei einem Hardreset werden Defaults eingetragen, außerdem setzt Du das Register ja richtig und machst nicht den Fehler es bei Initialisierung zu ver-odern.
    Code:
    TCCR1B = (1<<CS10);            // starte timer Prescaler 1
    Selbst bei 1MHz Clock müsste ein Wert von 3000 bei einem Hindernis in 50cm Entfernung und Prescaler 1 rauskommen.
    Stell den vollständigen Code ein und schreib auch dazu was es für ein µC-Typ ist und mit welcher Taktfrequenz er betrieben wird.

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. SRF04 oder SRF05 Ultraschallsensor ?!
    Von kamatschka im Forum Sensoren / Sensorik
    Antworten: 10
    Letzter Beitrag: 13.04.2012, 17:25
  2. Antworten: 27
    Letzter Beitrag: 14.10.2009, 19:49
  3. SRF05 Ultraschallsensor an atmega32, kein Signal
    Von bruegae im Forum Sensoren / Sensorik
    Antworten: 3
    Letzter Beitrag: 20.11.2008, 21:58
  4. Git es den Ultraschallsensor SRF05 mit analoger Spannung?
    Von Sheridan im Forum Sensoren / Sensorik
    Antworten: 6
    Letzter Beitrag: 18.04.2007, 17:35
  5. Ultraschallsensor SRF05
    Von MORRI$ im Forum Sensoren / Sensorik
    Antworten: 0
    Letzter Beitrag: 31.07.2006, 16:12

Stichworte

Berechtigungen

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