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.