PWM mit Sleepmode

OP #4553426
Lesenswert?
• ▲
▼
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

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.