Lichtsensor am MyAVR MK2 auslesen

OP #4649969
Lesenswert?

Guten Tag,
ich beschäftige mich seit ein paar Tagen mit Mikrocontrollern, genau 
genommen dem Atmega8A-PU (in AVR Studio muss ich immer Atmega8 angeben 
sonst funktioniert es nicht!?)

Ich habe mithilfe dieses Videos versucht den Lichtsensor auf meinem 
MyAVR-Board auszulesen.
https://www.youtube.com/watch?v=77o4I66WGHk&list=PLg8rGAQEOsuh9ZCwP6aW5ycCM5PFFqoNe&index=6
Mein Hintergedanke war das ich den Sensor am PIN C1 habe und das Signal 
über die PIN's B0-B5 über LED's ausgebe.

Ich habe versucht den Code soweit anzupassen, da im Video ein Atmega32 
verwendet wird und der Atmega8 kein ADATE (Auto-Trigger) hat.
Wenn ich das Programm aufspiele Leuchten aber durchgehen alle LED's, 
egal ob der Sensor Licht bekommt oder nicht.

Ich bin von dem kleinstem Teilungsfaktor ausgegangen,
Teilungsfaktor = 16MHz/200kHz=80 also ADPS = 111

Nochmal eine kurze Übersicht
Board: MyAVR MK2
µC: Atmega8A-PU
Belegung:
PC0(ADC0) = Sensor
PB0 - PB5 = LED's

Der Code sieht wie folgt aus:
1
#include <avr/io.h>
2

3

4
int main(void)
5
{
6
DDRB = 0b00111111; // Ausgabe des ADC-Messwertes
7

8
// ADC-Konfiguration
9
ADMUX |= (1<<ADLAR);
10
ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
11

12

13
  while(1)
14
  {
15
    while(!(ADCSRA & (1<<ADIF))) {}
16
    PORTB = ADCH;
17
    ADCSRA |= (1<<ADIF);
18
  }
19
}
Ich habe die Makefile noch hochgeladen falls die irgendwie hilfreich 
sein könnte.

Ich hoffe ihr könnt mir sagen was ich falsch gemacht/verstanden habe. :)

Viele Grüße
Troxan
Angehängte Dateien:
Gast #4649976
Lesenswert?

Wenn es mehr Lichtsensoren, als DEN LICHTSENSOR geben würde,
käme hier jetzt bestimmt die DÄMLICHE Nachfrage, nach dem
Typen des Lichtsensors.

Der Zwang, irgendwelche grottigen u-tube-Videos anzuschauen,
drückt schon mächtig auf die Hilfsbereitschaft...
Gast #4650012
Lesenswert?

Ja und - kann er das mit dem LDR nicht selber rausfinden?

Wenn das Verständnis für ADC am Spannungsteiler R / LDR
schon fehlt, kann man sich den Rest auch sparen...

Leute, die was lernen wollen, hängen ein Poti an den ADC und
schauen sich die Ergebnisse an, indem sie sich z.B. die sechs
höchstwertigen Bit des ADC-Ergebnisses auf B0..5 ausgeben
lassen.

Oder probieren vorher mal, sich die Bits eines langsamen
Zählers anzeigen zu lassen...

Dann weiß man schon mal, ob es an der Ausgabe, oder am
Einstellen des ADC liegt.

EIGENTLICH steht doch alles im Datenblatt.

ANSONSTEN kommt man ohne Findigkeit auch beim nächsten
Projekt nicht viel weiter...
OP #4650193
Lesenswert?

Ersteinmal Danke an alle,
ich habe den Plan jetzt ein wenig abgeändert, so das ich über ein Poti 
(an PC0 bzw. ADC0) die LED's ansteuern kann.
Genau genommen, soll der gemessene Wert Binär auf PB0-PB5 ausgegeben 
werden, also in binärer Zählweise 000001, 000010, 000011,... 111111 usw.
Diesmal habe ich versucht mich an dem AVR-GCC Tutorial zu orientieren.
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe

Hier mal meine Gedanken zu dem Code.

Teilungsfaktor:
Unter "Configuration Options" habe ich die Frequenz auf 8MHz gestellt 
(AVR Studio)
Also komme ich auf:
Tfmin = 8000000/200000 Hz=40
Tfmin = 8000000/50000 Hz=160
Daraus ergibt sich für ADPS = 110

ADEN: Einschalten; Ja
ADSC: Messvorgang starten; Ja
ADFR: Free Running Modus; Ja
ADIF: Interrupt; Nein
ADIE: Interrupt; Nein
ADPS2: Ja
ADPS1: Ja
ADPS0: Nein

Durch den "Free Running Modus", sollten nun also ständig Werte in das 
"ADC Data Register" geschrieben werden, wobei ADCL die ersten 8 Bit 
wieder gibt und ADCH die letzten beiden Bit wieder gibt, also 9 und 10.
Ich habe ich mir die Hilfsvariable "mess" erstellt, in die ich über den 
Bitweise verschieben Operator beide Werte hinein geschrieben habe.

Da ich nur 6 LED's angeschlossen habe, wollte ich den Wert noch auf 6 
Bit runter rechnen.
10 Bit ergeben max 1027
6 Bit ergeben max 63
1027/63 = 16,3 also teile ich "mess" durch 17.

Daraus habe ich Code erstellt:
1
#include <avr/io.h>
2

3

4
int main(void)
5
{
6
int mess; // ADC Data Register // ADCL und ADCH
7
DDRB = 0b00111111; // Ausgabe des ADC-Messwertes
8

9
// ADC-Konfiguration
10

11
/*
12
* ADEN (ADC Enable) : ADC aktivieren
13
* ADSC (ADC Start Conversion) : Messvorgang starten
14
* ADFR (ADC Free Run select) :  1 = "Free Running Modus; 0 = "Single Convention"
15
* ADIF (ADC Interrupt Flag):  Für den Interrupt Modus
16
* ADIE (ADC Interrupt Enable) : Für den Interrupt Modus
17
* ADPS2 (ADC Prescaler Select Bits): Teilungsfaktor
18
* ADPS1 (ADC Prescaler Select Bits): Teilungsfaktor
19
* ADPS0 (ADC Prescaler Select Bits): Teilungsfaktor
20
*/
21

22
ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (1<<ADPS2) | (1<<ADPS1);
23

24

25
  while(1)
26
  {
27
    mess = ADCL;
28
    mess += (ADCH<<8);
29
    mess = (mess/16); // Auf 6 Bit reduzieren
30
    PORTB = mess;
31
  }
32
}

Funktionieren tut es leider immer noch nicht, aber evtl. komme ich der 
Sache ja näher.
Es leuchten immer alle LED's.

Ich gehe jetzt schlafen, evtl. fällt ausgeschlafen ja noch etwas ein.

Ich bin für jeden Hinweis dankbar. :)

Viele Grüße
Timo
Gast #4650219
Lesenswert?

Schau mal nach dem ADLAR-Bit, wenn es richtig gesetzt ist,
musst du nur ADCH (obere 8 Bit) auslesen. Das Ergebnis teilst
du mit 2 x Shift-right durch 4 - und damit ist dein
6-Bit-Wert fertig.

Also:
    mess = ADCH
    mess = mess >> 2


Free Running ist für Anwendungen mit Messen und Anzeigen schon
mal Unsinn, weil niemand Messwerte, die sich mehr als 2...4 mal
in der Sekunde ändern, ablesen kann.

Wie willst du 15000 Messwerte / Sekunde ablesen?

Bei Regelschaltungen mag Free-Running erstmal besser aussehen,
dabei muss man aber die sich ergebende Auslese-Frequenz kennen,
um die ADC-Werte passend an die zeitabhängigen Auswertungs-
Gleichungen zu übergeben.

Grundsätzlich ist es besser, von einem Timer einen Interrupt
z.B. 100 mal pro Sekunde zu erzeugen. Und je nach Anzahl der
Durchläufe (40 Durchläufe = 1/5 Sekunde) das Hauptprogramm mit
einer ADC-Erfassung zu beauftragen...
(Firma: Vescomp) #4650318
Lesenswert?

Timo B. schrieb:
> 10 Bit ergeben max 1027
 10 bit ergeben immer noch max. 1023

> 6 Bit ergeben max 63
> 1027/63 = 16,3 also teile ich "mess" durch 17.
 Nein. 1024/64 = 16

 Und dein erstes Program war besser.
 Probiere das:
1
#include <avr/io.h>
2

3
int main(void)
4
{
5
DDRB = 0b00111111; // Ausgabe des ADC-Messwertes
6

7
// ADC-Konfiguration
8
ADMUX = (1<<ADLAR);
9
ADCSRA = (1<<ADEN) | (1<<ADSC) | (1<<ADFR) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
10

11
  while(1)
12
  {
13
    while(ADCSRA & (1<<ADIF)) {}
14
    PORTB = ADCH>>2;
15
  }
16
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren