mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LED Impulse Atmega8 Analog


Autor: Ganui Kliuz (Firma: BOSCH) (zmx2000)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Ich hab da ein kleines Problem mit dem ADC Channel des Atmega8 µC.
Folgendes Problem: Ich erzeuge eine lineare Rampe von 0V...5V innerhalb 
einer Sekunde und versuche anhand der eingelesenen analogwerte die LEDs 
blinken zu lassen (siehe anhang). Um auch hohe Frequenzen mitzubekommen 
habe ich ein Oszi angeschlossen.

Doch leider funktioniert es nicht so wie ich gehofft hatte. Der ADC 
scheint irgendwas einzulesen oder mein Code ist blödsinn (hab den code 
aus dem tutorial):

--------------------------------------------------
#include <avr/io.h>
//#ifndef F_CPU
/* prevent compiler error by supplying a default */

//#define F_CPU 8000000UL
//#endif
#include <util/delay.h>


uint16_t adc;

uint16_t ReadADC(uint8_t mux)
{
  uint8_t i;
  uint16_t result;

  ADMUX = mux;                                      // Kanal waehlen 
(ADC0)
  ADMUX |= (0<<REFS1) | (1<<REFS0);                 // AVCC als 
Referenzspannung nutzen

  ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) |(0<<ADPS0);        // 
Frequenzvorteiler 64 (40 - 160)



  // First Read Out um den ADC warmlaufen zu lassen //

  ADCSRA |= (1<<ADSC);                              // Start 
ADC-Wandlung
  while ( ADCSRA & (1<<ADSC) ) {
     ;
  }
  result = ADCL;
  result += (ADCH << 8);                          // ADCW muss einmal 
gelesen werden,

  result = 0;

//// Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden 
Wandlungen //////////

  for( i=0; i<2; i++ )
  {
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
    }
  result = ADCL;
    result += (ADCH << 8);        // Wandlungsergebnisse aufaddieren
  }
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren (2)

  result /= 4;                     // Summe durch vier teilen = arithm. 
Mittelwert

  return result;
}
////////////////////////////////////////////////////////////////////////

int main()
{

while(1)
{

adc = ((ReadADC(0)));

if (PIND & (1<<PIND4))
{

    PORTD |= (1<<PD0);
    _delay_ms(adc);
    PORTD &= ~(1<<PD0);
    _delay_ms(adc);

}
else PORTD &= ~(1<<PD0);
}

return 0;
}

-----------------------------------------------

Also ich sehe am Oszi nicht die Pulsbreitenänderung wie gedacht 
(hochfrequente impulse sinkend bis zu niederfrequente impulse (zum 
beispiel bei 5 V = 1023 entspricht 1023 ms)

Müsste doch so funktionieren oder?

Gruss

Autor: hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
for( i=0; i<2; i++ )
daraus werden nie!! 4 Messungen.

Tipp: 1023ms > 1 Sekunde ==>> Timing überdenken

ADC in C kann in einem Rutsch gelesen werden result = ADC;

Delay mit Variabler Zeit ==>> Speicherfresser, da Zeitberechnung 
eingebunden wird.

Nach mehr such ich jetzt mal nicht!!

Autor: Ganui Kliuz (Firma: BOSCH) (zmx2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohh danke hans..kleiner tippfelher. war ja vorher auf 4.
bin noch relativ neu auf disem gebiet :)

wenn nicht mit delay, wie macht man es sonst? Kenne leider nur diese 
Funktion..

Autor: Hubert G. (hubertg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo hast du deine Ports definiert.
Den ADC bei jedem Durchgang neu zu initialisieren ist nicht notwendig.
Als Abfrage genügt ein result = ADC;
Der ADC wird zu einem nicht definierten Zeitpunkt aufgerufen.
Variable als delay-Wert zu verwenden bläst den Code ziemlich auf.
Mit den delay wirst du  nicht glücklich werden, verwende Timer.

Autor: Ganui Kliuz (Firma: BOSCH) (zmx2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo hubert

die ports habe ich natürlich definiert, die habe ich nur ausgelassen:


int main()
{
DDRD |= (1 << PD0) | (1 << PD1);
....usw

Timer?
ich habe leider noch nie mit timern gearbeitet...wüsste jetzt nicht wie 
man da rangehen muss :(
wird der timer genauso gefüttert mit dem adc-wert wie der delay?

Autor: Hubert G. (hubertg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du nur den Codeteil postest von dem du glaubst das er fehlerhaft 
ist, ist es halt schwer festzustellen wo der Wurm liegt. Wer sagt was 
Absicht oder Fehler ist.
Die Timer sind im Tutorial ebenso gut beschrieben wie der ADC.
Du machst dir z.B. einen Timer mit 1ms Takt und wartest dann bei einem 
ADC-Wert von 500 diese Anzahl von Takte.

Autor: Ganui Kliuz (Firma: BOSCH) (zmx2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, hast natürlich recht.
Gibt es denn beispiele? Muss doch bestimmt jemand geben der das selbe 
problem hatte bzw eine lineares signal erzeugt und anhand dieser leds 
blinken lässt?

Das Tutorial lese ich mir auch durch :)

Autor: Ganui Kliuz (Firma: BOSCH) (zmx2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber nebenbei: Mit dem delay müsste es doch auch funktionieren oder? 
ausser dass er den speicher belastet. rein funktionstehnisch müsste es 
doch gehen. der niedrigste digitale wert ist 1 und der höchste ist 
1023....müsste doch auch so gehen ohne timer oder? :)

Autor: hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es sollte auch mit delay gehen, aber:

Deine Rampe läuft 1 Sek. deine Pausen/Impulse von 0-1023 ms.
Und wo dann gemessen wird weis keiner außer Gott.
Es können alle werte für die nächste Ausgabe rauskommen.
Wenn die Rampe extrem langsam ist (ein paar Minuten) hast du
den gewünschten Effekt.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Aber nebenbei: Mit dem delay müsste es doch auch funktionieren oder?

So auf jeden Fall nicht. delay_ms braucht einen konstanten Wert!

Das kannst du zb so machen
void delay( uint8_t ms )
{
  uint8_t i;

  for( i = 0; i < ms; ++i )
    delay_ms( 1 );
}

Aber back doch zunächst einfach mal kleinere Brötchen.
Vergiss die Rampe fürs erste, leg eine konstante Spannung an und sieh 
nach ob der ADC die korrekt einliest (= der Wert stimmt)

Autor: Ganui Kliuz (Firma: BOSCH) (zmx2000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, ich back erstmal kleine brötchen :) schritt für schritt....
danke für die tipps...

werde eure hilfe sicher noch benötigen..

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.