Hallo zusammen, Wir haben ein Problem: Wir machen gerade einen Sonnenfolger für eine Solarzelle. Damit das ganze möglichst Stromsparend ist, schicken wir den uC in den Power down mode. Das funktioniert super. Wenn er dann wieder Aufwacht spinnt der PWM, d.H. Die Solarzelle wackelt herum. Das beruhigt sich nicht, bis wir den Stecker ziehen. Mit dem DSO haben wir ausgemessen, dass der PWM viel zu kleine signale sendet (1.8uS statt 1-2ms). Während dem Schlafmodus steht die Solarzelle still. Wir benutzen einen aTmega 328p. Vielen Dank Hier noch der Code: #include "u8g.h" #if defined(_AVR_) #include <avr/interrupt.h> #include <avr/io.h> #include <avr/sleep.h> #include <avr/power.h> #include <util/delay.h> #include <avr/wdt.h> #endif #define LINKS OCR1A-=10 #define RECHTS OCR1A+=10 #define RUNTER OCR1B+=10 #define HOCH OCR1B-=10 #define SOLARAZIMX #define SOALRAZIMY uint8_t adc(uint8_t Nr); uint8_t taster(uint8_t Nr); uint8_t akkuadc(void); void watchdog_init(void); void watchdog_ein (void); void watchdog_aus (void); void PWM_init (void); uint8_t stateazim=9, stateelev=9, azimausgabe=3, elevausgabe=3, azimgrad=0, elevgrad=0, ladeflag=0, maincounter=0, flag=0; enum stateazim {left, right}; enum stateelev {up, down}; u8g_t u8g; void u8g_setup(void); void sys_init(void); volatile char ISR_zaehler = 0, ms100 = 0, sec = 0, min = 0; //ISR void u8g_setup(void) { //u8g_InitSPI(&u8g, &u8g_dev_ssd1306_128x64_hw_spi, U8G_PIN_NONE, U8G_PIN_NONE, PN(2, 1), PN(2, 0), U8G_PIN_NONE); // PB4 PB0 PC6 u8g_InitSPI(&u8g, &u8g_dev_pcd8544_84x48_hw_spi, PN(1,5), PN(1,4), PN(1,3), PN(1,0), PN(3,6)); //uint8_t u8g_InitSPI(u8g_t *u8g, u8g_dev_t *dev, sck, mosi, cs, a0, reset) u8g_SetFont(&u8g, u8g_font_baby); //sce, dc, reset // u8g_SetRot180(&u8g); } void sys_init(void) { #if defined(_AVR_) CLKPR = 0x80; CLKPR = 0x00; #endif } void draw(void) { u8g_SetFont(&u8g, u8g_font_5x7); u8g_DrawStr(&u8g, 0, 10, "ADC A"); u8g_DrawStr(&u8g, 0, 20, u8g_u16toa(akkuadc(), 3));//Variabel ausgeben und Zeichenlänge angeben u8g_DrawStr(&u8g, 60, 10, "ADC E"); u8g_DrawStr(&u8g, 65, 20, u8g_u16toa(adc(1), 3));//Variabel ausgeben und Zeichenlänge angeben$ u8g_SetFont(&u8g, u8g_font_4x6); u8g_DrawStr(&u8g, 5, 28, "NORD"); u8g_SetFont(&u8g, u8g_font_5x7); u8g_DrawStr(&u8g, 60, 45, u8g_u16toa(OCR1A, 4));//Variabel ausgeben und Zeichenlänge angeben u8g_DrawStr(&u8g, 15, 45, u8g_u16toa(OCR1B, 4));//Variabel ausgeben und Zeichenlänge angeben // u8g_DrawStr(&u8g, 60, 45, u8g_u16toa(elevgrad, 3)); //u8g_DrawStr(&u8g, 65, 30, "°"); // u8g_DrawStr(&u8g, 0, 45, u8g_u16toa(azimgrad, 3)); //u8g_DrawStr(&u8g, 38, 30, "°"); /* switch(elevausgabe) { case 1: u8g_DrawStr(&u8g, 70, 35, "|"); u8g_DrawStr(&u8g, 70, 30, "|"); break; case 2: u8g_DrawStr(&u8g, 70, 29, "/"); u8g_DrawStr(&u8g, 67, 32, "/"); u8g_DrawStr(&u8g, 64, 35, "/"); break; case 3: u8g_DrawStr(&u8g, 73, 29, "."); u8g_DrawStr(&u8g, 71, 30, "."); u8g_DrawStr(&u8g, 69, 31, "."); u8g_DrawStr(&u8g, 67, 32, "."); u8g_DrawStr(&u8g, 65, 33, "."); u8g_DrawStr(&u8g, 63, 34, "."); u8g_DrawStr(&u8g, 61, 35, "."); u8g_DrawStr(&u8g, 59, 36, "."); break; } switch(azimausgabe) { case 1: u8g_DrawStr(&u8g, 15, 35, "|"); u8g_DrawStr(&u8g, 15, 30, "|"); u8g_DrawStr(&u8g, 0, 35, "-->"); break; case 2: u8g_DrawStr(&u8g, 0, 35, "____"); u8g_DrawStr(&u8g, 1, 35, "____"); break; case 3: u8g_DrawStr(&u8g, 0, 35, "|"); u8g_DrawStr(&u8g, 0, 30, "|"); u8g_DrawStr(&u8g, 5, 35, "<--"); break; }*/ } ISR(WDT_vect) { watchdog_aus(); } int main(void) { DDRD &= ~((1<<PD2)|(1<<PD3)|(1<<PD4));//Taster zu eingang machen PORTD |= ((1<<PD2)|(1<<PD3)|(1<<PD4));//Pullup DDRD |= ((1<<PD6) | (1<<PD7)); DDRB|=((1<<PB2)|(1<<PB1)|(1<<PB0) | (1<<PB3) | (1<<PB4) | (1<<PB5));//PB1/2 PORTB|=((1<<PB2)|(1<<PB1)); DDRC|=(1<<PC5); PORTC|=(1<<PC5); /******************PWM*******************/ ICR1=0x9C40; // -> 20ms Periodendauer (Topwert, ab da wieder auf 0) vorher 7fff TCCR1A |= ((1<<COM1A1) | (1<<COM1B1)); //Bei Wert ICR1 auf 1 und bei wert OCR1a/-B auf 0 -> PINS im DDR definieren!! TCCR1A |= (1<<WGM11); //---------------------------- TCCR1B |=((1<<WGM12) | (1<<WGM13)); //--------PWM als fast-Mode PWM konfg TCCR1B |= (1<<CS11); //Taktvorteiler 8 TCNT0=0; /****************************************/ ////////////////////ADC//////////////////// ADMUX|= (1<<MUX1); ADMUX|=(1<<REFS0);//interne referenz 2.56V ADMUX|=(1<<ADLAR);//ergebnis in ADCH ADCSRA|=(1<<ADEN); ADCSRA|=(1<<ADPS1); ADCSRA|=(1<<ADPS0); ////////////////DISPLAY/////////////// u8g_setup();//Display initialisieren sys_init();//Display setup /********************initialisierung*********************/ OCR1A=1600;//Servo_X Mitte(linker stecker) OCR1B=1500;//Servo_Y Mitte (rechter stecker) watchdog_init(); while (1) { if(taster(1))//(((adc(1)<130)||(adc(1)>124))&&((adc(2)<130)||(adc(2)>124 )))||maincounter==60) { watchdog_ein(); maincounter=0; } else{ maincounter++; } ////////////LADE-STEUERUNG////////////// if(akkuadc()<50)//wenn akku <3V ladung(PC5) aus { PORTC&=~(1<<PC5); ladeflag=1; } else if(ladeflag==0)PORTC|=(1<<PC5); if(akkuadc()>75) ladeflag=0; ///////////////SONNENSENSOR AUSWERTEN////////////// if(adc(2)<124)//azimut { stateazim=left; } else if(adc(2)>130) { stateazim=right; } else { stateazim=100;//default } if(adc(1)<124)//elevation { stateelev=up; } else if(adc(1)>130) { stateelev=down; } else { stateelev=100;//default } //////////MANUELLE STEUERUNG/////////////// /*if(taster(1)||taster(2)||taster(3)) { if((taster(2)&&taster(3))||(taster(2)&&taster(1))) { if(taster(2)&&taster(1)) { stateelev=up; } else if(taster(2)&&taster(3)) { stateelev=down; } } else { stateelev=100; } if((taster(3)||taster(1))&&(!taster(2))) { if(taster(1)) { stateazim=left; } else if(taster(3)) { stateazim=right; } } else { stateazim=100; } }*/ ///////////////////////SOLARPANEL DREHEN/////////////// switch(stateazim) { case left: if(OCR1A>760) LINKS;//-- break; case right: if(OCR1A<2250)RECHTS;//++ break; default: break; } ////////////SOLARPANEL HEBEN////////////////// switch(stateelev) { case up: if(OCR1B>760)HOCH;//-- break; case down: if(OCR1B<2260)RUNTER;//++ break; default: break; } /////////////////////DISPLAY AUSGABE/////////////// u8g_FirstPage(&u8g);//auf Display schreiben do { draw(); } while (u8g_NextPage(&u8g)); }//end of while }//end of main void watchdog_ein (void) { set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); power_adc_disable(); sleep_cpu(); sei(); } void watchdog_aus (void) { sleep_disable(); power_adc_enable(); power_all_disable(); cli(); } void watchdog_init(void) { cli(); //Interrups sperren wdt_reset(); MCUSR=0x00; WDTCSR=0x00; WDTCSR |= ((1<<WDCE) |(1<<WDE)); //Prescalereinstellungen muessen als HEX wert egschrieben werden eine "veroderte" schreibweise duaert laenger //als vier Takte und damit wird die prescalereinstellung nicht uebernommen. //siehe Datenblatt wdt_enable(WDTO_8S);//WDTCSR = 0x61; //8 sekunden sei(); //Interrupt freigeben } void PWM_init(void) { ICR1=0x9C40; // -> 20ms Periodendauer (Topwert, ab da wieder auf 0) vorher 7fff TCCR1A |= ((1<<COM1A1) | (1<<COM1B1)); //Bei Wert ICR1 auf 1 und bei wert OCR1a/-B auf 0 -> PINS im DDR definieren!! TCCR1A |= (1<<WGM11); //---------------------------- TCCR1B |=((1<<WGM12) | (1<<WGM13)); //--------PWM als fast-Mode PWM konfg TCCR1B |= (1<<CS11); //Taktvorteiler 8 TCNT0=0; } uint8_t taster(uint8_t Nr) { switch(Nr) { case 1://taster1 if(!(PIND & (1<<PD2)))//an { return 1; } else return 0; break;//herausspringen aus Schlaufe default: return 0;//Wert, der bei keiner übereinstimmung zurückgegeben wird case 2://taster2 if(!(PIND & (1<<PD3)))//an { return 1; } else return 0; break; case 3://taster3 if(!(PIND & (1<<PD4)))//an { return 1; } else return 0; break; }//end of switch }//ende void taster uint8_t adc(uint8_t Nr) { ADMUX&=~((1<<MUX0)|(1<<MUX1)|(1<<MUX2)|(1<<MUX3));//adc kanal zurücksetzen switch(Nr) { case 1: { ADMUX|= (1<<MUX2); } break;//herausspringen aus Schlaufe case 2: { ADMUX|= ((1<<MUX0)|(1<<MUX1)); } break; }//end of switch ADCSRA|=(1<<ADSC);//startet messung while((ADCSRA & (1<<ADSC))); return ADCH; } uint8_t akkuadc(void) { ADMUX&=~((1<<MUX0)|(1<<MUX1)|(1<<MUX2)|(1<<MUX3));//adc kanal zurücksetzen ADMUX|=(1<<MUX1); ADCSRA|=(1<<ADSC);//startet messung while((ADCSRA & (1<<ADSC))); return ADCH; }
Antwort schreiben Wichtige Regeln - erst lesen, dann posten! Groß- und Kleinschreibung verwenden Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang Formatierung (mehr Informationen...)
1 | C-Code |
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.