www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Impulse schwanken im oberen Spannungsbereich?


Autor: Gunter (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich benutze einen Atmega8L zur Impulserzeugung.
Zunächst was ich vor habe (siehe Bild):

Ich habe vor mittels zweier 8 Bit Timer (T0,T2) und einen ADC Impulse zu 
erzeugen.
Beispiel: Ich stelle eine analoge Spannung von 2,5 Volt am ADC Kanal ein 
und erwarte eine bestimmte Breite des Impulses (zB. T = ca. 33 ms). Die 
Breite hängt dabei natürlich von meinem Preskaler (128), aktuellem ADC 
Wert (128) und CPU Takt (1MHz, internal RC) ab:

2,5 V --> entspricht 128 --> 1/(1000.000/128)*(255-128) = 32,768 ms

Stelle ich eine andere Spannung ein, so ändert sich auch die 
Impulsbreite.
Soweit klappt alles gut.
--> ABER nun das Problem: Im unteren Spannungsbereich ( bis ca. 3,5 V) 
sind die Impulse stabil bzw konstant. Sobald ich aber einen bestimmten 
Spannungsbereich ( > ca. 3,5 V) überschreite, fangen an die Impulse an 
zu schwanken. Aus irgendeinem Grund erhalte ich keine konstanten 
Impulsbreiten mehr, sondern, die Impulsperioden schwanken sehr. Hab 
einenOszi drangehangen und ich konnte messen, dass es mal 10 ms 
Impulsbreiten sind und mal 6,7 ms.
Ich kann nicht wirklich verstehen woran das liegen kann und grübele 
schon seit Stunden.

Der Code ist eigentlich sehr simple aufgebaut (siehe Anhang). Aber ich 
kann den Fehler nicht finden. Habe auch die ganze Zeit mit den 
Preskalern gespielt, aber da hat sich auch nix geändert.

Wäre super, wenn jemand mal über den Code schauen könnte und vielleicht 
erkennt wo der Wurm steckt ;)

Ich komme da wirklich nicht weiter

vielen Dank im voraus!!!

Gruss
Gunter

Autor: Gunter (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert

//// Impulse erzeugen mittels Timer Interrupt ////////////

#ifndef F_CPU
/* prevent compiler error by supplying a default */
#define F_CPU 1000000UL
#endif


#include <avr/interrupt.h>
#include <avr/io.h>

volatile char Pulslaenge = 0;  // Volatile aufgrund von Interrupt
char S1 = 0;           // Impulssignal 
char ImpulseStarten = 1;       // Impulserzeugung starten mit PD4


//////////////////////////////////////////////////////////////////////////////////////////////
// ADC  auslesen: ISR(ADC_vect)-Routine wird ausgeführt, wenn ADC Wandlung fertig ist! ///////
//////////////////////////////////////////////////////////////////////////////////////////////

ISR(ADC_vect) 
{  

  Pulslaenge = ADCH;  // Nur die obersten 8 Bit werden übernommen
      
}


///////////////////////////////////////////////////////////////////////////////////////////////
// Timer0 interrupt für ADC : alle 5 ms wird der ADC gestartet! ///////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

ISR(TIMER0_OVF_vect ) 
{  
      ADCSRA |= (1<<ADSC);    // ADC Messung Starten
  TCNT0 = 235;     // 1/(1000.000/256)*(255-235)= 5ms  
}


///////////////////////////////////////////////////////////////////////////////////////////////
// Timer2 interrupt: Pulslänge  -> kalkuliere nächstes Signal /////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

ISR(TIMER2_OVF_vect ) 
{

  //Impulse starten
  if (ImpulseStarten)       
  {                            //___     ___
    if (S1==1) { S1 = 0; }  // Mit jedem neuen Interrupt wird //entweder High oder Low erzeugt __|   |___|   |__
    else       { S1 = 1; }  
    
   }

  // Ansonsten mach nix    
  else if (!ImpulseStarten){;}

  
  if (S1) { PORTD |= (1<<PD1); } else { PORTD &= ~(1<<PD1); }

  TCNT2 = Pulslaenge; //Zählregister aktualisieren: abhängig vom //aktuellem ADC Wert!
}


///////////////////////////////////////////////////////////////////////////////////////////////
// Initialisierung Atmega8L ///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

void init() 
{
  //Ouputs: 
  DDRD  = (1 << PD1);      // Impulsausgang um z.B //eine LED anzusteuern    

  //Inputs: 
  DDRD &= ~(1 << PD4);      // Impulse starten  


  // Init Timer 0
  TCCR0 = ( 1 << CS02 );       // Preskaler:  256
    TIMSK = ( 1 << TOIE0 );     // Overflow Interrupt //einschalten
    TCNT0 = 235;        // init Wert:  overflow //alle 5ms  

  // Init Timer 2    
  TCCR2  = ( 1 << CS20 )|( 1 << CS22 );   // Preskaler:  //128    
  TIMSK  |= (1 << TOIE2);            // Overflow Interupt //einschalten  
  TCNT2= Pulslaenge;             // Aktueller ADC Wert //(Pulslaenge) an Zählregister übergeben 

  //ADC Konfiguration //
    ADMUX   = 0;                                // //Kanal ADC0 gewählt 
    ADMUX  |= (0<<REFS1) | (1<<REFS0) | (1<<ADLAR);       // //AVCC als Referenzspannung nutzen; left adjustet ADC Register (ADLAR) //gewählt (für ADCH)
    ADCSRA |= (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0) | (1<<ADIE);  // ADC //Einstellungen: ADC Enable, Teilungsfaktor muss zwischen 5 und 20 liegen: //8 gewählt,
                    // (ADC Interrupt Enable)
  ADCSRA &= ~((1<<ADPS2)|(1 << ADFR));                        // //Diaktiviere Rest                    
 

  // First Read Out, um den ADC warmlaufen zu lassen //
    ADCSRA |= (1<<ADSC);                // Start ADC-Wandlung 
    while ( ADCSRA & (1<<ADSC) ) { ; }  // Warten bis ADC Wandlung //fertig ist
}


/////////////////////////////////////////////////////////////////////////////////////////////
/////    MAIN
/////////////////////////////////////////////////////////////////////////////////////////////

int main()
{
  init();    // Initialisierug

  sei();     // Enable Interrupts

  while ( 1 ) {}

return 0;
}



Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wäre super, wenn jemand mal über den Code schauen könnte und vielleicht
>erkennt wo der Wurm steckt ;)

Poste besser mal den Schaltplan. Da wird der Wurm drin stecken.

Autor: Gunter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

noch was zum Verfahren:

Der Timer0-ISR holt alle 5 ms den aktuellen ADC Wert ab und der 
Timer2-ISR verarbeitet den ADC Wert zu einem Impuls mit entsprechender 
Pulsbreite.
Der ADC-ISR wird ja immer ausgeführt, wenn die ADC Wandlung beendet ist.

Autor: Gunter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

>>Poste besser mal den Schaltplan. Da wird der Wurm drin stecken.

mach ich....muss ich noch raussuchen

Autor: Gunter (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

hier ist der Schaltplan. Ich hofe es hilt weiter:

Autor: Gunter (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

hab vergessen den ADC Kanal einzuzeichnen ;)

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AVCC sollte doch auch an 5V liegen, oder?

Autor: Gunter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo


ja natürlich...in der eile hab ich es vergessen einzuzeichnen :)
benutze VCC für den ADC. Ist mit AVCC verbunden!!#

Danke für den Hinweis

Autor: Gont (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

keine Ideen woran es liegen könnte bzw. wo der Fehler eventuell im 
Schaltplan/Code ist?

Grüsse

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
warum schreibst du das überhaupt hin?

// Ansonsten mach nix
  else if (!ImpulseStarten){;}


da kannst du es doch auch weglassen. Ändert aber vermutlich nichts an 
dem Problem.
Du könntest aber versuchen z.b. 4 ADC Messungen zu machen und dann der 
Ergebniss runden. Um schwankungen am ADC auszugleichen.

Autor: Gont (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

die ADC Spannungist am Eingang stabil...kann also nicht daran liegen. 
Würde auch nicht erklären warum nur im oberen Spannungsbereich die 
Schwankung auftritt...

Autor: Gont (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Kann es vielleicht daran liegen, dass der ADC Takt anders gewählt werden 
muss. Also anstatt einen Teiler von 8 einen 16 Teiler wählen?


Grüsse

Autor: Gunter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

meint ihr man kommt mit dem CTC modus besser klar für dei 
IMPULSERZEUGUNG?
Hat da jemand Erfahrung?

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.