Hjälp med C-kod, PWM i AVR

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Hjälp med C-kod, PWM i AVR

Inlägg 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:

Kod: Markera allt

OCR0B = 128; // Anger duty cycle
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.
Användarvisningsbild
Krille Krokodil
Inlägg: 4062
Blev medlem: 9 december 2005, 22:33:11
Ort: Helsingborg

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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...
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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...
Användarvisningsbild
Krille Krokodil
Inlägg: 4062
Blev medlem: 9 december 2005, 22:33:11
Ort: Helsingborg

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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...
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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; ?
Användarvisningsbild
Krille Krokodil
Inlägg: 4062
Blev medlem: 9 december 2005, 22:33:11
Ort: Helsingborg

Re: Hjälp med C-kod, PWM i AVR

Inlägg av Krille Krokodil »

Det hittar du i inställningarna för kompileringen, -O0 är det för stänga av optimeringar.
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: Hjälp med C-kod, PWM i AVR

Inlägg av mattswe »

Det hittar du i inställningarna för kompileringen, -O0 är det för stänga av optimeringar.
Tackar!
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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?
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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

Kod: Markera allt

double aa = 1023UL*value;
så utförs multiplikationen med 32bitars aritmetik och resultatet får plats.
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: Hjälp med C-kod, PWM i AVR

Inlägg av mattswe »

Tack för förklaringen. Jag tog för givet att int var 32bitar. Dumt antagande.
snigelen
Inlägg: 815
Blev medlem: 8 maj 2009, 11:02:14
Ort: Lund

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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).
mattswe
Inlägg: 159
Blev medlem: 20 augusti 2012, 13:27:51

Re: Hjälp med C-kod, PWM i AVR

Inlägg 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!
Skriv svar