- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 8 von 8

Thema: Frequenzmessung mit einem Mega32

  1. #1
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    34
    Beiträge
    3.501
    Blog-Einträge
    9

    Frequenzmessung mit einem Mega32

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo Forum,

    ich versuche gerade meinen Feuchtigkeitssensor (http://www.hoperf.com/upload/sensor/hh10d.pdf) mit meinem RN-Control auszuwerten.
    Den Frequenzausgang des Sensors habe ich mit Pin D2 (INT0) verbunden.
    Der Grundgedanke ist, dass ich bei einer steigenden Flanke in der ISR von INT0 eine Variable hochzähle und die dann 1x in der Sekunde auf ein Terminal ausgebe.
    Damit bekomme ich ja dann die Impulse pro Sekunde sprich die Frequenz raus.
    Jetzt verwende ich dieses Programm:

    Code:
    /*
     * HH10D.c
     *
     * Created: 03.05.2012 20:46:19
     *  Author: Daniel
     */ 
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <string.h>
    #include <util/delay.h>
    #include <stdlib.h>
    
    int lenght = 0x00;
    char data[50];
    volatile int Zaehler = 0x00;
    int Frequenz = 0x00;
    
    int main(void)
    {
        UART_Init();
        Port_Init();
        Timer1_Init();
        sei();
        
        while(1)
        {
    
        }
    }
    
    void UART_Init()
    {    
        UCSRB = (1<<RXEN) | (1<<TXEN);                                                                    // Rx und Tx aktivieren
        UCSRC = (1<<URSEL)| (1<<UCSZ1) | (1<<UCSZ0);                                                    // 8 Bit Nachrichtenlänge einstellen
        
            
        UBRRH = 0x00;
        UBRRL = 0x33;                                                                                    // Baudrate auf 19200 festlegen
    }
    
    void Port_Init()
    {
        DDRD = 0x00;
        
        MCUCR = (1<<ISC01);                                                                                // Interrupt auf fallende Flanke stellen
        GIMSK = (1<<INT0);                                                                                // INT0 aktivieren
    }
    
    void Timer1_Init()
    {
        TCCR1B = (1<<CS12);                                                                                // Prescaler 256
        TCNT1H = 0x0B;
        TCNT1L = 0xDB;
        TIMSK |= (1<<TOIE1);                                                                            // Timer1 Overflow Interrupt aktivieren
    }
    
    
    void Send_UART(char data[])
    {
        char Counter;
        
        lenght = strlen(data);
        
        while(Counter < lenght)
        {
            while (!(UCSRA & (1<<UDRE)));
            UDR = data[Counter];    
            Counter++;
        }
            
        Counter = 0x00;    
        while (!(UCSRA & (1<<UDRE)));
        UDR = 0x0A;    
        while (!(UCSRA & (1<<UDRE)));
        UDR = 0x0D;    
    }
    
    ISR(TIMER1_OVF_vect)
    {
        cli();
        Frequenz = Zaehler;
        Zaehler = 0x00;
        TCNT1H = 0x0B;
        TCNT1L = 0xDB;
        sei();
                    
        itoa(Frequenz, data, 10);      
        Send_UART(data);
    }
    
    
    ISR(INT0_vect)
    {
        Zaehler++;
    }
    Allerdings stimmt die Frequenz nicht mit der Frequenz des Sensors überein (ich kontrolliere das per Oszi). Der Mikrocontroller spuckt mir immer einen Wert aus der 100-200 zu hoch ist.
    Weiß einer woran das liegen könnte?

    Danke für die Hilfe!
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Der Code ist recht ineffektiv, insbesondere wenn ein Input Capture zur Verfügung steht.
    Counter ist lokal zu Send_UART, befindet sich damit auf dem Stack. Wenn die lokale Variable nicht initialisiert wird, ist ihr Startwert unbestimmt, sagt Dir aber der Compiler schon.
    Den Wert nachträglich auf 0 zu setzen ist sinnlos, da Counter als Index auf den Ausgabestring dient, ist das eher Zufall wenn's klappt.

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    Hallo Daniel,

    vielleicht kannst du dir da (https://www.roboternetz.de/community...ngen-Messgerät) etwas abgucken?
    (Ist zwar für den RP6, aber der hat auch den ATmega32...)
    Gruß
    Dirk

  4. #4
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    34
    Beiträge
    3.501
    Blog-Einträge
    9
    Danke euch beiden.
    Ich habe das gestern auch mal mit der Capture and Compare Unit probiert aber damit hat es leider gar nicht geklappt. Eigentlich dachte ich für sowas einfaches würde das ohne Probleme mit dem Timer klappen....aber naja :/
    Der Compiler hat mir gar nichts zu der Variable Counter gesagt (und die Ausgabe per UART klappt auch ohne Probleme) aber trotzdem danke für den Hinweis
    Den Link schaue ich mir mal an und gucke mal ob ich da was von entnehmen kann.
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Zitat Zitat von Dirk Beitrag anzeigen
    Warum setzt Du eigentlich den Wert icrcnt_start.i16h in der ISR laufend zurück, ohne dass Du ihn jemals änderst ? Nicht dass es viel ausmachen würd', aber es ist sinnlos.
    Code:
     icrcnt_start.i16h = 0;            // Reset upper 16 bits (start value)
    Für die einmalige Initialisierung hätte Dir das gereicht:
    Code:
    static icrcounter_t icrcnt_start = {.i32=0};
    Zitat Zitat von Kampi Beitrag anzeigen
    Der Compiler hat mir gar nichts zu der Variable Counter gesagt (und die Ausgabe per UART klappt auch ohne Probleme) aber trotzdem danke für den Hinweis
    ../hh10d_meas.c:48: warning: 'Counter' may be used uninitialized in this function
    Wenn der Stackspeicher nicht stark benutzt wird, dann ist es möglich dass zufällig für sich diese lokale Variable immer wieder die gleiche Adresse im Stack benutzt wird, dann geht es.
    Änderst sich die Stackbenutzung kann dort ein anderer Wert stehen, mit entsprechendem Ergebnis.
    Grundsätzlich hat eine lokale Variable als verloren betrachtet zu werden, außer sie wird static deklariert, dann bleibt sie im Speicher erhalten.

  6. #6
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    34
    Beiträge
    3.501
    Blog-Einträge
    9
    Zitat Zitat von MagicWSmoke Beitrag anzeigen
    Warum setzt Du eigentlich den Wert icrcnt_start.i16h in der ISR laufend zurück, ohne dass Du ihn jemals änderst ? Nicht dass es viel ausmachen würd', aber es ist sinnlos.
    Code:
     icrcnt_start.i16h = 0;            // Reset upper 16 bits (start value)
    Für die einmalige Initialisierung hätte Dir das gereicht:
    Code:
    static icrcounter_t icrcnt_start = {.i32=0};

    Wenn der Stackspeicher nicht stark benutzt wird, dann ist es möglich dass zufällig für sich diese lokale Variable immer wieder die gleiche Adresse im Stack benutzt wird, dann geht es.
    Änderst sich die Stackbenutzung kann dort ein anderer Wert stehen, mit entsprechendem Ergebnis.
    Grundsätzlich hat eine lokale Variable als verloren betrachtet zu werden, außer sie wird static deklariert, dann bleibt sie im Speicher erhalten.
    Ok dank dir für den Hinweis
    Ich programmiere nicht so viel und so oft in C, daher sind mir solche Feinheiten nicht ganz klar.
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

  7. #7
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    34
    Beiträge
    3.501
    Blog-Einträge
    9
    Zitat Zitat von Dirk Beitrag anzeigen
    Hallo Daniel,

    vielleicht kannst du dir da (https://www.roboternetz.de/community/threads/47088-RP6Control-M32-Impulslängen-Messgerät) etwas abgucken?
    (Ist zwar für den RP6, aber der hat auch den ATmega32...)
    Hi,

    nochmal kurz ne Frage.....
    So richtig steige ich durch dein Programm (leider) nicht durch. Kannst du mir im groben Erklären wie das mit der Input-Capture Unit und deinem Programm funktioniert?
    Dank dir!
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    01.10.2009
    Beiträge
    437
    Ich empfand das verlinkte Programm auch ein wenig undurchsichtig, vor allem die Structs und Unions, kann man zwar so machen, muss man aber nicht. Auch ist, obwohl's tatsächlich nicht viel ausmacht, bei jedem Triggern des Input Capture eine Messung möglich. Ein Unterscheiden zwischen erster und zweiter Flanke ist nicht notwendig.
    Die normale Vorgehensweise ist so, man nimmt sich 'ne unsigned 16Bit Variable und zieht in der ISR immer den alten Zählerstand vom Neuen ab. Dass dann auch z.B. 200 - 65000 richtig behandelt wird, wird durch Berücksichtigung der Overflows erreicht. Die Overflows werden mit der Zählerbreite multipliziert und zum Ergebnis addiert.
    Wichtig ist dabei auf race-conditions aufgrund der Codelaufzeit zu achten, die im Bereich des Zählerüberlaufs vorkommen können, als auch das Ergebnis atomar zu übergeben, damit während der Ausgabe nichts vefälscht wird.

Ähnliche Themen

  1. USB + Frequenzmessung
    Von Tux12Fun im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 20.06.2011, 01:06
  2. Problem mit Frequenzmessung
    Von TB1 im Forum PIC Controller
    Antworten: 5
    Letzter Beitrag: 28.09.2006, 12:40
  3. Kann mann ein Program aus einem Mega32 wieder auslesen????
    Von jozefowicz im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 3
    Letzter Beitrag: 30.03.2006, 13:17
  4. Frequenzmessung mit AVR
    Von teslanikola im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 21
    Letzter Beitrag: 14.11.2005, 23:43
  5. Frequenzmessung autonom?
    Von RG im Forum Controller- und Roboterboards von Conrad.de
    Antworten: 2
    Letzter Beitrag: 06.12.2004, 12:02

Berechtigungen

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

Labornetzteil AliExpress