atMega644 PWM problem...

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
erikbrannlund
Inlägg: 53
Blev medlem: 12 februari 2007, 20:10:39
Ort: Frostkåge

atMega644 PWM problem...

Inlägg av erikbrannlund »

Hej!

Jag har en "app" som ska bli väckarklocka men även styra sänglampan plus en del annat.
Nu försöker jag PWM:a en lysdiod men den fladdrar trots att jag i min enfald tycker att den inte borde.

Kod: Markera allt

void initTimer(void)
{
  OCR1A = 250;      // timer compare value 
  TCCR1B = _BV(WGM12) | 2; // Presc -> Clock/ 8 -> 250000 MHz -> int 2000 Hz
  TIMSK1 = _BV(OCIE1A); 
  sei();         /* enable interrupts */ 
	timerCounter = 0;
}


int pwm = 0;
unsigned int pwmcnt;
int pwmdir = 1;

int PWMMAX = 10;


int secs = 0;
ISR(TIMER1_COMPA_vect) 
{ 
	timerCounter++;				// inc timeout tick
	if (++tcount == 2000)		// one second tick 
	{
		tcount = 0;
		sec_flag = 1;
		UTCtime ++;
	}

  if (++pwmcnt == PWMMAX)
    pwmcnt = 0;

  cli();
  if ((pwmcnt % PWMMAX == 0) && (pwm != 0))
    PORTC = 0xF0;
  if (pwmcnt % PWMMAX == pwm)
    PORTC = 00;
    
   if (sec_flag)
        if (secs-- == 0)
        {
          pwm += pwmdir;
          secs = 100;
         }

      if (pwm == PWMMAX-1)
        pwmdir = -1;

      if (pwm == 0)
        pwmdir = 1;

  sei();
}


Jag tycker att Jag med den här koden borde få en blinkhastighet på 200 Hz men är jag kör på de lägre intensiteterna så flimrar lysdioden, med PWMMAX = 4 blir ljuset stabilt men skulle vilja ha lite fler steg.

Har jag ett hjärnsläpp modell större eller vad är fel.

/Erik
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Kommentera koden tack.

Indenteringarna är helt fel.

Interrupts stängs av automatiskt när en ISR-rutin anropas och aktiveras igen när den tar slut. Alltså är dina cli() och sei() överflödiga.
erikbrannlund
Inlägg: 53
Blev medlem: 12 februari 2007, 20:10:39
Ort: Frostkåge

Inlägg av erikbrannlund »

Kommentarer var det...

Kod: Markera allt

//Den här funktionen startar timern...    
void initTimer(void)
{
  OCR1A = 250;      // timer compare value Interrupt var 250 "tick"
  TCCR1B = _BV(WGM12) | 2; // Presc -> Clock/ 8 -> 500000/250 MHz -> int 2000 Hz
  TIMSK1 = _BV(OCIE1A); 
  sei();         /* enable interrupts */ 
  timerCounter = 0;
}


//globala  variabler för PWM hanteringen
int pwm = 0;  // Vilken "pwm-nivå som används
unsigned int pwmcnt; ////pwmräknare, borde kanske byta till char jag kan i allafall inte köra med så stor PWM
int pwmdir = 1;  // Riktning att räkna upp eller ner pwm värdet

int PWMMAX = 10; //Antal PWM steg, borde ge 200Hz


int secs = 0; //Ingen direkt koppling till PWM delen
ISR(TIMER1_COMPA_vect) 
{ 
  timerCounter++;				// inc timeout tick  minns inte exakt vad den här var
  if (++tcount == 2000)		// one second tick kollar om  en sekund upplupit
  {
    tcount = 0;
    sec_flag = 1;
    UTCtime ++;
  }

  // Här kommer PWM delen
  if (++pwmcnt == PWMMAX)
    pwmcnt = 0;

  if ((pwmcnt % PWMMAX == 0) && (pwm != 0))
    PORTC = 0xF0;
  if (pwmcnt % PWMMAX == pwm)
    PORTC = 00;
    
   // Koden som följer räknar upp och ned  PWM värdet
  if (sec_flag)
    if (secs-- == 0)
    {
       pwm += pwmdir;
       secs = 100;
     }

  if (pwm == PWMMAX-1)
     pwmdir = -1;

  if (pwm == 0)
    pwmdir = 1;

}


Dessutom har jag försökt titta på utkurvan i ett "oscilloskåp" och kunde inte se annat än en kurva på ~200Hz. Tyvärr är skåpet inte riktigt hundra verkar vara ngt glapp eller annat mystiskt. Så hur kan en PWM signal på 200Hz ge ett synligt flimmer?

/Erik[/code]
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Okej. Jag tycker din kod verkar stämma. En lysdiod på 200 Hz borde inte flimra. :?

Men jag undrar varför du kör med modulus i din kod. Den första if-satsen ser ju till att pwmcnt bara går mellan 0 och PWMMAX-1. Du borde därför kunna jämföra "pwmcnt" istället för "pwmcnt % PWMMAX".

Det borde vara okej att använda "elseif" också...

Kod: Markera allt

// Här kommer PWM delen
  if (++pwmcnt == PWMMAX)
    pwmcnt = 0;

  if ((pwmcnt == 0) && (pwm != 0))
    PORTC = 0xF0;
  else if (pwmcnt == pwm)
    PORTC = 00;
edit: Går det till och med att skriva om sista if-else-if:en till:

Kod: Markera allt

  if (pwmcnt == pwm)
    PORTC = 0x00;
  else if (pwmcnt == 0)
    PORTC = 0xF0;
?
erikbrannlund
Inlägg: 53
Blev medlem: 12 februari 2007, 20:10:39
Ort: Frostkåge

Inlägg av erikbrannlund »

Modulus beror på att jag inte nollade pwmcnt tidigare. Eftersom det flimrar för mig så har jag ändrat koden åtskilliga gånger.
Men flimret inte bara att koden verkar stämma "skåpet" säger 200 Hz dessutom men likafullt flimrar det. Ju kortare puls desto mer flimmer.
Kopplingen är som följer.

Ut på porten till basen på en BC337:a.
Emittern till jord.
Spänningen från STK-500 till Powerled.
Powerled till resistor.
Resistor till kollektor.

/Erik
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Har du inget motstånd mellan porten och basen?
erikbrannlund
Inlägg: 53
Blev medlem: 12 februari 2007, 20:10:39
Ort: Frostkåge

Inlägg av erikbrannlund »

Nej kolla det har jag inte! Förslag på lämpligt motstånd? Men kan flimret verkligen bero på den saken.

/Erik
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Hur mycket ström låter du LED:en dra?

Har du provat om det blir flimmer med en vanlig lysdiod?

Sen blir väl förresten frekvensen 100 Hz, och inte 200 Hz, eftersom en tänd-släck-cykel är en period.

Kan du inte låta en separat timer sköta PWM:en istället? Då ställer du in pulskvoten genom att helt enkelt ändra motsvarande OCR-register. Då får du ju fler "intensitetsnivåer" också.
erikbrannlund
Inlägg: 53
Blev medlem: 12 februari 2007, 20:10:39
Ort: Frostkåge

Inlägg av erikbrannlund »

LED drar 200-300 mA enligt min "Classe-multimeter".

Lös lysdiod flimrade sist jag provade. Lysdiod på STK-plattan flimrade inte.

Ja, jo 100 Hz blir det men även det borde vara "oflimrigt".

Tyvärr är den timern upptagen!

/Erik
sodjan
EF Sponsor
Inlägg: 43249
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Ut på porten till basen på en BC337:a.

Utan motstånd = i princip kortslutning !
Vad tycker din processor om det ?
Är du säker på att processorn/koden inte startar om hela tiden ?
erikbrannlund
Inlägg: 53
Blev medlem: 12 februari 2007, 20:10:39
Ort: Frostkåge

Inlägg av erikbrannlund »

Jag har satt ett motstånd i serie mellan porten och 337:an efter första påpekandet kanske lite liten ~150 ohm.
Nej processorn snurrade snällt på kanske beronde på att den går på 3.3 V.

/Erik
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

erikbrannlund:
> Lös lysdiod flimrade sist jag provade. Lysdiod på STK-plattan flimrade inte.

Om vissa lysdioder flimrar medan andra inte gör det så är det nog inte AVR:en eller ditt program det är fel på i alla fall. Vad som kan vara fel vet jag däremot inte. :(
erikbrannlund
Inlägg: 53
Blev medlem: 12 februari 2007, 20:10:39
Ort: Frostkåge

Inlägg av erikbrannlund »

Nu har jag bytt till ett större motstånd mellan port och bas på trissan, 10k blev det. Jag undrar hur jag tänkte när jag inte hade ngt motstånd, inte alls mest troligt. Eventuellt blev flimret mindre men jag har inte haft tid att testa så mycket. Vad som däremot hände är att ADC:n inte stördes lika kraftigt av påslaget ljus, tidigare indikerade den 3-4 grader högre temperatur både inne och ute när lyset var på.
erikbrannlund
Inlägg: 53
Blev medlem: 12 februari 2007, 20:10:39
Ort: Frostkåge

Inlägg av erikbrannlund »

Bumpar denna: Jo flimret blev bättre med motståndet men det försvann inte helt. Däremot om jag slår av ADC:n och inte får några interrupt så blir ljuset helt plötsligt stabilt. Kanske beroende på mina försök att översampla för en högre upplösning enligt ngn appnote från ATMEL.

/Erik
Användarvisningsbild
cykze
EF Sponsor
Inlägg: 1539
Blev medlem: 8 april 2004, 10:40:28
Ort: Uppsala

Inlägg av cykze »

Vilken frekvens har du på ADC-klockan? Alltså vilken prescaler kör du med och vilken frekvens kör själva AVR:en med?
Skriv svar