PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit ADC



cesupa
12.05.2008, 12:09
Hallo,

ich versuche gerade mit meinem Atmega8 auf meinem Pollin-Board eine Spannung über den ADC zu erfassen. Ziel ist es, dann einen Temperatursensor anzuschließen und die Temperatur zu messen, leider scheitere ich schon an einer einfachen Spannungsmessung. Von der Schaltung her hab ich zwei 1,5K Widerständer in Reihe geschaltet, die an einer externen 5V Spannung anliegen, dazwischen greif ich am ADC0 die Spannung ab, die ja 2,5V betragen müsste. Wenn ich das ganze jetzt laufen lasse und mir die ADC-Werte ausgeben lasse, schwanken die ganz schön:



6.000e+02 6.000e+02 5.000e+02 5.000e+02 5.000e+02 5.000e+02 5.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 5.000e+02 5.000e+02 5.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 4.000e+02 5.000e+02 5.000e+02 5.000e+02 1.000e+03 7.000e+02 1.000e+03 6.000e+02 1.000e+03 6.000e+02 1.000e+03 6.000e+02 1.000e+03 7.000e+02 1.000e+03


Mein Quellcode für die ADC-Abfrage sieht wie folgt aus:



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

ADMUX=mux;
ADMUX|=(1<<REFS0);//|(1<<REFS1);

ADCSRA|=(1<<ADEN)|(1<<ADPS1)|(1<<ADPS2); //(ADSC<<1)|(ADATE<<1)|
ADCSRA|=(1<<ADSC);
while(ADCSRA & (1<<ADSC));
result=ADCW;
result=0;

for(i=0;i<4;i++)
{
ADCSRA|=(1<<ADSC);
while(ADCSRA & (1<<ADSC));
result+=ADCW;
}

ADCSRA&=~(1<<ADEN);
result/=4;
return result;


}

double getTemp(uint8_t channel)
{
uint16_t adc;
double U=0, step=0,T=0;

adc=readADC(channel);
step=(((double)5.00)/((double)1024.00));
U=((double)step)*((double)adc);
//T=(((double)118.321)*((double)U))-((double)215.583);

return (double)(adc);
}


Da das mein erster Versuch mit dem ADC ist, bin ich mir auch nicht ganz sicher, ob ich das so richtig mache bzw. weiß ich nicht, warum die ADC-Werte so schwanken.
Ich lasse mir das ganze dann über RS232 ausgeben:



int main()
{
double temp;
char buf[20];

uart_init();

while(1)
{
temp=(double)getTemp(0);
send(dtostre((double)temp,buf,3,0));
send(" ");
buf[0]='\0';
wait_sec(1);
}
}


Wenn das dann funktioniert möchte ich den einen widerstand an der Masse mit einem KTY 81-120 ersetzen, um dann die Temperatur zu ermitteln, hab ich mir mit ein paar Messadaten aus dem Datenblatt eine lineare Funktion ermitteln lassen, in die ich dann bloß noch die gemessene Spannung einzusetzen brauche und die Temperatur erhalte. Leider weiß ich nicht, ob es da evtl. eine bessere Möglichkeit gibt, da diese Variante ziemlich viel Speicher verschlingt...

Gruß
cesupa

franzl
12.05.2008, 13:18
Hi,
also so weit ich das sehe fängst du sofort nach dem einschalten des ADC mit der Messung an. Der ADC braucht aber eine Zeit bis er sich eingeschwungen hat. Das heißt du müsstest den ersten Wert den du einliest einfach verfallen lassen und nicht beachten, dann müssten die Schwankungen zurückgehen.
Hoffe das hilft dir weiter.
mfg franz

cesupa
12.05.2008, 13:46
Mache ich das nicht schon mit:



//...

ADCSRA|=(1<<ADEN)|(1<<ADPS1)|(1<<ADPS2);
ADCSRA|=(1<<ADSC);
while(ADCSRA & (1<<ADSC));
result=ADCW;
result=0;

//...


?

franzl
12.05.2008, 14:05
Ja, machst du damit. Hat ich übersehen. Es könnte allerdings auch an der Beschaltung des AVCC Pins liegen. Weiß jetzt nicht ob der beim Pollin-Board so wie im Datenblatt beschrieben beschalten ist. Mit 10µH nach +5V und mit 100nF nach GND.
mfg franz

cesupa
12.05.2008, 14:25
Okay, ich habs hingekriegt, es lag einfach daran, dass ich eine externe Versorgungsspannung für die Widerstandsschaltung verwendet habe und nicht die Spannung vom Pollinboard, die auch am Atmega anliegt.

Gruß
cesupa

Grandalf
16.06.2008, 13:11
hi ich habe auch eine externe spannungsquelle und bei mir lasse ich mir den wert per LED's anzeigen (mein quellcode is der von oben) nur bei mir spielen die LED's vollkommen verrückt

kann das auch an der externen spannungsquelle liegen?

gothmog
16.06.2008, 13:31
@Grandalf: Hast du die Masse der externen Spannungsquelle mit der von der Versorgungsspannung verbunden?

Gruß
Jonas

Grandalf
16.06.2008, 13:58
jo hab ich und das andere kabel am pin0 vom porta

gothmog
16.06.2008, 14:33
Naja, dann sollte es nicht daran liegen, dass die Spannungsquelle extern ist. Zur Sicherheit kannst du ja mit dem Multimeter an dem ADC-Pin die Spannung gegen den AGND pin messen. Wenn da die richtige Spannung ansteht, dann muss der Fehler woanders liegen
-> Code (+ Schaltplan, wenn vorhanden) posten

Grandalf
16.06.2008, 15:13
ne stimmt wohl anscheinend alles mit der spannungsquelle
in ordnung

hier mein code




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

uint16_t ReadChannel(uint8_t mux)
{
uint8_t i;
uint16_t result;
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0); // Frequenzvorteiler
// setzen auf 8 (1) und ADC aktivieren (1)
ADMUX = mux; // Kanal waehlen
ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen

/* 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
}
result = ADCW; // ADCW muss einmal gelesen werden,
// sonst wird Ergebnis der nächsten Wandlung
// nicht übernommen.

/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
result = 0;
for( i=0; i<4; i++ )
{
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) )
{
; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
result /= 4; // Summe durch vier teilen = arithm. Mittelwert
return result;
}

void ShowByte(uint16_t wert)
{
PORTC = wert;
}

int main (void)
{
DDRC = 0;
PORTC = 0;
uint16_t adcval = 0;

while(1)
{
adcval = ReadChannel(0); /* MUX-Bits auf 0b0000 -> Channel 0 */
ShowByte(adcval);
}
return 0;
}




und schaltplan is eigendlich nur das PORT C an jedem pin ne LED hat
AVCC und VCC sowie AGND und GND sind verbunden und von meiner 2ten spannungsquelle wie gesagt das eine an GND das andere an PORTA pin0
von nem atmega16 welcher auf dem evaluationboard von pollin sitzt und wo das addonboard noch dabei is www.pollin.de (für die datenblätter)

angeschlossen is also wie ich glaube alles richtig. komisch finde ich nur das am PORTC 3 LED's dauerhaft leuchten (3, 5 und 6) egal was am analogpin anliegt (selbst wenn reset gedrückt wird
die gehen einfach nicht mehr aus)

led 7 und 8 verhalten sich normal und led 1 und 2 flackern wie wild
led 4 is immer aus....

eigendlich sollte dort wenn ich das richtig gemacht hab einfach der ADC wert ausgegeben werden indem die 8 leds als byte leuchten

gruß Grandalf

gothmog
16.06.2008, 15:26
Hm, du solltest DDRC = 1 setzen, um den PortC als Output zu konfigurieren. Ist außerdem gewährleistet, dass die Spannung am ADC0-Pin kleiner als 2,56V ist?

EDIT: Sorry, Schwachsinn, es muss natürlich DDRC=0xFF heißen

Gruß
Jonas

Grandalf
16.06.2008, 15:29
DDRC = 1; Oo? ouch ok dann macht das sinn ^^


und am PORTA PIN0 is kleiner als 2,56V

was passiert denn wenns mehr wird?


EDIT: aehm die LED'S verhalten sich imemrnoch so

gothmog
16.06.2008, 15:49
Also dass 1 und 2 flackern ist zu erwarten, der Messwert schwankt ja etwas. Was machen die LEDs, wenn du den ADC0 auf GND legst?

Grandalf
16.06.2008, 15:56
wenn des auf 0 is dann flackerts am stärksten aber es flackert bei egal welchem wert aber das hat ich mir schon gedacht das es an messfehlern liegt aber wieso 3-6 nicht das machen was sie sollen versteh ich nicht

EDIT: sorry also wenn ich analog auf 0 setze dann flackert nur noch LED 1
LED2 is aus
LED 3 und 4 sind dauerhaft an egals was man macht
LED 5 is aus egal was man macht
LED 6 wie LED 3 und 4
LED 7 und 8 sind aus (aber halt nur weil 0V anliegen)

gothmog
16.06.2008, 16:04
Mit was für einer Taktfrequenz läuft der Controller?

Grandalf
16.06.2008, 16:09
4MHz jedenfalls läuft damit meine _delay.h
der quarz auf dem board is nen 16MHz

aber es sind auch nur 4MHz da ich das als ich mal den internen taktgenerator eingestellt hab und 2 LED's abwechselnd an und aus machte im sekunden takt da hatte der controller umgerechnet 4 MHz


(ps: hehe meine nachricht muss min 15 zeichen haben daher soviel drumrumgerede)

gothmog
16.06.2008, 16:57
Ok, dann ist der ADC-Takt im Rahmen. Mir fällt grad auf dass der ADC-Pin nicht als Eingang konfiguriert ist. Mach das mal, und schalte den Pull-up aus!
Gruß
Jonas

Grandalf
17.06.2008, 07:17
guten morgen

also ich habe nun mal den pin0 portA als eingang festgelegt aber was meinst du mit pullup?

aber mir fällt heut morgen was ganz komisches auf

gestern konnt ich schön von 0V bis hoch zu 32V (theoretisch habe aber nur bis 2,5V) regeln

heute morgen mach ich das netzteil an (an meiner schaltung ist nichts verändert worden) und das netzteil steht auf 3,7V bei 10mA und das bei der einstellung bei der eigendlich 0V sein müssten. wieso das auf einmal?

sobald ich den GND wegnehme und bei AREF anschließe verhält sich das netzteil wieder normal aber der controller macht nix

ach und komisch is sobald einmal diese 3,7V anliegen gehen alle LED's (bis auf LED 4 mal wieder) an und bleiben auch an selbst wenn ich die kabel abnehme und reset betätige.
nur wenn ich das programm nochmal neu aufspiele komm ich wieder in die startposition.....ist etwa was kaputt gegangen?

Grandalf
17.06.2008, 07:57
OK nach längerem warten kehrt das alte verhalten des analogen eingangs zurück und von 3,7V gehts wieder runter auf gewünschte 0V

gothmog
17.06.2008, 10:07
Was für ein Netzteil ist das? Mit Strom- und Spannungsbegrenzung?
Wie hast du denn AREF beschaltet? Am besten erstmal offenlassen, oder mit Abblockkondensator gegen Gnd, aber nicht direkt an gnd!
Zum Thema Pull-up Widerstand würde ich dich bitten, die Forensuche oder einfach das Datenblatt(unter IO-Ports) zu benutzen. Der Pull-Up Widerstand vom benutzten ADC-Pin muss ausgeschaltet sein!
Ach ja, du hast doch Vorwiderstände an den LEDs?

Grandalf
17.06.2008, 15:10
hi also: Netzteil hat strom und spannungsbegrenzer und nun läuft das auch wieder wie es soll allerdings nur so lange ich an AREF 5V angelegt habe (von VCC herkommend)

+ is an PIN0 PORTC und GND an GND


ja die LED's haben vorwiderstände und was ein pull-up-widerstand is weiß ich wohl, nur hatte ich dich oben falsch verstanden. bzw wollte wissen wo du meinst wo der eingesetzt werden soll. weil widerstände rausnehmen kann ich nicht weil die platine halt so is kann aber weil ich brücken setzen kann welche dazusetzen

gothmog
17.06.2008, 17:24
Ich meinte den internen Pull-up Widerstand des Pins (Datenblatt -> IO Ports). Du schaltest ihn aus, indem du ins PORT-Register 0 schreibst, wenn der Pin als Eingang konfiguriert ist.
AREF an 5V ist schlecht, weil AREF mit der internen Spannungsreferenz verbunden ist und du also 2,56V mit 5V verbindest. Also entweder unbeschaltet lassen oder über Kondensator an GND.
Was mit deinem Netzgerät los ist weiß ich nicht... Wenn es in derselben Stellung der Regler einmal 3,7V und einmal 0V rausgibt, bedeutet das womöglich, dass es bei 0V in der Strombegrenzung hängt. Bei 3,7V wahrscheinlich in der Spannungsbegrenzung(oder immer noch in der Strombegrenzung).

Grandalf
18.06.2008, 07:18
hi

also ich habe nun folgendes

DDRA = 0; //eingang
DDRC = 1; //ausgang
PORTC = 0xff; //alle LED's an
PORTC = 0x00; //alleLED'S aus

doch es änder sich nix
selbst wenn ich nen delay von einer sekunde dazwischen baue führt der die schritte nicht aus außer bei LED 0, 1,6 und 7.
sprich wenn ich reset drücke dann leuchten 0,1,6 und 7 kurz auf und sind dann aus.
LED 2, 3 und 5 sind wie immer einfach nru an und LED 4 is immer aus
habe wie gesagt schon daran gedacht das es nen platinen fehler sei oder im controller sei was kaputt gegangen (was auch immer) aber ich habe das ganze 2 mal hier (platine und kontroller) und bei der anderen verhält es sich genauso.

und wie gesagt was das netzteil angeht so spuckt es halt 3,7V aus (die komischerweise auch fest sind sprich egal welche einstellungen ich beim netzteil mache es bleiben 3,7V und 0,01A) wenn ich keine brücke zwischen VCC und AREF habe und wenn ich eine einbaue kann ich meine gewünschten 0V - 2,5 V anlegen nur dabei knallte nach ca 10 min die sicherung im netzteil durch wenn ich >0V anliegen habe

aehm wie groß meinst du sollte nen kondensator zum von AREF zu GND wohl sein, oder einfach nur groß?

gruß grandalf

Grandalf
18.06.2008, 07:47
OK nen 1mF kondensator hat den selben effekt wie als ich VCC mit AREF verbunden habe (nur denk ich mal das es nun nicht mehr nach 10 min die sicherung raushaut *g*)

gothmog
18.06.2008, 10:02
1mF ist viel zu groß. 100n oder 10n sind üblich (Abblockkondensator). Vielleicht solltest Du dich erstmal über ein paar Grundlagen informieren, und klein anfangen. Du hast ja nichtmal die IO-Ports im Griff, da macht es keinen Sinn, den ADC miteinzubeziehen und das dann über die IO-Ports zu "debuggen" (es gibt dann zu viele potentielle Fehlerquellen). Das Pollin-Board ist doch recht groß. Sind die Jumper richtig gesetzt? Mach mal eine Durchgangsprüfung von den Controller-Port-Pins zu den jeweiligen LEDs. Vll. sind die gar nicht richtig angeschlossen...
Gruß
Jonas

Gruß
Jonas

Grandalf
18.06.2008, 11:15
im grunde hab ich die IO-Ports im griff
nur habe wahrscheinlich letzte woche meinen controller kaputt geschossen...

was den kondensator angeht so ist es doch egal ob er groß ist oder nur die 10-100nf hat wie du meinst
hatte gerad einen hier liegen daher hab ich den genommen und ich mein seine aufgabe erfüllt er!

die platine funktioniert (hab gerad alles nachgemessen etc)

daher wird der controller wohl irgend einen knacks weg bekommen haben.
werde um 2 uhr nen neuen haben und testen ob der sich anders verhält, da das programm eigendlich ja auch funktionieren müsste (is schließlich aus nem tutorialpdf und der erste poster hier im thread hat es auch damit hinbekommen)

naja och such mir mal nen 100nf elko

gothmog
18.06.2008, 11:45
Ok, vielleicht geht´s ja mit dem neuen Controller.


was den kondensator angeht so ist es doch egal ob er groß ist oder nur die 10-100nf hat wie du meinst
hatte gerad einen hier liegen daher hab ich den genommen und ich mein seine aufgabe erfüllt er!

Was meinst du denn ist seine Aufgabe? Ein Abblockkondensator soll hochfrequente Anteile einer Spannung ableiten. Zwischen 1mF und 100nF sind 4 Größenordnungen, überleg mal, was das für das Frequenzverhalten bedeutet...

Grandalf
18.06.2008, 13:09
so hab nun den neuen controller mit neuem board drangepackt und der LED fehler ist dort unverändert

und das bei jedem programm selbst wenn da nur

main (void){
while (1)
{
}
return 0;
}

als programm drin is

gothmog
18.06.2008, 13:22
Hast du überprüft, dass die LEDs mit den entsprechenden Pins (und nur mit diesen) verbunden sind? Wenn ja, dann schreib doch noch DDRC = 255 (EDIT: Wert korrigiert); PORTC=255; ins Programm, oder wahlweise irgendeinen festen Wert. Wenn die LEDs dann nicht machen was sie sollen, dann stimmt wohl irgendwas grundlegend nicht .

Gruß
Jonas

Grandalf
18.06.2008, 14:50
ja sagte ich doch schon bereits
habe nun

DDRC = 1;
while(1)
{
PORTC = 0xff;
_delay_ms(250);
PORTC = 0x00;
_delay_ms(250);
}
return 0;

ergebnis....immernoch das selbe.
pin 0 1 6 und 7 funktionieren und 2 3 4 5 sind starr

wenn ich aber PORTD statt PORTC nutze funktioniert alles so wie es soll ohne probleme
ich brauch nichtmal den kondensator (egal ob 10nf oder 1mf).

gothmog
18.06.2008, 15:19
Hmpf, es muss DDRC = 255 heißen, da hab ich Unsinn geschrieben. Es müssen ja alle Pins als Ausgang konfiguriert werden. Hab´s oben korrigiert, sorry dafür.

Gruß
Jonas

Grandalf
24.06.2008, 09:50
So programm funktioniert

nur lag das problem an dem PORTC
habs nun auf PORTD laufen und dort klappts wunderbar

irgendwie hab ich dauerlow bzw dauerhigh gesetzte pins an meinem atmega16

egal was ich einstelle sie sind immer fest
das betrifft halt bei portC den pin 2,3,5 als high und pin 4 als low
bei portB sind es pin 1,2 usw nur portD schein in ordnung zu sein

komischer weise hab ich das mit allen meinen atmega16'ern und all meinen evaluation-board bzw addon-boards egal in welcher kombination (habe alles 3mal)

sast
24.06.2008, 10:15
"das betrifft halt bei portC den pin 2,3,5 als high"

Datenblatt Seite 5:
If the JTAG interface is enabled, the pull-up resistors on pins
PC5(TDI), PC3(TMS) and PC2(TCK) will be activated even if a reset occurs.
Port C also serves the functions of the JTAG interface and other special features of the
ATmega16 as listed on page 61.

Vielleicht solltest du dich mal um die Fuses kümmern und das Datenblatt lesen bezüglich der Ports.

sast

Grandalf
24.06.2008, 10:29
und wieso is das auch bei portb und porta?

und 2. wie bekomm ich das wieder weg?

sast
24.06.2008, 10:47
Ich beschäftige mich nicht mit dem m16. Hab nur mal interessehalber reingesehen ins Datenblatt. Und da viel mir die Pin Übereinstimmung zum JTAG Interface auf. Wenn du es nicht brauchst, kannst du es über die Fuses ausschalten. Da mach dich aber bitte erst mal schlau was du wirklich brauchst, denn bei den Fuses kann man sich auch selber aussperren (für immer). Und noch mal der Hinweis: Datenblatt lesen hilft bei den meisten Anfangsproblemen.

sast

Grandalf
24.06.2008, 12:02
ja ich hab mir gerad das datenblatt durchgelesen und
1. find ich die stelle die du meinst nicht und
2. was du mit fuses meinst versteh ich gerad auch leider nicht

sast
24.06.2008, 12:27
Wie stellst du denn deine Taktfrequenz ein?
Mein Datenblatt zum m16 hat 3xx Seiten. Also wenn du das schon durch hast, dann Hut ab. Ansonsten solltest du mal auf die Atmel Webseite gehen und dir das ausführliche Datenblatt runterladen.

Zu den Fuses siehe z.B.
https://www.roboternetz.de/wissen/index.php/Avr#Die_Fusebits

Hoffe das hilft dir weiter. Wenn du konkrete Hilfe zu deiner Entwicklungsumgebung brauchst, dann musst du noch sagen mit was du programmierst und flashst.

sast