www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme mit SMT 160 Duty Cycle auslesen, Denkfehler ?


Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bin seit ein paar Tagen dabei einen SMT 160 auszulesen. Ich bin aber 
ziemlich am verzweifeln, warum mein Programm einfach nicht funktioniert. 
Ich benutze den Input Capture von Timer 1, ich bekomme nur sehr seltsame 
springende ( von negative bis 189°) Temperaturwerte angezeigt. Ich find 
einfach meinen Fehler im Programm nicht, vielleicht habe ich einen 
denkfehler ?

Abgehesehen von der erste Messung, die mit meinem Programm so einen 
Fehler rausbringen dürfte, weiß ich einfach nicht warum´s nicht läuft.

Ich frage zuerst die Steigende Flanke ab, setze dann in mit einem 
Interrupt den Startwert und lasse die fallende Flanke abfragen und setze 
mir noch eine Erkennungsvariable. Sobald die Fallende Flanke erkannt 
wurd, wird der Endwert gespeichert,.. anschließend berechne ich Puls und 
Pausenzeit, addiere diese und erhalte die Periodenzeit. Da im 
Datenblatte des Senors steht man solle über mehrer Perioden messen und 
dann Puls und Periodenzeit ins Verhältnis setzen, addiere ich diese. 
Habe ich genug Perioden gemessen, lasse ich mir die Temperatur berechnen 
und gebe diese auf einem LCD Display aus.

Hier der Code:
 #include <stdlib.h>
#include <stdio.h>
#include <avr/io.h>
#include <inttypes.h>
#include <lcd/lcd.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#include <lcd/lcd.c>
#include <avr/interrupt.h>



volatile uint16_t start=0;        // Globale Variable Start, übergigt Zeitwert an Main  
volatile uint16_t ende=0;        // Globale Variable Start, übergigt Zeitwert an Main  
volatile uint16_t overflow=0;      // Globale Variable Start, übergigt Timer 1 Overflows an Main  

volatile uint8_t tc_zuweis=0b11000010;  // Hilfsvariable Zuweisung TCCR1B -> Bit7 für Noise Killer, Bit6 flankenerkennung (1=steigend)
volatile uint8_t flanke_erkannt = 0;  // Hilfsvariable Flanke erkannt

ISR(TIMER1_CAPT_vect)        // Capture erkannt
{
  if (TCCR1B == tc_zuweis)  // steigende Flanke?
    {            // ja
    start=ICR1;        // Startwert für Puls           oder Endwert für Pause 
    TCCR1B = 0b10000010;  // fallende Flanke abfragen
    flanke_erkannt = 1;    // Flanke erkannt
    }        
  else            // nein 
    {
    ende=ICR1;        // Endwert für Puls               oder Startwert für Pause
    TCCR1B = 0b11000010;  // steigende Flanke abfragen
    flanke_erkannt = 1;    // flanke erkannt
    }
}


ISR(TIMER1_OVF_vect)        // Overflow T1 
{
    overflow++;  
}


int main(void)
{ 
  DDRB= 0b01001100;      // Pin B2,B3,B6 als Ausgang 
  DDRD= 0b10110011;      // Pin D2,D3,D6 als Eingang
  PORTD=0b01001100;      // Pull Up D2,D3,D6 aktivieren
  lcd_init(LCD_DISP_ON);    // LCD initialisieren

  char Buffer[20];       // Zeichenkette für LCD Ausgabe deklarieren

  double temp;        // Float Hilfsvariable temp deklarieren, für Temperatur ausgabe
  double y;          // Float Hilfsvariable
  double tast_verhaeltnis;  // Float Hilfsvariable für Tastverhältnis   


  TIMSK =  0b00100100;    // Bit5 Input Capture und Bit2 Overflow erlauben
  TCCR1B = tc_zuweis;      // Teiler und Input Capture Timer  
  sei();
  uint32_t puls_summe = 0;  // Hilfsvariable für Pulssumme
  uint32_t perioden_summe = 0;// Hilfsvariable für Periodensumme
  uint32_t puls = 0;      // Hilfsvariable für Pulsberechnung
  uint32_t pause = 0;      // Hilfsvariable für Pausenberechnung
  uint32_t periode = 0;    // Hilfsvariable für Periodenberechnung
  uint8_t periodenanzahl = 0; // Hilfsvariable für Vollständige Periodenmessung
  uint8_t messungen = 0;    // Hilfsvariable für Anzahl der Messungen
  while(1)
    {
    
    if ((TCCR1B == 0b11000010) && flanke_erkannt)    // Wird steigende Flanke abgefragt und wurde eine Flanke erkannt?
      {                  // JA
      puls =(overflow*65536)+ende-start;  // Puls berechnen
      overflow=0;              // Timer Overflow zurücksetzen
      flanke_erkannt = 0;          // Flanken erkannt zurücksetuen
      }
    else                  // Nein
      {
      pause=(overflow*65536)-ende+start;  // Pause berechnen
      overflow=0;              // Timer Overflow zurücksetzen
      periodenanzahl= 1 ;          // Vollständig gemessene Periode = 1
      flanke_erkannt = 0;          // Flanken erkannt zurücksetuen
      }

    if (periodenanzahl==1)                // Wenn Vollständige Periode gemessen wurde Summierung durchführen
      {
      periode     = puls     + pause;      // Periode berechnen
      perioden_summe   = periode   + perioden_summe;  // Messung meherer Perioden, um fehler zu minieren
      puls_summe     = puls     + puls_summe;    // Messung meherer Pausen, um fehler zu minieren
      periodenanzahl  = 0;              // Periodenanzahl zurücksetzen
      messungen++;                  // Messungen erhöhen
      }
    
    if (messungen>=10)                        // wenn mehr als x Perioden gemessen wurden, Temperatur berechnen und ausgeben
      {
      tast_verhaeltnis = (float)puls_summe / perioden_summe;    // Tastverhältnis berechnen
      perioden_summe   = 0;
      puls_summe      = 0;
      messungen     = 0;            
      y = tast_verhaeltnis - 0.32;
      temp= y * 212.7659574468085;
      sprintf( Buffer, "Temp: %3.4f", temp );
      lcd_clrscr();
      lcd_puts(Buffer );
      _delay_ms(200);
      }

    }


}
 

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja, Atmega 16 mit 8 Mhz im STK 500. Sensor und LCD sind auf 
Steckboard gesteckt.

Vielen Dank schonmal !

Autor: Markus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich konnte den Fehler jetzt weiter einschränken, die Puls bzw. 
Pausenzeit ist bei mir ab und zu mal negativ. Nur wie kann das sein ?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Zählen mit Overflow ist etwas tricky, sonst gibts Zahlensalat:

Beitrag "AVR Timer mit 32 Bit"

Ist hier aber auch garnicht nötig, da sich 4kHz komplett in 16Bit zählen 
lassen.

Hier mal mein Code:

u32 time_hi;
u32 time_period;
u8 period_count;


void smt160_init( void )
{
#if 0
//              Initialisation done by init PWM (mode 15)
//
  TCCR1A = 0;                           // mode 0
  TCCR1B = 1<<ICNC1^1<<CS10;            // count XTAL / 1
                                        // ICP on falling edge
                                        // noise canceler on
#endif
  TIMSK1 = 1<<ICIE1;                    // capture interrupt
  period_count = 1;
}


ISR( TIMER1_CAPT_vect )
{
  static u32 count_hi, count_period;
  static u16 old_time;

  u16 diff_time;
  u8 i;

  i = ICR1H;                            // save high byte!
  diff_time = ICR1 - old_time;
  ICR1H = i;                            // restore high byte

  TCCR1B = i = TCCR1B ^ 1<<ICES1;       // toggle direction

  if( i & 1<<ICES1 ){
    count_hi += diff_time;              // + high duration
  }else{
    old_time += diff_time;              // old_time = new ICR1
    count_period += diff_time;          // + period duration

    if( --period_count == 0 ){          // 4kHz / 256 = 64ms
      time_period = count_period;       // store results
      time_hi = count_hi;
      count_period = 0;                 // clear counters
      count_hi = 0;
    }
  }
}


Peter

Autor: Thomas D (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

danke für deine Antwort. Ich hab´s jetzt schon ein bisschen anders 
gelöst, werde mir aber dein Vorschlag nochmal genau ansehen, ist 
bestimmt viel besser als meine Lösung.

Trotzdem wollte ich meine Lösung hier kurz darstellen, vielleicht kann 
die ja irgendwann mal jemand gebrauchen.
#include <stdlib.h>
#include <stdio.h>
#include <avr/io.h>
#include <inttypes.h>
#include <lcd/lcd.h>
#define F_CPU 8000000
#include <util/delay.h>
#include <lcd/lcd.c>
#include <avr/interrupt.h>


volatile uint16_t start=0;        // Globale Variable Start, übergigt Zeitwert an Main  
volatile uint16_t ende=0;        // Globale Variable Start, übergigt Zeitwert an Main  
volatile uint16_t overflow=0;      // Globale Variable Start, übergigt Timer 1 Overflows an Main  
volatile uint8_t flanke_erkannt = 0;  // Hilfsvariable Flanke erkannt

ISR(TIMER1_CAPT_vect)        // Capture erkannt
{
  if (TCCR1B == 0b11000001)  // steigende Flanke?
    {            // ja
    start=ICR1;        // Startwert für Puls           oder Endwert für Pause 
    TCCR1B = 0b10000001;  // fallende Flanke abfragen
    }        
  else            // nein 
    {
    ende=ICR1;        // Endwert für Puls               oder Startwert für Pause
    TCCR1B = 0b11000001;  // steigende Flanke abfragen
    }
flanke_erkannt = 1;        // Signal Flanke wurde erkannt setzen
}


ISR(TIMER1_OVF_vect)        // Overflow T1 
{
    overflow++;  
}


int main(void)
{ 
  DDRB= 0b01001100;      // Pin B2,B3,B6 als Ausgang 
  DDRD= 0b10110011;      // Pin D2,D3,D6 als Eingang
  PORTD=0b01001100;      // Pull Up D2,D3,D6 aktivieren
  lcd_init(LCD_DISP_ON);    // LCD initialisieren

  char Buffer[16];       // Zeichenkette für LCD Ausgabe deklarieren

  float temp=0.0;          // Float Hilfsvariable temp deklarieren, für Temperatur ausgabe
  float y;          // Float Hilfsvariable
  float tast_verhaeltnis=0.0;  // Float Hilfsvariable für Tastverhältnis   



  TIMSK =  0b00100100;    // Bit5 Input Capture und Bit2 Overflow erlauben
  TCCR1B = 0b11000001;    // Teiler und Input Capture Timer  
  sei();
  uint32_t puls_summe = 0;  // Hilfsvariable für Pulssumme
  uint32_t perioden_summe = 0;// Hilfsvariable für Periodensumme
  uint32_t pausen_summe = 0;  // Hilfsvariable für Pausensumme
  uint16_t puls = 0;      // Hilfsvariable für Pulsberechnung
  uint16_t pause = 0;      // Hilfsvariable für Pausenberechnung
  uint16_t pausenanzahl = 0;  // Hilfsvariable für Vollständige Periodenmessung
  uint16_t pulsanzahl = 0;   // Hilfsvariable für Vollständige Periodenmessung
  


  while(1)
    {
    if (flanke_erkannt==1)
      {
      
      if (TCCR1B == 0b11000001)                 // Wird steigende Flanke abgefragt und wurde eine Flanke erkannt?
        {
        if (pulsanzahl<=pausenanzahl)            // Puls und Pausenzahl angleichen
          {                        
          puls =(overflow*65536)+ende-start;        // Puls berechnen
          pulsanzahl++;
          puls_summe = puls + puls_summe;          // Messung meherer Pausen, um fehler zu minieren
          }
        }
      else                          
        {
          if (pausenanzahl<=pulsanzahl)          // Puls und Pausenzahl angleichen
          {
          pause=(overflow*65536)-ende+start;        // Pause berechnen
          pausenanzahl++ ;                // Vollständig gemessene Periode = 1
          pausen_summe = pause + pausen_summe;      // Messung meherer Pausen, um fehler zu minieren
          }
        }

      overflow=0;                        // Timer Overflow zurücksetzen
      flanke_erkannt = 0;                    // Signal Flanken erkannt zurücksetzen
      }        
    

    if ((pulsanzahl==pausenanzahl)&(pulsanzahl>=2500))      // Wenn 2500 Vollständige Periode gemessen wurde Berechnung
      {                            
      perioden_summe   = puls_summe + pausen_summe;      // Gesamtzeit berechnen
      tast_verhaeltnis=(float)puls_summe/perioden_summe;    // Tastverhaeltnis berechnen
      y = tast_verhaeltnis - 0.32;              // Achsenabschnitt subtrahieren
      temp= y * 212.765957;                  // Temperatur brechnen
      
      lcd_clrscr();                      // LCD löschen
      sprintf( Buffer, "Temp: %2.4f",temp);          // Float in String umwandeln
      lcd_puts(Buffer );                    // String auf LCD ausgeben
      
      pulsanzahl  = 0;                    // Pulsanzahl zurücksetzen
      pausenanzahl =0;                    // Pausenanzahl zurücksetzen
      puls_summe=0;                      // Gesamt Pulse zurücksetzen
      pausen_summe=0;                      // Gesamt Summe zurücksetzen
                        
      }      

    }

}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.