Hallo, ich möchte 3 - 4 Kanäle am AD Wandeln.
den Code aus dem Tut habe ich leicht abgewandelt und will damit testen,
ob das Wandeln klappt. Mein Problem ist, dass es Nur bei Channel 5
klappt, nicht aber bei Channel 4 und 3.
An Port B 1-3 habe ich einen RGB Stripe angeschlossen.
Ich habe bisher nur im Code den Channel geändert und dann aufgespielt...
Ich kann keinen Fehler finden. Danke für die Hilfe!!
1
/*
2
* test.c
3
*
4
* Created: 03.02.2012 09:26:14
5
* Author: Rudi
6
*/
7
8
#include<avr/io.h>
9
10
// Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
11
// unter Verwendung der internen Referenzspannung von nominell 1,1V.
12
// Zur Anpassung an andere AVR und/oder andere Referenzspannungen
13
// siehe Erläuterungen in diesem Tutorial und im Datenblatt
14
15
/* ADC initialisieren */
16
voidADC_Init(void){
17
18
uint16_tresult;
19
20
// interne Referenzspannung als Refernz für den ADC wählen:
21
ADMUX=(0<<REFS1)|(1<<REFS0);
22
23
// Bit ADFR ("free running") in ADCSRA steht beim Einschalten
24
// schon auf 0, also single conversion
25
ADCSRA=(1<<ADPS1)|(1<<ADPS0);// Frequenzvorteiler
26
ADCSRA|=(1<<ADEN);// ADC aktivieren
27
28
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
29
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
30
31
ADCSRA|=(1<<ADSC);// eine ADC-Wandlung
32
while(ADCSRA&(1<<ADSC)){}// auf Abschluss der Konvertierung warten
33
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
34
Wandlung nicht übernommen. */
35
result=ADCW;
36
}
37
38
/* ADC Einzelmessung */
39
uint8_tADC_Read(uint8_tchannel)
40
{
41
// Kanal waehlen, ohne andere Bits zu beeinflußen
42
43
ADMUX=(0b10100000|channel);
44
45
ADCSRA|=(1<<ADSC);// eine Wandlung "single conversion"
46
while(ADCSRA&(1<<ADSC)){}// auf Abschluss der Konvertierung warten
> Mein Problem ist, dass es Nur bei Channel 5> klappt, nicht aber bei Channel 4 und 3.
Wundert mich, dass es bei Channel 5 klappt, denn in deinem Quelltext
fragst du Channel 5 (und 4) gar nicht ab, sondern Channel 3:
> adcval = ADC_Read(3); // Kanal 3
Ansonsten besteht auch noch die Möglichkeit, dass die Schaltung falsch
ist (Schaltplan?).
Rudi schrieb:> Hallo, ich möchte 3 - 4 Kanäle am AD Wandeln.> den Code aus dem Tut habe ich leicht abgewandelt
Das war keine gute Idee.
Nimm doch den Code erst mal so, wie er ist. Einzig die Referenzspannung
passt du an.
Und dann testest du erst mal diesen Code.
Und wenn der dann zur Zufriedenheit funktioniert, dann fängst du an ihn
abzuwandeln.
Wie willst du denn unterscheiden, ob der Ursprungscode schon nicht
funktioniert hat oder ob du Fehler eingeführt hast?
> // Kanal waehlen, ohne andere Bits zu beeinflußen>> ADMUX =(0b10100000|channel) ;
Damit hast du schon mal
* Funktionalität weggeworfen.
Der Originalcode war insofern richtig, dass er Kanalwechsel
korrekt ausgeführt hat.
Deiner verändert das ADMUX Register komplett, wobei man dann
wieder raussuchen muss, was eigentlich die anderen Bits in ADMUX
machen. INteressiert hier doch keinen: Der Rest von ADMUX ist in
der Init Funktion korrekt eingestellt worden. Hier soll nur
noch der Kanal gewechselt werden
* mit der Schreibweise (kryptische Bitverschlüsselung) hast du dir
auch keinen Gefallen getan. Der restliche Code (den du übernommen
hast), hat überall die benannten Konstanten verwendet. Mit ein bischen
Übung weiß man, welche Konstante was macht. Bei dir muss man erst
mal das Datenblatt rauskramen
* return ADCH; // ADC auslesen und zurückgeben
Hast du ADLAR gesetzt? Man weiss es nicht, weil die ADMUX Zuweisung
möglichst kryptisch geschrieben ist.
Ist das ADLAR Bit überhaupt in ADMUX? Man weiß es nicht, weil
die ADMUX Zuweisung möglichst kryptisch geschrieben ist.
Danke für die schnelle Reaktion!
Ich habe jetzt alles zurück gesetzt, nur um das ADCH nutzen zu können
ADLAR gesetzt.
Klappt auch, aber nur eben Channel 5.
/*
* test.c
*
* Created: 03.02.2012 09:26:14
* Author: Rudi
*/
#include <avr/io.h>
// Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
// unter Verwendung der internen Referenzspannung von nominell 1,1V.
// Zur Anpassung an andere AVR und/oder andere Referenzspannungen
// siehe Erläuterungen in diesem Tutorial und im Datenblatt
/* ADC initialisieren */
void ADC_Init(void) {
uint16_t result;
// interne Referenzspannung als Refernz für den ADC wählen:
ADMUX = (1<<REFS1) | (1<<REFS0);
// Bit ADFR ("free running") in ADCSRA steht beim Einschalten
// schon auf 0, also single conversion
ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
ADCSRA |= (1<<ADEN); // ADC aktivieren
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man
liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu
lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while (ADCSRA & (1<<ADSC) ) {} // auf Abschluss der
Konvertierung warten
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
Wandlung nicht übernommen. */
result = ADCW;
}
/* ADC Einzelmessung */
uint8_t ADC_Read( uint8_t channel )
{
// Kanal waehlen, ohne andere Bits zu beeinflußen
ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
ADMUX=(1<<ADLAR);
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while (ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung
warten
return ADCH; // ADC auslesen und zurückgeben
}
/* ADC Mehrfachmessung mit Mittelwertbbildung */
/* beachte: Wertebereich der Summenvariablen */
uint16_t ADC_Read_Avg( uint8_t channel, uint8_t nsamples )
{
uint32_t sum = 0;
for (uint8_t i = 0; i < nsamples; ++i ) {
sum += ADC_Read( channel );
}
return (uint16_t)( sum / nsamples );
}
/* Beispielaufrufe: */
int main()
{
DDRB=0xff;
uint8_t adcval;
ADC_Init();
while( 1 ) {
adcval = ADC_Read(5); // Kanal 5
if (adcval<=128)
{
PORTB=0xff;
}
else{
PORTB=0x00;
}
// mach was mit adcval
//adcval = ADC_Read_Avg(2, 4); // Kanal 2, Mittelwert aus 4
Messungen
// mach was mit adcval
}
}
Rudi schrieb:> Ich habe jetzt alles zurück gesetzt, nur um das ADCH nutzen zu können> ADLAR gesetzt.>> Klappt auch, aber nur eben Channel 5.
Du veräppelst uns. Der aktuelle Code geht auch für Channel 5 garantiert
nicht.
Das Setzen von ADLAR gehört in geeigneter Form mit nach ADC_Init().
Hi,
zum testen habe ich ADC_Read();
nacheinander 5,4,3 eingesetzt, aufgespielt und getestet. Angeschissen
habe ich an die Kanäle jeweils ein 1k Poti. Eine Reaktion bekomme ich
aber nur an Port 5.