Sida 1 av 1
Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 10:27:47
av mattswe
Hej!
Nu behöver jag lite hjälp med min C-kod. Jag programmerar en ATmega328P (AVR). Tanken är att med timer0 generera en PWM-signal på pin D5. uC clockfrekvens är 1MHz och jag sätter PWM-signalens frekvens till 488Hz (prescaler = 8 ).
Kod: Markera allt
TCCR0A = ((1<<WGM01)|(1<<WGM00)); // Fast PWM mode
TCCR0A |= (1<<COM0B1); // PIND5 sätts som ut-pin
TCCR0B = (1<<CS01); // Prescaler=8 => PWM-freq = 488Hz. (Fclk = 1MHz)
Med följande anrop ser utsignalen hur fin ut som helst på osciloskopet:
Men med följande kod blir signalen minst sagt instabil:
Kod: Markera allt
OCR0B = calcPower(LANE_1,128);
uint8_t calcPower(eLane lane,uint16_t value)
{
double res=0;
uint32_t ret = 0;
if(lane == LANE_1)
{
res = ((double)(1023*value)/(double)maxPower1) + ((double)(maxTrim1*value)/(double)maxPower1) - ((double)(minTrim1*value)/(double)maxPower1) + (double)minTrim1;
ret = res;
}
if(ret>1023)
ret = 1023;
ret = (double)ret*(double)256/(double)1024; // PWM-signalens duty cycle måste ges ett värde på 0-255 (8 bitar).
return (uint8_t)ret;
}
Varken frekvens eller duty cycle är stabil. Kan även säga att anropet ligger i en evighetsloop i main(). (Det hårdkodade värdet 128 ska så småningom ersättas av ett värde från ADCn.)
Vad är det i min funktion som kvaddar PWM-utsignalen?
Tacksam för hjälp.
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 11:19:51
av Krille Krokodil
Men om det ligger i main-loopen ligger du väl och skriver till OCR0B i ett par kHz samtidigt som PWM:en snurrar?
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 11:27:23
av sodjan
Det brukar nog vara så att PWM modulen gör en "reset" när man ändrar
värderna i registren (eller skriver till dom, den vet ju inte att det
är samma värde gång på gång). Jag har en liten aning om att man
kan ställa hur modulen ska reagera vid ändringar, det kan vara det
som kallas "glitch-free", d.v.s att ändringar väntar till nästa flank
innan de "tar" för att undvika halva pulser och liknande...
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 11:43:55
av mattswe
Men om det ligger i main-loopen ligger du väl och skriver till OCR0B i ett par kHz samtidigt som PWM:en snurrar?
Ja, jag antar det. Kan tyckas onödigt förstås, fast jag behöver en regelbunden uppdatering med många gånger per sekund.
Det brukar nog vara så att PWM modulen gör en "reset" när man ändrar
värderna i registren (eller skriver till dom, den vet ju inte att det
är samma värde gång på gång). Jag har en liten aning om att man
kan ställa hur modulen ska reagera vid ändringar, det kan vara det
som kallas "glitch-free", d.v.s att ändringar väntar till nästa flank
innan de "tar" för att undvika halva pulser och liknande...
Jag förstår vad du menar, fast om detta vore problemet så borde det ju inte fungera när jag skippar min funktion och hårdkodar värdet heller. Eller?
Jag ska testa att ställa ner uppdateringsfrekvensen, återkommer...
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 11:52:56
av Krille Krokodil
Lägg en if-sats runt skrivningen till OCR0B då som jämför med föregående varv och bara skriver när där skett ändring.
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 11:55:28
av sodjan
Du menar att du fortfarande har loopen men hårdkodar värdet?
Ja, i så fall så är det ju något med funktionen som sådan...
Men, det är väl bara vanlig felsökning kurs 1A som gäller?

Om man har en variant som fungerar och en som inte funegrar
så är det bara att testa med varanter mellan dessa två tills man
hittar vad den kritiska skillnaden är...
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 12:02:32
av mattswe
Du menar att du fortfarande har loopen men hårdkodar värdet?
Korrekt.
Men, det är väl bara vanlig felsökning kurs 1A som gäller?

Låter i och för sig rimligt när du uttrycker det så..
Jag testade med att bara uppdatera duty cycle 2ggr/s. Då ligger frekvensen på 500Hz vilket är korrekt, men duty cycle ligger på 6%, borde vara 50% (128).
Ett problem jag har när jag felsöker är att då jag debuggar så kan jag inte hålla musen över double-variablerna och se deras värde, rad för rad. Misstänker att det är kompilatorn som optimerar koden på något sätt. Kan man slå av denna optimering i Atmel Studio så att det går att stega sig fram rad för rad, även på en rad som double aa = (uint16_t)heltal; ?
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 12:15:01
av Krille Krokodil
Det hittar du i inställningarna för kompileringen, -O0 är det för stänga av optimeringar.
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 12:27:56
av mattswe
Det hittar du i inställningarna för kompileringen, -O0 är det för stänga av optimeringar.
Tackar!
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 12:31:30
av Swech
Det var något in i h*-*** med beräkningar
Kod: Markera allt
res = ((double)(1023*value)/(double)maxPower1) + ((double)(maxTrim1*value)/(double)maxPower1) - ((double)(minTrim1*value)/(double)maxPower1) + (double)minTrim1;
För din egen skull så bena ut denna för den går att förenkla mycket
Swech
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 16:33:22
av mattswe
[quote] uint16_t value = 512
double aa = (double)1023*value;
double bb = (double)(1023*value);
Det visade sig till sista vara en konverteringsproblematik som jag inte riktigt förstår mig på. I ovanstående kod blir aa = 523776, men bb blir 65024. Det var aa jag ville åstadkomma, men jag hade skrivit enligt bb. Någon som kan förklara?
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 17:05:08
av snigelen
Den första betyder "Konvertera 1023 till double och multiplicera sedan med value".
Den andra betyder "multiplicera heltalet (en int) 1023 med value, konvertera resultatet till double". Eftersom int i avr-gcc är 16 bitar får inte 1023*512 plats, det blir overflow. Men du kan säga att 1023 skall vara t.ex unisgned long (32 bitar). Typ
så utförs multiplikationen med 32bitars aritmetik och resultatet får plats.
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 17:09:48
av mattswe
Tack för förklaringen. Jag tog för givet att int var 32bitar. Dumt antagande.
Re: Hjälp med C-kod, PWM i AVR
Postat: 21 oktober 2013, 17:18:44
av snigelen
double är förresten 32 bitar i avr-gcc (samma som float) kan ju nämnas i sammanhanget. Så där följer den inte standarden (en double måst vara minst typ 48 bitar har jag för mig).
Re: Hjälp med C-kod, PWM i AVR
Postat: 22 oktober 2013, 10:34:23
av mattswe
Nu verkar det fungera. Fixade konverteringsproblematiken och minskade uppdateringsfrekvensen av pwm-utsignalen (Krille Krokodil o Sodjan, tack för det tipset).
Tack för hjälpen!