PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hilfe! Ich will an den ADC Port ...



Teslafan
03.11.2010, 19:12
Servus,

hab vor zwei Tagen mein Pollin Board zusammen gelötet und will mich jetzt mit voller Wucht ins AVR getümmel werfen :)
Jetzt steh ich jedoch vor ein paar kleinen Problemen :(

Hab momentan nen ATMega 32 drauf.

Will mit meinem Labornetzteil mal auf die ADC Eingänge gehen und da gehts schon los ...

- Der Pluspol kommt doch auf z.B. PC0 und der Minus vom Netzteil auf GND vom AVR?
- Ich will intern den AVCC auf AREF schalten, hab bei meinem Board auf AVCC 5V anliegen, das bedeutet das ich theoretisch auch mit meinem Labornetzteil auf max. 5V gehen darf oder?
- Muss zu Testzwecken der 10nF Kondensator zum glätten dazwischen geschaltet werden oder kann man den auch mal weg lassen?

Hab vor ersteinmal dieses C-Programm aufzuspielen um das ganze zu testen:

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

uint16_t readADC(uint8_t channel) {
uint8_t i;
uint16_t result = 0;

// Den ADC aktivieren und Teilungsfaktor auf 64 stellen
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

// Kanal des Multiplexers waehlen
// Interne Referenzspannung verwenden (also 2,56 V)
ADMUX = channel | (1<<REFS1) | (1<<REFS0);

// Den ADC initialisieren und einen sog. Dummyreadout machen
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADSC));

// Jetzt 3x die analoge Spannung and Kanal channel auslesen
// und dann Durchschnittswert ausrechnen.
for(i=0; i<3; i++) {
// Eine Wandlung
ADCSRA |= (1<<ADSC);
// Auf Ergebnis warten...
while(ADCSRA & (1<<ADSC));

result += ADCW;
}

// ADC wieder deaktivieren
ADCSRA &= ~(1<<ADEN);

result /= 3;

return result;
}

int main(void) {
uint16_t result = readADC(0); //Auslesen der analogen Spannungen an Pin 0,
// also ADC0. In result steht das Ergebnis.
return 0;
}

Kenn mich noch nicht so gut in C aus von daher noch meine letzte wirklich dumme Frage...

- Ich wandel das C-Prog in AVRStudio in ne Hex. um und übertrage das ganze dann mit PonyProg, wie kann ich da ein Result sehen? Wenn dies nicht möglich ist, ab welchem Teil des Programms kann ich z.B. Leuchtdioden leuchten lassen wenn eine bestimmte Spannung erreicht ist? Normalerweise nach "int main (void)" so das ich z.b. eine LED anschalte wenn der wert 512 erricht ist alsp bei 2,5V.

Ich danke euch allen schon mal im vorraus, ich weiß das sind echt blöde fragen aber ich hab die letzten Tage ein Lauflicht mit delay geschrieben und will jetzt auch mal was aufregenderes machen.

Gruß Andi

Besserwessi
03.11.2010, 19:38
Mit einem externen Netzgerät an den AD-eingang gehen ist nicht unbedingt besonders sicher. Da geht schnell mal was kaputt. Besser wäre ein Poti (z.B. 10 K) zwischen Vcc und GND von der µC-Platine.

Den Kondensator an AREF muß man nicht unbedingt haben, man kriegt damit aber weniger Rauschen hin.

Damit die LED auf den ADC reagiert, und das nicht nur einmal, braucht man eine Endlosschleife. Dadrin denn den ADC auslesen, dann Vergleichen und entspechend was ausgeben.

Teslafan
03.11.2010, 20:04
Will den ADC nutzen um damit zu einem späteren Zeitpunkt die Spannung meines Netzgerätes über den AVR auf ein Display auszugeben. Ist das machbar? Deshalb wollte ich auch mit dem Netzgerät auf PC0 und GND gehen.

BMS
03.11.2010, 20:06
Hallo,

so könnte das Programm aussehen, um den Wert des Analogeingangs mit einer Zahl zu vergleichen, und die LED zu schalten:


int main(void)
{
//Endlosschleife
while(1)
{
uint16_t result = readADC(0); //Auslesen der analogen Spannungen an Pin 0,
// also ADC0. In result steht das Ergebnis.

if(result>512)
{
//LED an
//musst du noch vervollständigen
}
else
{
//LED aus
//musst du noch vervollständigen
}

} //Endlosschleife bis hier

//an diese Stelle wird das Programm wegen der Endlosschleife nicht mehr gelangen,
//außer du verlässt die while-Schleife mit einem break;

return 0;
}


Du möchtest den Inhalt von "result" auf dem PC sehen? Funktioniert gut über das sog. UART und einem Terminal-Programm auf dem PC.
Dazu brauchst du auf jeden Fall eine kleine Zusatzschaltung mit MAX232 und 4 Elkos und kannst dann über eine serielle Schnittstelle (RS232) mit dem PC kommunizieren. Es gibt auch USB-Seriell Adapter ( die heutigen PCs werden wohl kaum noch eine serielle Schnittstelle haben).
Damit kannst du recht einfach von PC zu Mikrocontroller und umgekehrt Daten übertragen.
Siehe auch:
Daten und Texte zum PC übertragen (http://rn-wissen.de/index.php/AVR-Einstieg_leicht_gemacht#Daten_und_Texte_zum_PC_.C3 .BCbertragen)

Alternativ: ein Display anschließen (braucht aber einen größeren Brocken Software, gibts zum Glück im Internet)

Könnte auch noch Programmschnipsel für UART-Übertragung und einen Link zu einem vernünftigen Terminal nachliefern - falls erwünscht ;)

Grüße,
Bernhard

EDIT: Du kannst die Spannung des Netzgeräts schon messen. Wenn es maximal 5 V liefern kann und damit deine Vref nicht überschreitet, könntest du es direkt an den Analogeingang anschließen.
Ansonsten muss da noch ein Spannungsteiler dazwischen !!
Welche Spannung liefert das Netzteil maximal ?
Der Wert im Programm lässt sich dann auch relativ einfach wieder in den Spannungswert umrechnen.

PS: PC0 ist kein analoger Eingang! Beim Atmega32 sind die alle am PORT A !!!

Teslafan
03.11.2010, 20:11
Ja gerne mein Board hat einen Com Ausgang wäre echt super nett von dir.

BMS
03.11.2010, 20:25
gut :)
Als Terminal verwende ich das von Burkhard Kainka:
Hier ist es (http://www.elektronik-labor.de/RS232/2010Terminal.html)
Damit funktionieren auch die USB-auf-seriell-Adapter problemlos (habs selber ausprobiert).

Erst mal musst du den ganzen UART-Kram aktivieren und konfigurieren:


//Die Zahlenwerte hier sind für eine Baudrate von 9600 bei Verwendung eines 16Mhz-Quarzes gewählt
UBRRH=0; //Baudrate
UBRRL=103; //Baudrate
UCSRB=0b00011000; //internen UART einschalten
UCSRC=0b10000110; //Datenformat: 8 Datenbits, no Parity, 1 Stopbit

Die Werte für UBRRH und UBRRL geben die Übertragungsgeschwindigkeit an. Die Zahlenwerte dafür musst du im Datenblatt vom Atmega32 ab Seite 163 in der Tabelle - abhängig von Taktfrequenz und Baudrate ablesen.

Funktion, um ein Byte zu senden:


void serial_sendbyte(unsigned char i)
{
while( !(UCSRA & 32) );
//senden
UDR=i;
}


Funktion, um zu prüfen, ob der PC Daten gesendet hat (wenn ja, dann liefert diese Funktion "true"):


bool serial_available()
{
if(UCSRA & 128){return true;}
return false;
}


Funktion, um das empfangene Byte zu lesen


unsigned char serial_receive()
{
//bis Daten empfangen
while( !(UCSRA & 128) );
//einlesen
return UDR;
}


Die Funktionen senden nur Bytes. Das Terminal zeigt sie sowohl als Dezimalzahlen als auch als Text an (ASCII Tabelle sagt dir vielleicht was)

Grüße,
Bernhard

Teslafan
03.11.2010, 21:42
Vielen Dank,

das ist echt super von dir, hast mir wirklich enorm geholfen. Werde es gleich morgen mal ausprobieren. :)

Gruß Andi

Teslafan
03.11.2010, 23:02
So habs jetzt mal versucht, klappt leider noch nicht, hab ich da irgendwo noch nen fehler drin?
Hab ein 10k Poti zwischen VCC und GND geklemmt und den Abgang auf Port C.0 gesetzt. Hab zwischen VCC und GND 5V und kann das Poti auch bis 5V hochdrehen. Hab in nem Tutorial was von 2,56V gelesen am ADC Eingang...


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

uint16_t readADC(uint8_t channel) {
uint8_t i;
uint16_t result = 0;

// Den ADC aktivieren und Teilungsfaktor auf 64 stellen
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

// Kanal des Multiplexers waehlen
// Interne Referenzspannung verwenden (also 2,56 V)
ADMUX = channel | (1<<REFS1) | (1<<REFS0);

// Den ADC initialisieren und einen sog. Dummyreadout machen
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADSC));

// Jetzt 3x die analoge Spannung and Kanal channel auslesen
// und dann Durchschnittswert ausrechnen.
for(i=0; i<3; i++) {
// Eine Wandlung
ADCSRA |= (1<<ADSC);
// Auf Ergebnis warten...
while(ADCSRA & (1<<ADSC));

result += ADCW;
}

// ADC wieder deaktivieren
ADCSRA &= ~(1<<ADEN);

result /= 3;

return result;
}

int main(void)
{
//Endlosschleife
while(1)
{
uint16_t result = readADC(0); //Auslesen der analogen Spannungen an Pin 0,
// also ADC0. In result steht das Ergebnis.

if(result>128)
{
//LED an
PORTA = 0x01;
//Setze PinA.0 auf 1
}
else
{
//LED aus
PORTA = 0x00;
//Setze PinA.0 auf 0
}

} //Endlosschleife bis hier

//an diese Stelle wird das Programm wegen der Endlosschleife nicht mehr gelangen,
//außer du verlässt die while-Schleife mit einem break;

return 0;
}

BMS
04.11.2010, 17:17
Du musst den Anschluss A0 erst mal auf Ausgang schalten, sonst geht das nicht.


...
int main(void)
{

DDRA=0x01; //Diese Zeile muss noch rein

//Endlosschleife
while(1)
{
...

Teslafan
04.11.2010, 17:53
Vielen Dank, hatte ich vergessen. Werds nachher gleich mal probieren :)