- Akku Tests und Balkonkraftwerk Speicher         
Ergebnis 1 bis 10 von 18

Thema: counter Problem (SRF05 Ultraschallsensor C code)

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    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.

  2. #2
    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?

  3. #3
    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.

  4. #4
    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.

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    27.03.2009
    Beiträge
    96
    Hardware:
    -Asuro
    ->Atmega8
    ->externer Quarz 8Mhz
    -Ultraschallsensor SRF05

    Hier ist mein aktuellster Code:
    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];  //Doofe Frage: Was macht die Zahl in den eckigen Klammern???
      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)));   //warte auf Echo Signal
         TCCR1B = (1<<CS11);            // starte timer Prescaler 8
         TCNT1 = 0;                    // setze Timer1 auf 0
         while((PINC & (1<<PC3)));    //warte auf Echoende
         ergebnis = TCNT1;
         TCCR1B &= ~(1<<CS11);           // Stoppe timer
         
         itoa(ergebnis, buffer, 10); //übersetze (int)ergebnis in ASCII
         ergebnis = 0;
         SerPrint("\n\r Ergebnis: \n\r"); 
         SerPrint(buffer);              //übertragung des Ergebnisses über RS232
         _delay_ms(500);            //warte 500ms
      }
    }
    Ich erhalte in meiner UART Konsole bei ca. 12cm Abstand einen Wert von ca. 250,
    wenn ich nun den Abstand vergrößere dann wird dieser Wert kleiner bis er 1 beträgt.
    Vergrößere ich wieder den Abstand zähl er den Wert wieder bis auf ca. 250 u.s.w..
    Ist das nicht ein komisches Verhalten???

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Hab' mir mal das Datenblatt für den Sensor gesucht, der setzt das intern um, das ist also nicht die Laufzeit des Schalls, sondern die Formel lautet:
    Zurückgegebener Impuls in µs / 58 = Wert in cm, bei min. 100µs und max. 25000µs

    Bei einem Prescaler mit 8 und einem 8MHz Takt hast Du in 25000µs einen Zählerstand von 25000. Kann es sein, dass mit der Ausgaberoutine etwas nicht klappt ?
    Weise doch mal Ergebnis den Wert 25000 fest zu und gib das aus.

    Das Teil mit den eckigen Klammern ist ein Char-Array, das Äquivalent zu Strings in Bascom, die Zahl bezeichnet die Länge des Arrays.

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    27.03.2009
    Beiträge
    96
    Code:
    int main(void)
    {
    
      Init();
      
      char buffer [10];
      uint16_t distance=0;
    
      while (1)
      {     
         distance = 25000;
         itoa(distance, buffer, 10); //übersetze (int)ergebnis in ASCII
         SerPrint("\n\r Ergebnis: \n\r"); 
         SerPrint(buffer);              //übertragung des Ergebnisses über RS232
         _delay_ms(500);            //warte 500ms
      }
    }
    Hab ich gemacht. In der Konsole erscheint auch 25000, also hier dürfte der Fehler nicht liegen.
    Ich stehe gerade so ziemlich aufm Schlauch
    Ich bin mir ziemlich sicher das der Fehler irgendwie mit dem Timer zusammenhängt.
    Ich befürchte ich komme mit der Bit schreibweiße noch ein wenig durcheinander.
    Es macht bei mir keinen Unterschied ob ich Das CS11 Bit so schreibe:
    TCCR1B = (1<<CS11); // starte timer Prescaler 8
    oder so wie man es bei den Ausgängen macht:
    TCCR1B |= (1<<CS11); // starte timer Prescaler 8

    Mache ich vielleicht dort einen Fehler???

    Vielleicht lösche ich das Bit ja auch falsch???
    TCCR1B &= ~(1<<CS11); // Stoppe timer

    Ich hoffe du kannst mir noch einmal helfen

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Zitat Zitat von Maxtronik Beitrag anzeigen
    Es macht bei mir keinen Unterschied ob ich Das CS11 Bit so schreibe:
    TCCR1B = (1<<CS11); // starte timer Prescaler 8
    oder so wie man es bei den Ausgängen macht:
    TCCR1B |= (1<<CS11); // starte timer Prescaler 8
    Solange TCCR1B vorher 0 war, macht das keinen Unterschied. Beim Einschalten des µC's ist das Register 0.
    Nur soll man bei der ersten Initialisierung nicht verodern (|=), sondern direkt zuweisen. Grund dafür: Wenn z.B. ein Bootlader aktiv war, kann der das Register schon vorbesetzt haben, dann kommt mit Verodern Murks raus.
    Was macht eigentlich das Init() ? Auch würde ich noch TCCR1A auf 0 setzen, einfach der Gründlichkeit halber und damit ich sicher bin, das alle beteiligten Register den von mir gewünschten Wert haben.
    Mache ich vielleicht dort einen Fehler???
    Nein, hab's simuliert und sieht alles gut aus, in Ergebnis steht der Wert in µs.
    Vielleicht lösche ich das Bit ja auch falsch???
    TCCR1B &= ~(1<<CS11); // Stoppe timer
    Ist auch richtig. Du bist sicher das richtige Target gewählt und F_CPU definiert zu haben ?
    Welcher Optimierungslevel ist eingestellt ?
    Bekommst Du Warnings ? Wenn ja, welche ?

  9. #9
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die Schreibweise mit TCCR1B = (1<<CS11); ist besser, weil man da das ganze Register definiert, also alles richtig einstellt, egal was vorher drin war. Die andere Version wird meistens auch gehen, weil der normale Mode default ist. die Version mit dem |= wird ggf. kürzer weil dafür spezielle ASM Befehle existieren.

    So ähnlich ist es mit dem Stoppen des Timers - das kommt hier ohnehin nach dem Auslesen, ist also nicht von Bedeutung. Man könnte es ggf. Probieren den Timer erst zu stoppen, und dann auszulesen. Im Prinzip sollte es aber auch bei laufendem Timer gehen.
    An sich macht GCC das auslesen von 16 Bit Registern richtig, man könnte es ggf. auch mal von Hand probieren (erst low Byte lesen), oder den erzeugten Code ansehen.

    An sich kann ich da keinen Fehler sehen. Ein versuch wäre ggf. noch den Timer erst auf 0 zu setzen und dann zu starten. Im Prinzip sollte aber beides gehen.

    Eine kleine Ungenauigkeit ist da noch drin bei der Ausgabe. Statt itoa sollte man utoa nehmen, denn die variable ist uint16_t. Bis gut 32000 sollte das aber auch noch keinen Unterschied machen.

    Die 58 µs/cm kommen übrigens ganz gut hin mit der Laufzeit. Das ist also schon die Zeit bis zu Echo.

Ähnliche Themen

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

Stichworte

Berechtigungen

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

LiFePO4 Speicher Test