- Labornetzteil AliExpress         
Seite 5 von 6 ErsteErste ... 3456 LetzteLetzte
Ergebnis 41 bis 50 von 55

Thema: srf04 mit pulse

  1. #41
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    38
    Beiträge
    215
    Anzeige

    Powerstation Test
    Hier wäre ein Beispiel ohne verwendung von Input Capture oder Externe Interrupts. Also wie du gemeint hast.
    Code:
    // für 8 Mhz, Timer1(16bit), Prescaler 8, Takt von 1us, Überlauf nach 65535us oder 65,535ms
    
    #include <avr/io.h>
    #include <avr/delay.h>
    
    // Das mit PD1 auf PORTD ist nur ein Beispiel, jeder beliebige Pin kann gewält werden
    #define    MESS_PORT           PORTD
    #define    MESS_PORT_RICHTUNG  DDRD
    #define    MESS_PIN            PIND
    #define    MESS_BIT            PD1               // Echo-Trigger Eingang  oder einfach Messeingang
    
    #define US_PORT                PORTD 
    #define US_PORT_RICHTUNG       DDRD 
    #define US_BIT                 PD2               // Der Pin kommt zum Trigger-Puls Eingang
    
    
    unsigned int zeit_messung_us(void)
    {
        unsigned int wert_us;               // Wert in 
    
    	US_PORT_RICHTUNG|=(1<<US_PIN);         // US_PIN auf Ausgang
    	US_PORT|=(1<<US_PIN);     // Trigger-Puls auf high  
                          
        _delay_us(15);            // Laut Datenblatt Trigger-Puls min 10us auf high 
        US_PORT&=~(1<<US_PIN);   // Trigger-Puls Eingang wieder auf low   
    	
    	// Wenn keine srf04 Messung dann einfach ab hier
    	TCNT1=0;                   // Timerregister  auf 0
    	TCCR1B|= (1<<CS11);;      // Timer starten
    	while ( MESS_PIN & (1<<MESS_BIT));     // Warten bis Echo/Mess Eingang auf low
    	wert=TCNT1;
    	TCCR1B&= ~(1<<CS11);     // Timer wieder aus    
        	return wert;
    }
    Gruß Muraad

  2. #42
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    28.04.2004
    Ort
    Nähe Köln
    Alter
    58
    Beiträge
    247
    Hallo Ihr Beiden

    Und Dino Dieter im Datenblatt vom ATmega32 steht doch ausdrücklich das man das Bit durch schreiben einer logischen 1 löscht?!
    Gruß Muraad
    Ja ich weiß das das da steht, stimmt aber nicht so ganz. Atmel hat da eine eigene Auslegung. Schau dir doch mal die Fuse Bits an, ist doch je nach Progger genau so.


    TCCR1B= ~(1<<CS12) & ~(1<<CS11) & ~(1<<CS10); // Timer wieder aus
    Schade das du meinen Rat nicht angenommen hast. Das geht in die Hose.

    Hier mal meine Version von der Software

    Code:
    
    #include <avr/io.h>
    #include <avr/delay.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    #include <stdio.h>
    #include <delay.c>   // das unterprogramm warte
    #include <stdint.h>
    
    #define USART_BAUD_RATE    19200
    #define USART_BAUD_SELECT    (F_CPU/(USART_BAUD_RATE*16l)-1)
    
    #define US_PORT  PORTD
    #define US_PORT_RICHTUNG   DDRD
    #define US_PIN  PD7         // Der Pin kommt zum Trigger-Puls Eingang
    
    
    void usart_init(void) {
        UCSRB = (1<<RXCIE) | (1<<TXCIE) | (1<<RXEN) | (1<<TXEN);
        UBRRL = (unsigned char) USART_BAUD_SELECT;
        UCSRC |= (1<<URSEL)|(3<<UCSZ0);               //Asynchron 8N1
    
    }
    
    void uart_putc(unsigned char c)      // Ein zeichen
    {
        while(!(UCSRA & (1 << UDRE)));   /* warte, bis UDR bereit */
    
        UDR = c;    /* sende Zeichen */
    }
    
    void uart_puts(unsigned char *s)             // mehrere Zeichen
    {
        while (*s)
        {   /* so lange *s != NULL */
            uart_putc(*s);
            s++;
        }
    }
    // PD6 ist Input Capture Pin beim ATMega8, hier kommt der Echo-Pulse Ausgang hin
    uint16_t start_messung(void)
    {
       uint16_t wert = 0 ;        //wert_in_cm;
       
       //Timer vorbereiten
       TCCR1B  &=~(1<<ICES1);   // Fallende Flanke für Input Capture
       TCNT1 = 0;		    // Timer1 löschen
       
       US_PORT|=(1<<US_PIN);      // Trigger-Puls auf high
    
       _delay_us(11);            // Laut Datenblatt Trigger-Puls min 10us auf high
    
       US_PORT &=~(1<<US_PIN);   // Trigger-Puls Eingang wieder auf low
    
       while ( !(PIND & (1<<PD6)));  //warten bis der Echo Impuls anfängt
    
    
       TCCR1B  |= (1<<CS11);         // Prescaler 8, damit dauert ein Tackt  1 micro Sekunde, Timer startet
    
       while ( !(TIFR & (1<<ICF1)));
      // Warten bis Input Capture Flag gesetzt   ---> Echo-Eingang ist low
    
       if(ICR1 < 20000)  		       		 // gültiger Bereich  (max 18 ms + Reserve )
            wert= (unsigned int) (ICR1 / 58);	 //umrechnen in cm    (laut Datenblatt )
    
          TCCR1B &= ~(1<<CS11);     // Timer wieder aus
          TIFR   &= ~(1<<ICF1);     // ICF1 Bit wieder löschen durch schreiben einer logischen 0
    
        return wert;
    }
    
    int main (void)
    {
        US_PORT_RICHTUNG|=(1<<US_PIN);         // US_PIN auf Ausgang
        char s[3];
        uint16_t wert_1;
        usart_init();
    
       for (;;) {
    
        wert_1=start_messung();     	//bei Rückgabe 0 ungültige Messung
        sprintf(s,"%u",&wert_1);
        usart_puts(s);
        usart_puts("\n\r");
        warte(20000);
    
        }
    }
    Ablauf:

    Trigger Impuls ausgeben ( 11 µs)
    warten bis der Echo Impuls auf High geht
    Timer starten
    warten bis ICF1 high ist
    Abfrage ob gültiger Bereich
    Umrechnen
    und Ende

    Ich erwarte einen Impuls zwischen 100 µs und 18 mS, laut Datenblatt.
    Werte über 20 ms sind ungültig.

    Wenn es immer noch nicht klappt, folgende Zeile

    if(ICR1 < 20000) // gültiger Bereich (max 18 ms + Reserve )

    mal löschen und sehen was dann rauskommt.


    while(!(USR & (1 << UDRE))) asm volatile("NOP"); /* warte, bis UDR bereit */
    Diese Zeile bringt immer eine Fehlermeldung wegen USR. Kennt der mega 16 nicht. ???????


    MFG
    Dieter

  3. #43
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    28.04.2004
    Ort
    Nähe Köln
    Alter
    58
    Beiträge
    247
    Hallo

    Zitat:
    Und Dino Dieter im Datenblatt vom ATmega32 steht doch ausdrücklich das man das Bit durch schreiben einer logischen 1 löscht?!
    Gruß Muraad


    Ja ich weiß das das da steht, stimmt aber nicht so ganz. Atmel hat da eine eigene Auslegung. Schau dir doch mal die Fuse Bits an, ist doch je nach Progger genau so.
    Tut mir Leid, was ich da gesagt habe. Du hast natürlich Recht.

    Anstatt

    Code:
          TIFR   &= ~(1<<ICF1);     // ICF1 Bit wieder löschen durch schreiben einer logischen 0
    muß natürlich das rein
    Code:
         TIFR   |=  (1<<ICF1);     // ICF1 Bit wieder löschen durch schreiben einer logischen 1


    Aber das hier kann auch eine böse Falle werden.

    Code:
      UCSRB = (1<<RXCIE) | (1<<TXCIE) | (1<<RXEN) | (1<<TXEN);
    Wenn Mann später mal Int benutzen will und nicht die beiden INT Routinen definiert, bekommt man die schönsten Fehler, nur so als Tip. In dem Code hatte das aber keine Auswirkungen.

    Habe den Code so mal getestet und er macht das, was ihr wollt.

    Gruß
    Dieter

  4. #44
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    38
    Beiträge
    215
    Hier jetzt nochmal nur die Funktion start_messung() mit deinen Verbesserungen:
    Code:
    #include <avr/io.h> 
    #include <avr/delay.h>        // F_CPU definiert als 8Mhz
    #include <stdint.h>
    
    #define US_PORT  PORTD 
    #define US_PORT_RICHTUNG   DDRD 
    #define US_PIN  PD7         // Der Pin kommt zum Trigger-Puls Eingang
    
    // PD6 ist Input Capture Pin beim ATMega8, hier kommt der Echo-Pulse Ausgang hin 
    uint16_t start_messung(void) 
    { 
       uint16_t wert = 0 ;        //wert_in_cm; 
        
       //Timer vorbereiten 
       TCCR1B  &=~(1<<ICES1);   // Fallende Flanke für Input Capture 
       TCNT1 = 0;          // Timer1 löschen 
        
       US_PORT|=(1<<US_PIN);      // Trigger-Puls auf high 
    
       _delay_us(11);            // Laut Datenblatt Trigger-Puls min 10us auf high 
    
       US_PORT &=~(1<<US_PIN);   // Trigger-Puls Eingang wieder auf low 
    
       while ( !(PIND & (1<<PD6)));  //warten bis der Echo Impuls anfängt 
    
    
       TCCR1B  |= (1<<CS11);         // Prescaler 8, damit dauert ein Tackt  1 micro Sekunde, Timer startet 
    
       while ( !(TIFR & (1<<ICF1))); 
      // Warten bis Input Capture Flag gesetzt   ---> Echo-Eingang ist low 
    
       if(ICR1 < 20000)                      // gültiger Bereich  (max 18 ms + Reserve ) 
            wert= (unsigned int) (ICR1 / 58);    //umrechnen in cm    (laut Datenblatt ) 
    
          TCCR1B &= ~(1<<CS11);     // Timer wieder aus 
          TIFR   |= (1<<ICF1);     // ICF1 Bit wieder löschen durch schreiben einer logischen 1 
    
        return wert; 
    }
    Also Danke dir nochmal Dino Dieter. Und stimmt die _delay_us() Funktion jetzt, da du erst gemeint hast man muss sie zweimal aufrufen um auf 192us zu kommen?
    Gruß Muraad

  5. #45
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    28.04.2004
    Ort
    Nähe Köln
    Alter
    58
    Beiträge
    247
    Hallo

    Die delay_µs (11) geht, laut Simulator gut. Nur die lange Delay macht Probleme.

    Gruß
    Dieter

  6. #46
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    20.06.2004
    Beiträge
    1.941
    hallo, die einfache routine gibt jetzt den wert zwischen 214 und 217 dauérnd aus (ohne Input Capture oder Externe Interrupts). es tut sich schon was. auf verschiedene entfernungen ist noch keine reaktion.
    nochmal : ich habe den AVR16 mit 8mhz, nicht das ich jetzt einen falschen AVR habe.
    gibt es nicht eine delay routine, die genau +-1 us geht.
    mf pebisoft

  7. #47
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    38
    Beiträge
    215
    Pepisoft in der einfachen Variante im Code hatte ich noch nen Fehler.
    Diese Zeile:
    while (!( MESS_PIN & (1<<MESS_BIT)));
    muss so heissen. while ( MESS_PIN & (1<<MESS_BIT));
    vorher hat er immer gewartet bis der Echo-Pin auf high geht und das ist ziemlich gelich nach dem 200us langen Ultraschalltburst. Aber ein Echo ist erst angekommen wenn der Echo-Trigger Eingang auf low geht.
    Ach und bei der Funktion(ohne Input Capture usw.) musst du das ergebniss noch selbst in cm umrechnen. Also:
    unsigned int wert;
    wert=zeit_messung_us();
    wert=(unsigned int) ( wert/58 ); // Jetzt in cm

    Gruß Muraad

  8. #48
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    38
    Beiträge
    215
    Und noch was. Der Ablauf einer Messung beim srf04:
    1.Trigger-Puls-Eingang länger als 10us auf high startet Messung.
    2. Sendet 200us langen 40kHz Ultraschallburst und Echo-Ausgang wird auf high gelegt.
    3. Erste hereinkommende Echo schaltet Echo-Trigger-Ausgang auf low.
    Aber wird erst der 200us lange Burst gesendet und dann der Echo-Trigger-Ausgang auf high gesetzt oder wird er davor auf high gesetzt.
    Wird er nämlich danach erst auf high gesetzt muss man in der Funktion zeit_messung_us() nach der Zeile
    US_PORT&=~(1<<US_PIN); // Trigger-Puls Eingang wieder auf low
    noch 200us warten,da sonst diese Zeile
    while ( MESS_PIN & (1<<MESS_BIT));
    den Zustand des Ports abfrägt bevor dieser überhaupt high wurde.
    Hoffe man konnte es verstehn.
    Gruß Muraad

  9. #49
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    20.06.2004
    Beiträge
    1.941
    hallo, habe die normale funktion geändert.
    wenn ich den echo-puls ganz schnell vom pin abziehe und wieder daruf setze, erscheint je nach schnelligkeit ein zahl die immer verschieden gross ist. dieses geschieht bei der normalen routine. ich habe nach dem triggerpuls(10us) noch einmal die wartedelay von 200us reingesetzt. ändert sich nicht.
    nach dem 200us burst wird der trigger-ausgang zum messen erst auf high gesetzt.
    mfg pebisoft

  10. #50
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    20.06.2004
    Beiträge
    1.941
    hallo, es geht jetzt.
    die variablen müssen "Volatile" werden, weil diese beim programmablauf immer einen willkürlichen wert bekommen. weiterhin werden auch durch den compiler nicht-volatile-variablen wegoptimiert.
    ich habe mir noch eine einfache for-schleife erstellt, die im avr-studio bei einem durchgang 0,75us verbraucht und habe dann dem entsprechend die zahlen für die us umgerechnet 10us = 14 und 200us ist 267.
    Code:
    // Das mit PD1 auf PORTD ist nur ein Beispiel, jeder beliebige Pin kann gewält werden 
    #define    MESS_PORT           PORTB 
    #define    MESS_PORT_RICHTUNG  DDRB 
    #define    MESS_PIN            PINB 
    #define    MESS_BIT            PB0               // Echo-Trigger Eingang  oder einfach Messeingang 
    
    #define US_PORT                PORTB 
    #define US_PORT_RICHTUNG       DDRB 
    #define US_BIT                 PB1               // Der Pin kommt zum Trigger-Puls Eingang 
    
    uint16_t start_messung(void) 
    { 
       volatile uint16_t wert,i,x,x1;
       x=14;
       x1=267;
       wert=0;
       
       US_PORT_RICHTUNG|=(1<<US_BIT);         // US_PIN auf Ausgang 
       US_PORT|=(1<<US_BIT);     // Trigger-Puls auf high  
       for (i=0; i<x; i++)
        asm volatile("nop");
        US_PORT&=~(1<<US_BIT);   // Trigger-Puls Eingang wieder auf low   
       for (i=0; i<x1; i++)
        asm volatile("nop");
       // Wenn keine srf04 Messung dann einfach ab hier 
       TCNT1=0;                   // Timerregister  auf 0 
       TCCR1B|= (1<<CS11);      // Timer starten 
       while (MESS_PIN & (1<<MESS_BIT))     // Warten bis Echo/Mess Eingang auf low 
       wert=TCNT1; 
       TCCR1B&= ~(1<<CS11);     // Timer wieder aus    
       return wert; 
    }
    läuft jetzt im normalen interrupt ganz toll. die messung läuft sehr genau.
    man lernt nie aus, habe heute noch mal mit der "volatile" gelesen und der wegoptimierung.
    ihr alle habt eine hervorragende arbeit geleistet, ich hoffe es bleib weiterhin so. werde das andere musterprogramm auch noch umschreiben.
    jetzt habe ich ein nächstes thema : ein i2ceeprom 24c64 oder 24c256 beschreiben und lesen. es gibt zwar einige vorschläge, aber da steige ich nicht durch. vielleicht interessiert euch auch das thema, und macht es übersichtlich . vielen dank.
    mfg pebisoft

Seite 5 von 6 ErsteErste ... 3456 LetzteLetzte

Berechtigungen

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

Labornetzteil AliExpress