PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATMega32, Werte vom ADC ins EEPROM



Spessi
12.11.2008, 22:21
Hallo,
ich versuche gerade verzweifelt die Werte, die mir mein ADC zurückliefert, ins EEPROM zu schreiben, damit ich sie am PC auswerten kann (Platine ist schon fertig geätzt, aber kein UART dran, da ich da wohl nich dran gedacht hatte, dass ich die 1N4148 (genutzt als Temperatursensor) vielleicht auch erstmal auswerten sollte).

Im Anhang ist der Schaltplan, habe die Diode genauso an den ADC gehängt, wie es auch bei Thomas Pfeifer im Schaltplan von seinem Laminiergerät zu sehen ist. Bei 22°C messe ich 0,66V.

Hier ist der Code, der mir Probleme bereitet. Im EEPROM landet immer 00FF00FF00FF (usw.). Kann mir nicht vorstellen, woran es liegen könnte. Der ATMega läuft bei 1MHz und der ADC hat den Prescaler 4.



#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>

void waitms(int ms);

int* offset=0;

void initADC() {
// Den ADC aktivieren und Teilungsfaktor auf 4 stellen
ADCSRA = (1<<ADEN) | (1<<ADPS1);

// AREF als Referenzspannung nutzen [ist das Richtig?!]

// Den ADC initialisieren und einen sog. Dummyreadout machen [auch unnötig, oder? Wartezeit von wenigen µS sollte auch reichen... Aber ich hab's nicht eilig ;)]
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADSC));
}

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

// Kanal des Multiplexers waehlen
ADMUX = channel;

// 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;
}

result /= 3;
return result;
}


int main() {
unsigned char val;

DDRA &= ~(1<<PA0); /* Temperatursensor - Eingang */
DDRB |= (1<<PB0); /* Fixierwalze u. LED - Ausgang */
DDRC |= (1<<PC0); /* Power LED - Ausgang */
DDRD |= (1<<PD5); /* PWM f. Motor ON/OFF - Ausgang */

PORTB &= ~(1<<PB0);
PORTC |= (1<<PC0);
PORTD |= (1<<PD5);
initADC();

while(1==1) {
waitms(500);
val=readADC(0);
eeprom_write_byte ((void*)offset, &val);
offset=offset+0x01;
}

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

void waitms(int ms) {
int i;
for (i=0;i<ms;i++) _delay_ms(1);
}



Die Diode hängt am PA0.

Ich hoffe ihr könnt mir helfen, die richtigen Werte ins EEPROM zu bekommen, wird mit Sicherheit nur 'ne Kleinigkeit sein, die ich übersehen habe..
Danke schonmal im Voraus

linux_80
12.11.2008, 22:38
Hallo,

so auf die Schnelle sehe ich nur, daß die Variable, die den ADC-Wert aufnehmen soll (in main), nur 8 Bit breit ist, das reicht dann nicht ganz ?

Spessi
12.11.2008, 22:43
Oh, ja. Das liegt daran, dass ich da mittlerweile zuviel mit rumprobiert habe...

Ursprünglich war das eine Integer Variable.. Habe ich dann so in den Eeprom geschrieben:


void writeEeprom(int wert, void* address)
{
float localfloat = wert;
eeprom_write_block(&localfloat, address, sizeof(float));
}

Die Address (also Variable offset) wurde nach jedem Schreiben um 4 Byte erhöht. Trotzdem immer FFFFFFFF00000000FFFFFFFF (usw.)

sternst
12.11.2008, 22:50
int* offset=0;
...
val=readADC(0);
eeprom_write_byte ((void*)offset, &val);
offset=offset+0x01;
Du erhöhst offset in jedem Durchgang um 2, schreibst aber immer nur ein Byte. So kommt das Muster zustande, die 0x00 ist das was du schreibst, die 0xff ist die jeweils übersprungene leere EEPROM-Zelle.
Und wegen dem "&" vor dem val schreibst du Müll ins EEPROM.

Spessi
12.11.2008, 22:58
Hallo, ok, hab den Dereferenzierer rausgenommen.
*kopfkratz* Warum erhöhe ich den Offset um 2? Ist doch +1. (Muss zugeben: nach extrem langer Delphi Zeit sind meine C Kenntnisse wieder etwas eingerostet).

Jedenfalls wird jetzt nurnoch 0xFF geschrieben.

sternst
12.11.2008, 23:08
*kopfkratz* Warum erhöhe ich den Offset um 2? Ist doch +1.
"+1" bedeutet bei Pointern "lass den Pointer auf das nächste Element zeigen". Und da das "Element" hier ein int ist, erhöhst du offset damit um 2.


Jedenfalls wird jetzt nurnoch 0xFF geschrieben.
Wenn du GND als Referenzspannung nimmst, bekommst du natürlich als Ergebnis immer 0x03FF. Und davon schreibst du das Low-Byte ins EEPROM, also 0xFF.

McJenso
12.11.2008, 23:13
Hallo,

schau dir noch einmal die Beschaltung von AREF und AVCC. Du möchtest VREF nutzen und legst den Pin auf Gnd? :-k
AVCC mit einem Kondensator nach +5V zu verbinden ist böse.
Das ist sogar dann schlecht, wenn man den ADC nicht nutzt.
Hier (http://www.kreatives-chaos.com/artikel/avr-grundschaltungen) sind die Beschaltungen sehr schön verdeutlicht (Abschnitt A/D-Wandler).

Gruß

Jens

Spessi
12.11.2008, 23:28
Ja, das war die Sache die mich am meisten verwirrt hat. Die einen sagen: machs so, die anderen sagen: machs so und so... Naja... Ich würde einfach nur gerne den ADC Wert auslesen, wäre das trotz der offensichtlich vermurksten Schaltung noch möglich?

Hab eben mal die EEPROM Schreibroutine komplett rausgehauen und mit einer if abgefragt... Der ADC Wert scheint immer 1024 zu sein (1023)

sternst
12.11.2008, 23:37
Naja... Ich würde einfach nur gerne den ADC Wert auslesen, wäre das trotz der offensichtlich vermurksten Schaltung noch möglich?
Du musst C2 durch eine Drahtbrücke ersetzen und die Verbindung von AREF zu GND auftrennen. Wenn du dann über ADMUX als Referenzspannung AVCC oder die interne Referenz auswählst, kannst du was messen. Richtig gut wird das aber nicht gehen, denn du bräuchtest auch noch einen Kondensator von AREF nach GND.

Spessi
13.11.2008, 00:12
Hey. Besten Dank! So funktioniert es...


Ich bin echt überrascht. Hab mir aus nem alten Drucker die Fixiereinheit ausgebaut und angesteuert für das Toner-Transfer-Verfahren. Eben mal ne Platine auf ne ungesäuberte Platine gebügelt. Ich hab ja mit allem gerechnet, aber nicht mit so geilen Ergebnissen. Besten Dank nochmal euch allen!