theodouma
de theorie is het idealisme van de paktijk
Ik ben de gehele avond al op zoek naar een klein stukje code voor het gebruiken van vier PWM signalen op een Atmgea88 in C. In mijn huidige code heb ik het volgende staan:
//----------------------------------------------------------------
// PWM 1+2
//----------------------------------------------------------------
/////////// initialisatie voor pwmsignaal 1 en 2
void InitPWM1(void)
{
// Fast PWM, non inverting, WGM mode 14, no pre-scaler
TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);
TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);
// Pulse repeat time 5.1 mSec ( = 198 Hz)
ICR1 = 5100;
// Timer Overflow interrupt enable
TIMSK1 = (1<<TOIE1);
}
//////// waardes voor pwm kanaal 1 en 2 instellen
ISR(TIMER1_OVF_vect)
{
OCR1B = 20 * pwmwit; // waarde voor de pwm van 0 tot 255 (ocr1 is max 5100)
OCR1A = 20 * pwmgroen;
}
Deze code maakt gebruik van timer 1 (OCR1A en OCR1B). In de verdere code hoef ik alleen de waarde voor pwmwit en pwmgroen te veranderen (0-255) om de pwm uitgangen te sturen.
Ik zoek een stukje code (het zal niet veel zijn lijkt mij) om ook gebruik te kunnen maken van (bijvoorbeeld) OCR0A en OCR0B van Timer 0 op dezelfde manier als bij timer 1.
Heeft iemand een suggestie waar ik een stukje voorbeeldcode kan vinden om totaal vier pwm kanalen te kunnen gebruiken met timer 0 en 1 op de pinnen OCR1A, OCR1, OCR2A en OCR2B? Ik ben momenteel de gehele avond aan het zoeken en uitproberen maar ben helaas niet echt opgeschoten..
Pros heeft een geweldig lijstje van alle timers hier neergezet:
http://www.circuitsonline.net/forum/view/message/1070172#1070172
theodouma
de theorie is het idealisme van de paktijk
Als ik de init van pros gebruik, aangevuld met een functie als de timer afgelope is dan heb ik de volgende code:
//----------------------------------------------------------------
// PWM 3+4
//----------------------------------------------------------------
/////////// initialisatie voor pwmsignaal 3 en 4
void InitPWM2(void)
{ // Initialiseer Timer0 voor fast PWM
TCNT0 = 0;
TCCR0A = _BV(WGM00) | _BV(WGM01) | _BV(COM0A1) | _BV(COM0B1);
TCCR0B = _BV(CS02); // Prescaler = 256
OCR0A = 32; // PWM = 1/8
OCR0B = 32;
DDRD |= _BV(PD5) | _BV(PD6); // PWM-uitgangen vrijgeven
}
ISR(TIMER0_OVF_vect)
{
OCR0B = 128; // waarde voor de pwm van 0 tot 255
OCR0A = 128;
}Deze code werkt echter niet. In de main roep ik eenmalig InitPWM2 aan, echter krijg ik geen pwm signaal op pin D5 en D6. Haal ik de
ISR(TIMER0_OVF_vect) functie weg dan krijg ik nog steeds geen pwm signaal op de D5 en D6
trouwens ook nog relevante informatie: Ik gebruik de interne oscillator van de µC
Je gebruikt de timer als PWM. Nu wil je code uitvoeren wanneer de timer "klaar" is.
void Init_Ports(void)
{
TCCR0A = _BV(WGM00) | _BV(WGM01) | _BV(COM0A1) | _BV(COM0B1);
TCCR0B = _BV(CS02);
DDRD |= _BV(PD5) | _BV(PD6);
}
int main(void){
Init_Ports();
OCR1B = 128; // waarde voor de pwm van 0 tot 255 (ocr1 is max 5100)
OCR1A = 128;
}
theodouma
de theorie is het idealisme van de paktijk
Hmmz, Het werkt nu wel, echter is de pwm frequentie 15.4 Hz... Kan ik deze boven de 100-150 Hz krijgen zonder een kristal te hoeven gebruiken?
Op 19 februari 2010 23:14:12 schreef theodouma:
Hmmz, Het werkt nu wel, echter is de pwm frequentie 15.4 Hz... Kan ik deze boven de 100-150 Hz krijgen zonder een kristal te hoeven gebruiken?
De prescaler staat nu clk/256, als je deze gelijk aan de clock zet zou dat moeten lukken. Zie ook pagina 104 van de datasheet. Maar pin mij er niet op vast dat dit klopt...
Dit moet dan werken:
TCCR0B = _BV(CS00);
plantrekker
True story bro!
Euhm, dan ga je er van uit dat ICR1 op 0xFFFF staat en FCPU op 8Mhz, uit de geposte code is duidelijk dat ICR1 op 5100 staat en FCPU op 1Mhz ...
Fast PWM op Timer0 (8bits) is een vaste top van 255 en dus een max PWM (zonder prescaler bij 1Mhz) van ~ 3,9khz. De 88 kan zonder kristal op 8 mhz draaien zodat je bijna 32khz kunt halen.
plantrekker
True story bro!
Had idd beter (en alles) moeten lezen maar dat zou de TS ook beter doen.. de datasheet. Het staat er allemaal zo mooi in 
theodouma
de theorie is het idealisme van de paktijk
Ik heb het nu werkend gekregen op een vrij simpele manier! De initialisatie van pwmkanaal drie en vier ziet er als volgt uit
//----------------------------------------------------------------
// PWM 3+4
//----------------------------------------------------------------
/////////// initialisatie voor pwmsignaal 3 en 4
*/
void InitPWM2(void)
{
TCCR0A = _BV(WGM00) | _BV(WGM01) | _BV(COM0A1) | _BV(COM0B1);
TCCR0B = _BV(CS01);
DDRD |= _BV(PD5) | _BV(PD6);
OCR0B = 192;
OCR0A = 192;
Met TCCR0B = _BV(CS01); heb ik een pwm frequentie van 494 Hz. Met de voorgestelde TCCR0B = _BV(CS00); was dit een facor tien hoger, en dan is de frequentie wel erg hoog voor een pwm signaal voor verlichting.
ISR(TIMER1_OVF_vect)
{
OCR1B = 20 * pwmwit; // waarde voor de pwm van 0 tot 255 (ocr1 is max 5100)
OCR1A = 20 * pwmgroen;
OCR0B = pwmwarmwit; // deze twee zijn voor het instellen van de waarde svan pwm3 en 4!!!
OCR0A = pwmbuiten;
}
Voor het instellen van de vier pwmsignalen gebruik ik alleen de interrupt van timer1, dit omdat alle pwmsignalen continu moeten worden bijgeregeld en ik niet in de rest van de code ook maar ieta met het pwm wil doen (OCR0A wil ik niet buiten de PWM functies zien of gebruiken ondanks dat deze minimaal 60 maal per seconde moet worden bijgewerkt, code moet immers ook een beetje netjes en overzichtelijk blijven)
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Je doet er idd. verstandig aan, de PWM-frequentie niet hoger te nemen dan nodig. Hogere frequenties produceren nu eenmaal hogere schakelverliezen.
Toch had ik deze
OCR0B = pwmwarmwit;
OCR0A = pwmbuiten;
graag zien veranderen in
OCR0B = warmbuiten;
OCR0A = warmbuiten;
Kan je daar voor zorgen? Please?! 
theodouma
de theorie is het idealisme van de paktijk
Ik laat ze toch zo staan 
In de rest van de code is de variabele 'wit' gebruikt als o.a. referentievariabele welke in het eeprom wordt opgeslagen en uitgelezen (opgeslagen gebeurt zeer zelden en is voorzien van een delay_ms(250) als backup om per ongeluk veelvuldig schrijven naar het geheugen tegen te gaan)
Aan de hand van 'wit' en een paar adc waardes wordt pwmwit bepaald.
Ik ga toch de handleiding/datasheet eens doorspitten. PWm kanaal 1 en twee hebben een schakelfrequentie van ongeveer 200 Hz. Pwm 3 en 4 zitten rond de 490 Hz. het zal leuk zijn als deze snelheid een factor twee of drie omlaag kan richting de 150-200 Hz.
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Ik ga toch de handleiding/datasheet eens doorspitten.
Dat moet je zeker doen. Het is geen onderhoudende lectuur, en naarmate er meer instellingen mogelijk zijn wordt het instellen moeilijker. Daar valt weinig aan te veranderen, vrees ik...
theodouma
de theorie is het idealisme van de paktijk
Ik heb mij verdiept in de datasheet van de chip, en dan met name de hoofdstukken over de timer/counter0 en 2.
Bij TC1 is met een werkfrequentie van 1 Mhz een pwmsignaal van 4.000, 500, 62, 15 en 4 Hz mogelijk. Bij TC2 blijkt het ook mogelijk om een frequentie van 124 of 31 Hz te selecteren.
Op TC1 moet ik dus een frequentie van 500 Hz nemen voor een goed pwm signaal voor verlichting (62 Hz zie ik flikkeren). Op TC2 is een frequentie van 124 Hz mogelijk, en deze is een stuk beter als pwm voor verlichting 
theodouma
de theorie is het idealisme van de paktijk
Omdat het op 1 Mhz ook werkt
(met name de 9.6 Kb/s usart) En ik ben 'bang' dat als ik op 8 Mhz ga werken dat ik een aantal timings opnieuw moet instellen voor de pwm en dat de usart eventueel niet meer werkt.
Voor mij heeft het momenteel geen enkel voordeel om op 8 Mhz te werken boven een klok van 1 Mhz.
Ahum ...
Table 19-9. Examples of UBRRn Settings for Commonly Used Oscillator Frequencies
Baud fosc = 1.0000 MHz
Rate U2Xn = 0 U2Xn = 1
(bps) UBRRn Error UBRRn Error
...
9600 6 -7.0% 12 0.2%
...
En twee pagina's verder:
Table 19-11. Examples of UBRRn Settings for Commonly Used Oscillator
Baud fosc = 8.0000 MHz
Rate U2Xn = 0 U2Xn = 1
(bps) UBRRn Error UBRRn Error
...
9600 51 0.2% 103 0.2%
...
De kans op fouten op je 9k6 usart is bij 8Mhz dus beduidend lager dan bij 1Mhz. De timings zal je inderdaad opnieuw uit moeten rekenen (met een factor 8 vermenigvuldigen). Als je een hogere PWM frequentie wilt is dat toch ideaal?
Ik heb juist het idee dat je heel veel voordeel hebt bij de 8Mhz klok?
theodouma
de theorie is het idealisme van de paktijk
Met U2Xn == 1 is de foutmarge bij 1 Mhz en bij 8 Mhz beide 0.2%, dus daarbij is de foutmarge niet een aanleiding om op 8 Mhz te gaan draaien.
Momenteel heb ik een PWM frequentie van 120 Hz voor kanaal 1 en 2 en 180 Hz voor 3 en 4. Die 180 Hz kan ik gemakkelijk instellen omdat deze van Timer1 afkomstig is, en die 120 Hz is van timer2. Ik kan op 8 Mhz gaan werken met een andere prescaler voor Timer2, echter kan ik dan nog steeds een PWM frequentie kiezen van 30, 120 of 240 Hz, iets dat op 1 Mhz ook mogelijk is.
Aangezien de pwm bedoeld is voor verlichting en er aan de pwmkanalen FETjes komen welke ongeveer 2 ampère moeten schakelen heb ik de frequentie zo laag mogelijk om in en uitschakelverliezen zo laag mogelijk te houden. Schakeltechnisch wil ik de frequentie dus zo laag mogelijk houden.
Dus als ik de µC op 8 Mhz zal draaien blijft mijn PWMfrequentie 120 Hz en 180 Hz en blijft de foutmarge voor de USART 0.2%. Er zit voor mij dus geen enkel voordeel in 8 Mhz draaien..
Of zie ik nu echt iets over het hoofd?
Je ziet nog 1 ding over het hoofd; met U2Xn == 1 draai je de USART op double speed (asynchroon) en dus effectief niet op 9k6 maar 19k2. Dat hoeft natuurlijk geen probleem te zijn, je moet er alleen even rekening mee houden.
Hallo ik heb een vraag. Ik gebruik precies dezelfde microcontroller en wil via een zelfgemaakte print met dubbelpolige relais een motor kunnen sturen. maar ik kom er niet uit met de code. Ook niet hoe ik de motor uit moet zetten. Ik heb niet zoveel ervaring en wil graag een beetje hulp als het kan??
