Hi Leute, Ich benutze einen ATmega8535 um eine Solarzelle automatisch nach der Sonne auszurichten (und weiter adwandlungen zur stromerfassung etc.) Hierzu habe ich 2 kleinere solarzellen , die rücken an rücken zusammengeklebt und antiparallel verschaltet wurde rechtwinklig an der solarzelle befestigt. durch eine kleine diodenschaltung bekommen dann 2 pins (PA3 und PA4) die ausgewerteten analogen signale und der controller soll nun nur noch beide signale analog einlesen, vergleichen und daraufhin entsprechend die motoren ansteuern. zudem wurde ein ldr installiert (PA6), der die ausrichtung abschaltet, sobald der himmel bewölkt ist. so, jetzt zu meinem problem... ich bin C-neueinsteiger und habe mich daran begeben, das programm (assembler und funktionsfähig!) in c umzuschreiben. wie im programm möchte ich die pins separat einlesen und auswerten, jedoch stimmen die MUX-werte des ports nicht mehr... das habe ich auch auf ner testplatine probiert und bei 2 programmierten wandlungen verdreht es auch schon die werte... hierzu erstmal ein programmausschnitt indem ich durch rumprobieren den mux so gesetzt habe, dass es soweit funktioniert. die funtionen sind soweit funktionsfähig und sollten eig. nichts zu sagen haben ^^ #include <avr/io.h> // µC Register einbinden #include <stdint.h> // Zahlenwerte (int) einbinden #define F_CPU 4000000 // Quarztakt bestimmen #include <util/delay.h> // Verzögerung einbinden #include "includeLCD.c" // Include-Datei für folgende LCD-Befehle uint16_t wert=0; uint16_t hilf1=0; uint16_t hilf2=0; uint16_t hell=0; uint8_t x=0; uint8_t y=0; void analog (void) { ADCSRA = 0xC5; //ADEN , ADSC und Pescaler auf 5 (32) loop_until_bit_is_set (ADCSRA, ADSC); wert=ADCW; _delay_ms(1); } //*Prüfe Position und speicher Werte in Akku & Wert*/ lcd_cursor(0,1); lcd_string(" Suche "); ADMUX = 0x02; //Linke Solarzelle???!!!!???? analog(); hilf1=wert; ADMUX = 0x06; //Rechte Zelle???!!!???? analog(); hilf2=wert; //*Werte Position aus*/ if(hilf1==hilf2) { if (y==1) { stop_li(); } if (y==2) { stop_re(); } y=0; } else { if(hilf1<hilf2) //Links ausrichten { y=1; links(); } else //Rechts ausrichten { y=2; rechts(); } } //*Prüfe ob Hell genug für Auswertung*/ ADMUX = 0x03; //!!!!!????!!!!!! analog(); hell=wert; while (hell < 0x00FF) { lcd_cursor(0,1); lcd_string(" Wolken "); lcd_cursor(0,2); lcd_string(" "); PORTC &= ~((1<<motor_li)|(1<<motor_re)); ADMUX= 0x06; //!!!!!????!!!!! analog(); hell=wert; } normalerweise sollte rechts: ADMUX = 0x02; links ADMUX = 0x03; ldr ADMUX = 0x06; wie kommen diese komischen dreher zusammen ?? falls der ausschnitt nicht reicht häng ich mein bisher zusammengebasteltes programm in assembler und c an. ich hoffe ihr könnt mir helfen =) danke schonmal gruß hendrik
Was funktioniert denn jetzt nicht? Im Datenblatt steht doch die eindeutige Zuordnung des ADMUX Registers. Und versuche mal eindeutige Variablennamen zu benutzen, x,y hilf, wert könnte man sicher schöner machen.
Um Fehlschaltungen und sonstige Logikfehler auszuschliessen, würde ich hergehen und mir einfach mal die Werte vom ADC am LCD ausgeben lassen. Der deiner Meinung nach richtige Wert müsste sich verändern, wenn du mit der Hand die jeweilige Solarzelle/LDR abschattest.
1 | if(hilf1==hilf2) |
Das ist sehr optimistisch. Selbst wenn sich eine Spannung nicht verändert, liefert ein ADC bei 2 Messungen normalerweise keine identischen Werte. Eine Abweichung von 1 bis 2 binären Digits ist normal, solange man nicht einen hohen Aufwand zur Rauschunterdrückung und Stabilisierung der Referenzspannung treibt. PS: Was spricht gegen Verwendung von zb. "ZelleLinks" "ZelleRechts" "Ldr" als Variablennamen anstelle von so nichtssagenden Namen wie x, y, hilf, test etc. Schreibst du deine Funktion so
1 | uint16_t analog (void) |
2 | {
|
3 | uint16_t wert; |
4 | |
5 | ADCSRA = 0xC5; //ADEN , ADSC und Pescaler auf 5 (32) |
6 | loop_until_bit_is_set (ADCSRA, ADSC); |
7 | wert = ADCW; |
8 | _delay_ms(1); |
9 | |
10 | return wert; |
11 | }
|
Dann kannst du sie so benutzen
1 | //*Prüfe Position und speicher Werte in Akku & Wert*/
|
2 | |
3 | lcd_cursor(0,1); |
4 | lcd_string(" Suche "); |
5 | |
6 | ADMUX = 0x02; //Linke Solarzelle???!!!!???? |
7 | hilf1 = analog(); |
8 | |
9 | ADMUX = 0x06; //Rechte Zelle???!!!???? |
10 | hilf2 = analog(); |
Gibst du zusätzlich der analog() Funktion auch noch den Kanal mit
1 | uint16_t analog ( uint8_t channel ) |
2 | {
|
3 | uint16_t wert; |
4 | |
5 | ADMUX = channel; |
6 | ADCSRA = 0xC5; //ADEN , ADSC und Pescaler auf 5 (32) |
7 | loop_until_bit_is_set (ADCSRA, ADSC); |
8 | wert = ADCW; |
9 | _delay_ms(1); |
10 | |
11 | return wert; |
12 | }
|
dann vereinfachen sich die Aufrufe zu
1 | //*Prüfe Position und speicher Werte in Akku & Wert*/
|
2 | |
3 | lcd_cursor(0,1); |
4 | lcd_string(" Suche "); |
5 | |
6 | hilf1 = analog( 0x02 ); |
7 | hilf2 = analog( 0x06 ); |
macht man sich dann für die magischen Konstanen 0x02 und 0x06 ein paar #define
1 | #define ZELLE_LINKS 0x02
|
2 | #define ZELLE_RECHTS 0x06
|
3 | |
4 | //*Prüfe Position und speicher Werte in Akku & Wert*/
|
5 | |
6 | lcd_cursor(0,1); |
7 | lcd_string(" Suche "); |
8 | |
9 | hilf1 = analog( ZELLE_LINKS ); |
10 | hilf2 = analog( ZELLE_RECHTS ); |
dann wird das ganze Codestück selbsterklärend und leicht lesbar
es funktioniert SO schon aber normalerweise sollten die MUX-werte , die nach der zuordnung im datenblatt vorgegeben sind auch zutreffen. Wenn ich beispielweise am PA0 und PA1 etwas einlese, ist für PA1 ADMUX = 0x00 und für PA0 ADMUX = 0x01 eintreffend... das verwirrt mich und muss an irgendetwas liegen. Die Muxwerte sind Durch ausporbieren rausgekommen und bei der auswertung unten im programm lese ich den selben pin einmal mit 0x03 und 0x06 ein o.O
Hendrik S. schrieb:
1 | > void analog (void) |
2 | > { |
3 | > ADCSRA = 0xC5; //ADEN , ADSC und Pescaler auf 5 (32) |
4 | > loop_until_bit_is_set (ADCSRA, ADSC); |
Wenn der Name stimmt, dann macht diese Funktion nichts. Und dadurch liest Du immer den Wert der vorherigen Wandlung aus. Du brauchst ein "loop_while_bit_is_set"
1 | > wert=ADCW; |
2 | > _delay_ms(1); |
Was soll das, ist Dir die CPU zu schnell? Peter
PS: Was spricht gegen Verwendung von zb. "ZelleLinks" "ZelleRechts" "Ldr" als Variablennamen anstelle von so nichtssagenden Namen wie x, y, hilf, test etc. Schreibst du deine Funktion so
1 | uint16_t analog (void) |
2 | {
|
3 | uint16_t wert; |
4 | |
5 | ADCSRA = 0xC5; //ADEN , ADSC und Pescaler auf 5 (32) |
6 | loop_while_bit_is_set (ADCSRA, ADSC); |
7 | wert = ADCW; |
8 | _delay_ms(1); |
9 | |
10 | return wert; |
11 | }
|
Dann kannst du sie so benutzen
1 | //*Prüfe Position und speicher Werte in Akku & Wert*/
|
2 | |
3 | lcd_cursor(0,1); |
4 | lcd_string(" Suche "); |
5 | |
6 | ADMUX = 0x02; //Linke Solarzelle???!!!!???? |
7 | hilf1 = analog(); |
8 | |
9 | ADMUX = 0x06; //Rechte Zelle???!!!???? |
10 | hilf2 = analog(); |
Gibst du zusätzlich der analog() Funktion auch noch den Kanal mit
1 | uint16_t analog ( uint8_t channel ) |
2 | {
|
3 | uint16_t wert; |
4 | |
5 | ADMUX = channel; |
6 | ADCSRA = 0xC5; //ADEN , ADSC und Pescaler auf 5 (32) |
7 | loop_while_bit_is_set (ADCSRA, ADSC); |
8 | wert = ADCW; |
9 | _delay_ms(1); |
10 | |
11 | return wert; |
12 | }
|
dann vereinfachen sich die Aufrufe zu
1 | //*Prüfe Position und speicher Werte in Akku & Wert*/
|
2 | |
3 | lcd_cursor(0,1); |
4 | lcd_string(" Suche "); |
5 | |
6 | hilf1 = analog( 0x02 ); |
7 | hilf2 = analog( 0x06 ); |
macht man sich dann für die magischen Konstanen 0x02 und 0x06 ein paar #define
1 | #define ZELLE_LINKS 0x02
|
2 | #define ZELLE_RECHTS 0x06
|
3 | |
4 | //*Prüfe Position und speicher Werte in Akku & Wert*/
|
5 | |
6 | lcd_cursor(0,1); |
7 | lcd_string(" Suche "); |
8 | |
9 | hilf1 = analog( ZELLE_LINKS ); |
10 | hilf2 = analog( ZELLE_RECHTS ); |
dann wird das ganze Codestück selbsterklärend und leicht lesbar
okay, danke =) eine andere schreibweise hat meinen fehler behoben, auch wenn ich kp hab , wo genau der fehler war...
Dein Fehler ist hier: Peter Dannegger schrieb: > Hendrik S. schrieb: >
1 | >> void analog (void) |
2 | >> { |
3 | >> ADCSRA = 0xC5; //ADEN , ADSC und Pescaler auf 5 (32) |
4 | >> loop_until_bit_is_set (ADCSRA, ADSC); |
5 | >
|
> > Wenn der Name stimmt, dann macht diese Funktion nichts. > Und dadurch liest Du immer den Wert der vorherigen Wandlung aus. > > Du brauchst ein "loop_while_bit_is_set"
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.