Вы находитесь на странице: 1из 22

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

MicrocontrollersandElectronicsProjectBlog

BlogEntry

April30,2011byrwb,underMicrocontroller.

PulseWidthModulation(PWM)isatechniquewidelyusedinmodernswitchingcircuittocontroltheamount

ofpowergiventotheelectricaldevice. ThismethodsimplyswitchesONandOFFthepowersuppliedto

theelectricaldevicerapidly.Theaverageamountofenergyreceivedbytheelectricaldeviceis

correspondingtotheONandOFFperiod(dutycycle);thereforebyvaryingtheONperiodi.e.longeror

shorter,wecouldeasilycontroltheamountofenergyreceivedbytheelectricaldevice.TheLightEmitting

Diode(LED)willrespondtothispulsebydimmingorbrightenitslightwhiletheelectricalmotorwill

respondtothispulsebyturningitsrotorsloworfast.

respondtothispulsebyturningitsrotorsloworfast.

TheabovepictureshowatypicalPulseWidthModulation(PWM),thePWMdutycycleistheproportionof

thesignal“ON”timetooneperiod(T)ofthesignaltime.ThedutycyclewillbehigherwhentheONtimeis

longerthantheOFFtimeandviceversa.Dutycycleisexpressedinpercentage;thereforeyoucould

definethedutycycleofPWMsignalasfollow:

definethedutycycleofPWMsignalasfollow:

The100%PWMdutycyclemeansit’sfullyONandwecouldsaythat100%ofthepowerorenergyis

deliveredtotheelectricaldevice,while15%dutycyclemeansonly15%ofthepowerisbeingdelivered

totheelectricaldevice.Thisaverageinpowercouldbepresentedasaverageinvoltageasfollow:

ThePWMsignalnormallyhasafixedfrequency(period)withadutycyclethatcouldvaryfrom0%to

100%.NowyouunderstandthatbyjustadjustingthePWMdutycyclewecouldeasilycontroltheLED

brightnessortheelectricalmotorspinningspeed.

TodaymostofmodernmicrocontrollerhasabuildinPWMperipheralinside;thismakegeneratingPWM

signalisbecomeeasyandstraightforward,youcouldreadmoreaboutnonmicrocontrollerPWMbase

blog.OnthistutorialwearegoingtouseAtmelAVRATMega168microcontrollerwhichsupportupto6

SearchThisSite

Search
Search

CustomSearchSearchThisSite Search FuturePost ControllingtheMotorisoneof

FuturePost

ControllingtheMotorisoneof

interestingtopicsintheembedded

worldespeciallyfortherobotics

enthusiasts,onthenextpostwewill

learnthebasicofmotorelectronic

circuitaswellashowtocontrolitwith

microcontroller.

Thereforedon'tmissit,staytuneon

thisblog!

Subscribe

Posts| Comments SubscribewithBloglines AddtoTechnoratiFavorites
Posts| Comments
SubscribewithBloglines
AddtoTechnoratiFavorites
Comments SubscribewithBloglines AddtoTechnoratiFavorites AddtoWindowsLiveFavorites AddtoMyMSN RecommendedBooks
Comments SubscribewithBloglines AddtoTechnoratiFavorites AddtoWindowsLiveFavorites AddtoMyMSN RecommendedBooks
AddtoWindowsLiveFavorites AddtoMyMSN
AddtoWindowsLiveFavorites
AddtoMyMSN

RecommendedBooks

FeatureProduct

AddtoMyMSN RecommendedBooks FeatureProduct AVRJazzMega168Board Categories SelectCategory Blogroll

AVRJazzMega168Board

Categories

SelectCategory

Blogroll

Archives

SelectMonth
SelectMonth

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

PWMoutputsimultaneouslyandattheendofthistutorialwewilltakeadvantageofalltheavailablePWM

peripheraltomakeaniceRGBLEDLightandSoundShow.

peripheraltomakeaniceRGBLEDLightandSoundShow. TheAVRMicrocontrollerPWMPeripheral

TheAVRMicrocontrollerPWMPeripheral

MostofthemicrocontrollerPWMperipheraldependsontheTIMERperipheraltoprovidethePWMsignals

frequency.ThePWMperipheralwillusetheTIMERcounterregister(TCNT)asadigitalstep­up/downand

continuouslycomparetothepre­determinedutycycleregister(OCR–outputcompareregister)value.

OCR –outputcompareregister)value. When TCNT equalto OCR

WhenTCNTequaltoOCRvaluethewavegeneratorcircuitwillset(ON)orreset(OFF)thecorresponding

microcontrollerPWMI/Oports.ThefollowingpictureshowasimplifiedversionofAtmelAVRATMega168

microcontrollerPWMperipheral(pleaserefertotheAtmelATMega48/88/168/328datasheetformore

information):

information): http://www.ermicro.com/blog/?p=1971 2/22

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

EachoftheAVRATMega168microcontrollersTIMERhastwoPWMchannelsnamedchannelAandchannel

B,whereeachchannelhasitsownoutputcompareregister(OCR).Fromthediagramaboveyoucould seethatbothchannelsharethesameTIMERcounterregister(TCNT),thismeanyoucouldonlyhaveone

PWMfrequencyforeachTIMER(TIMER0,TIMER1,andTIMER2)butyoucouldhavedifferentdutycycleon

eachchannel(AandB).TheAVRATMega48/88/168/328microcontrollerprovidesthreePWMmodes

whichareFastPWMMode,PhaseCorrectPWMMode,andPhaseandFrequencyCorrectMode.Thelast

modeisonlyavailableonTIMER1(16­bittimer).Okbeforewecontinuelet’slistdownthehardwareand

softwareneededforthistutorial:

1.AVRJazzMega168orAVRJazzUltimate28Pboard(Iusedinthisproject),youcouldalsouseanyAVR

ATMega168boardorbareATMega168,whateveravailabletoyou(theelectronicscomponentslistedhere

isjustforthefinalproject)

2.OneBreadboard

3.Resistors:10K(1),15K(1),and18(1)

4.One10KTrimpot

5.NonpolarCapacitor0.1uF(3)and0.01uF(1)

6.PolarCapacitor220uF/16V(1)and10uF/16V(1)

7.One5mmRGBLED

8.NationalSemiconductorLM386IC

9.Onewhiteping­pongballfordefusingtheRGBLEDlight

10.OneSpeaker

11.ThelatestAtmelAVRStudio(inthisprojectIusedv4.18)andWinAVRGNU­CCompiler(inthisproject

IusedWinAVR20100110)

12.AVRMicrocontrollerProgrammer

13.AtmelATMega48/88/168/328andLM386datasheet.

13.AtmelATMega48/88/168/328andLM386datasheet. TheAVRFastPWMMode

TheAVRFastPWMMode

TheAVRfastPWMmodecouldgeneratethemosthighfrequencyPWMwaveformcomparedtotheother twoPWMmodes(i.e.PhaseCorrectorPhaseandFrequencyCorrectmode).ThisPWMmodesimplyuses

theTIMERcounterregister(TCNTn,wherenrepresenttheTIMER0,TIMER1,andTIMER2respectively)

incrementalvaluewhichisstartfrom0x00(BOTTOM)to0xFF(8­bitTOP)or0xFFFF(16­bitTOP).

WhentheTIMERcounterregisterreachtheoutputcompareregister(OCRnAorOCRnB)valuethenthe

wavegeneratorcircuitwillCLEAR(logicallow)theoutputcomparebitchannel(OCnAorOCnB).Whenthe

TIMERcounterregistervaluereachtheTOPvaluethenitwillSET(logicalhigh)theoutputcomparebit

channelandthewholeprocesswillrepeatagainfromBOTTOM.ThisPWMgenerationprocesscouldbe

shownonthisfollowingdiagram:

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

Asshownonthediagramabove,thebehaviorofoutputcomparebitchannel(OCnAorOCnB)output couldbesettonon­inverting(CLEARandSET)orinverting(SETandCLEAR)modebysettingthecompare

matchchannelbit(COMnA1,COMnA0,COMnB1,andCOMnB0)onTimer/CounterregisterA(TCCRnA).

TheFastPWMmodecouldbesetbysettingthewavegenerationmodebit(WGM01andWGM00)on

Timer/CounterregisterA(TCCRnA)andWGM02bitonTCCRnBregister.WhentheTIMERcounter

register(TCNTn)equaltoOutputCompareRegister(OCRnAorOCRnB)itwillgeneratetheOutput

CompareinterruptandwhentheTCNTnregisterreachTOPitwillgeneratetheTIMERoverflowinterrupt

(TOV).

( TOV ).

AsyouseeattheAtmelAVRmicrocontrollerPWMperipheraldiagramabovewhenweupdatetheOutput CompareRegister(OCRnAandOCRnB)value,thevaluewillbeupdatedontheOutputCompareRegister

BufferfirstandwhentheTIMER0CounterRegister(TCNT0)reachTOPthentheOCRnregisterwillbe

updatedwiththeOCRnbuffervalueandatthesametimetheOutputCompareBits(OCnAorOCnB)will

beset.

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

OnthisfollowingCcode,wearegoingtouseTIMER0FastPWMmodeonbothchannelAandchannelB.

//***************************************************************************

//

File Name

: avrpwm01.c

//

Version

: 1.0

//

Description : AVR TIMER0 Fast PWM Mode

//

Author

: RWB

//

Target

: AVRJazz Ultimate 28PIN Board

// Compiler

: AVR‐GCC 4.3.3; avr‐libc 1.6.7 (WinAVR 20100110)

//

IDE

: Atmel AVR Studio 4.18

// Programmer

: AVRJazz Mega168 STK500 v2.0 Bootloader

//

: AVR Visual Studio 4.18, STK500 programmer

//

Last Updated : 21 March 2011

//*************************************************************************** #include <avr/io.h> #include <util/delay.h>

int main(void)

{

unsigned char duty_cyc_a,duty_cyc_b;

// Initial PORT Used DDRD = 0b11111111; PORTD = 0x00;

// Set PORTD: Output

// Initial TIMER0 Fast PWM // Fast PWM Frequency = fclk / (N * 256), Where N is the Prescaler // f_PWM = 11059200 / (64 * 256) = 675 Hz

TCCR0A = 0b10100011; // Fast PWM 8 Bit, Clear OCA0/OCB0 on Compare Match, Set on TOP TCCR0B = 0b00000011; // Used 64 Prescaler

TCNT0 = 0; OCR0A = 0; OCR0B = 0;

// Reset TCNT0 // Initial the Output Compare register A & B

duty_cyc_a=0; // Initial Duty Cycle for Channel A

duty_cyc_b=255;

// Initial Duty Cycle for Channel B

for(;;) {

// Loop Forever

while(duty_cyc_a < 255) {

OCR0A=duty_cyc_a++;

OCR0B=duty_cyc_b‐‐;

_delay_ms(10);

}

while(duty_cyc_b < 255) {

OCR0A=duty_cyc_a‐‐;

OCR0B=duty_cyc_b++;

_delay_ms(10);

}

}

return 0;

// Standard Return Code

}

/* EOF: avrpwm01.c */

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

TheTIMER0FastPWMmodeisactivatedbysettingtheWaveGenerationModebitsWGM02=0,

WGM01=1,andWGM00=1onTIMER0Timer/CountercontrolRegisters(TCCR0AandTCCR0B)as

follow:

// Initial TIMER0 Fast PWM // Fast PWM Frequency = fclk / (N * 256), Where N is the Prescaler // f_PWM = 11059200 / (64 * 256) = 675 Hz TCCR0A = 0b10100011; // Fast PWM 8 Bit, Clear OCA0/OCB0 on Compare Match, Set on TOP TCCR0B = 0b00000011; // Used 64 Prescaler

ThereforebyassigningtheClockSetBitCS02=0,CS01=1,andCS00=1respectively,wetellthe

TIMER0touse64asaprescaler,thereforeyoucouldcalculatethePWMfrequencyifweuse11059200Hz

externalcrystalasfollow:

PWMFrequency=FreqClock/(prescalerx256)=11059200/(64x256)=675Hz

YoucouldfreelychooseorexperimentwithanyPWMfrequencythatworkbestwiththeelectricaldevices

thatyouwanttocontrolwiththeFastPWMmodesignal.

OneofdisadvantageusingtheFastPWMmodetogeneratethePWMsignalisthePWMphaseisshifted

whenwechangethePWMdutycycle.ThisbecausewhentheTIMER0CounterRegister(TCNTn)reach

TOPandstartfromBOTTOMitwillalwaysSET(orCLEAR)theOutputCompareBits(OCnAorOCnB)

despitetheOutputCompareRegister(OCRnAandOCRnB)value;thereforewhenwechangetheduty

cycleinFastPWMmodethePWMsignalphaseisalwaysshiftedasillustratedonthisfollowingdiagram:

http://www.ermicro.com/blog/?p=1971 6/22

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

ThismaketheFastPWMmodeisnotsuitablewhenwewanttouseforcontrollingthemotorspeed

precisely;thereforeonournextdiscussionwewillcorrectthisshiftedphaseeffectbyusingtheAVR

microcontrollerPhaseCorrectPWMmodeforgeneratingthePWMsignal.

NowasyouunderstandofhowtousetheFastPWMmodeonTIMER0,youcouldeasilyadaptthisprincipal

toTIMER1(16­bit)andTIMER2(8­bit).PleaserefertotheAtmelATMega48/88/168/328datasheetfor

completeinformation.

TheAVRPhaseCorrectPWMMode

DifferfromtheFastPWMMode,thePhaseCorrectPWMmodeisusingdualslopeTIMERcounter.Basically

theTIMERcounterregister(TCNTn)willincreaseitsvalue(upcounter)fromBOTTOMtoTOPandthen

decreaseitsvalue(downcounter)fromTOPtoBOTTOM.WhentheTIMERcounterregisterequaltothe

OutputCompareRegister(OCRnAandOCRnB)thenthewavegeneratorbitwillsimplytoggletheOutput

Comparechannel(OCnAandOCnB)asshownonthisfollowingdiagram:

OCnA and OCnB )asshownonthisfollowingdiagram:

AsshownonthediagramaboveyoucouldseethatthePhaseCorrectPWMmodewillhavehalfofthe

PWMsignalfrequencycomparedtothefastPWMmode.Becauseofthedualslopetechniqueusedinthe

PhaseCorrectPWMmodetogeneratethePWMsignal,thereforethephasecorrectPWMmodeismore

precisionandsuitabletobeusedasamotorcontroller,becauseaswechangethePWMsignaldutycycle

thephasebetweeneachdutycyclesremainthesameasillustratedonthisfollowingdiagram:

thephasebetweeneachdutycyclesremainthesameasillustratedonthisfollowingdiagram: http://www.ermicro.com/blog/?p=1971 7/22

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

OnthisfollowingCcode,wearegoingtouseTIMER0PhaseCorrectPWMmodeonbothchannelAand

channelB.

//***************************************************************************

//

File Name

: avrpwm02.c

//

Version

: 1.0

// Description : AVR TIMER0 Phase Correct PWM Mode

//

Author

: RWB

//

Target

: AVRJazz Ultimate 28PIN Board

// Compiler

: AVR‐GCC 4.3.3; avr‐libc 1.6.7 (WinAVR 20100110)

//

IDE

: Atmel AVR Studio 4.18

// Programmer

: AVRJazz Mega168 STK500 v2.0 Bootloader

//

: AVR Visual Studio 4.18, STK500 programmer

//

Last Updated : 21 March 2011

//***************************************************************************

#include <avr/io.h> #include <util/delay.h>

int main(void)

{

unsigned char duty_cyc_a,duty_cyc_b;

// Initial PORT Used DDRD = 0b11111111; PORTD = 0x00;

// Set PORTD: Output

// Initial TIMER0 Phase Correct PWM // Fast PWM Frequency = fclk / (N * 510), Where N is the Prescaler // f_PWM = 11059200 / (64 * 510) = 338.82 Hz

TCCR0A = 0b10100001; // Phase Correct PWM 8 Bit, Clear OCA0/OCB0 on Compare Match, Set on TOP TCCR0B = 0b00000011; // Used 64 Prescaler

TCNT0 = 0; OCR0A = 0; OCR0B = 0;

// Reset TCNT0 // Initial the Output Compare register A & B

duty_cyc_a=0;

// Initial Duty Cycle for Channel A

duty_cyc_b=255;

// Initial Duty Cycle for Channel B

for(;;) {

// Loop Forever

while(duty_cyc_a < 255) {

OCR0A=duty_cyc_a++;

OCR0B=duty_cyc_b‐‐;

_delay_ms(10);

}

while(duty_cyc_b < 255) {

OCR0A=duty_cyc_a‐‐;

OCR0B=duty_cyc_b++;

_delay_ms(10);

}

}

return 0;

// Standard Return Code

}

/* EOF: avrpwm02.c */

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

TheTIMER0PhaseCorrectPWMmodeisactivatedbysettingtheWaveGenerationModebitsWGM02=0,

WGM01=0,andWGM00=1onTIMER0Timer/CountercontrolRegisters(TCCR0AandTCCR0B)as

follow:

// Initial TIMER0 Phase Correct PWM // Fast PWM Frequency = fclk / (N * 510), Where N is the Prescaler // f_PWM = 11059200 / (64 * 510) = 338.82 Hz TCCR0A = 0b10100001; // Phase Correct PWM 8 Bit, Clear OCA0/OCB0 on Compare Match, Set on TOP TCCR0B = 0b00000011; // Used 64 Prescaler

ThereforebyassigningtheClockSetBitCS02=0,CS01=1,andCS00=1respectively,wetellthe

TIMER0touse64asaprescaler,thereforethePhaseCorrectPWMfrequencycouldbecalculatedas

follow:

PWMFrequency=FreqClock/(prescalerx510)=11059200/(64x510)=338.82Hz

AgainyoucouldeasilyadaptthisprincipaltoTIMER1(16­bit)andTIMER2(8­bit)aswell(pleasereferto

AtmelATMega48/88/168/328datasheetforcompleteinformation).

TheAVRPhaseandFrequencyCorrectPWMMode

ThePhaseandFrequencyCorrectPWMModefeatureisonlyavailableonTIMER1(16­bit).Basicallythe

PhaseandFrequencyCorrectPWMmodeusethesamedualslopetechniqueusedinPhaseCorrectPWM

modetogeneratethePWMsignal.ThesetwomodesactuallyareidenticalifweneverchangethePWM

signalfrequency,butifweneedtochangethePWMsignalfrequencyonfly,thenweneedtousetheAVR

ATMega168microcontrollerPhaseandFrequencyCorrectmodetogeneratethePWMsignal.

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

DifferfromthePhaseCorrectPWMMode,inPhaseandFrequencyCorrectPWMModetheOutputCompare

Register(OCRnAandOCRnB)isupdatedfromthebufferwhentheTimerCounterRegister(TCNTn)

reachesBOTTOMinsteadofTOPinPhaseCorrectPWMMode.Thefrequencycouldbechangebychanging

theTOPvalue,hereyoucouldunderstandwhyweneedtousethePhaseandFrequencyCorrectPWM

mode,becauseaswechangethefrequencyandatthesametimethePWMperipheralupdatetheOutput

Compareregister(OCRnAandOCRnB)thentherewillbeaglitchinthePWMfrequencysignal.

InPhaseandFrequencyCorrectPWMmodebecausetheOutputCompareRegisterisupdatedatthe

BOTTONthereforetherisingandfallinglengthofthePWMsignalisalwaysequalthisresultinfrequency

beingcorrectedwhenwechangethefrequencyonfly.

beingcorrectedwhenwechangethefrequencyonfly.

TypicallyincontrollingtheelectricaldevicewithPWMsignalweseldomchangethePWMfrequencyonfly,

thereforethecommonapplicationforthismodeistogeneratethesound.OnthisfollowingCcode

exampleIusedthePhaseandFrequencyCorrectPWMtogeneratedtone.Anotherexampleofusingthis

PWMmodecouldbereadin“AVRTwinkle­TwinkleSongUsingPWMProject”articleonthisblog.

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

//***************************************************************************

//

File Name

: avrpwm03.c

//

Version

: 1.0

// Description : AVR TIMER0 Phase and Frequency Correct PWM Mode

//

Author

: RWB

//

Target

: AVRJazz Ultimate 28PIN Board

// Compiler

: AVR‐GCC 4.3.3; avr‐libc 1.6.7 (WinAVR 20100110)

//

IDE

: Atmel AVR Studio 4.18

// Programmer

: AVRJazz Mega168 STK500 v2.0 Bootloader

//

: AVR Visual Studio 4.18, STK500 programmer

//

Last Updated : 21 March 2011

//*************************************************************************** #include <avr/io.h> #include <util/delay.h>

// Notes Frequency from http://www.phy.mtu.edu/~suits/notefreqs.html // The Original frequency value (decimal) is converted to the integer value #define C4 262 #define Cc4 277 #define D4 294 #define Dc4 311 #define E4 330 #define F4 349 #define Fc4 370 #define G4 392 #define Gc4 415 #define A4 440 #define Ac4 466 #define B4 494

#define C5 523 #define Cc5 554 #define D5 587 #define Dc5 622 #define E5 659 #define F5 698 #define Fc5 740 #define G5 783 #define Gc5 831 #define A5 880 #define Ac5 932 #define B5 988

#define C6 1047

// LED Display variables unsigned char ledstat,led_out;

// PlayNotes function void PlayNotes(unsigned int note_frequency,unsigned int duration)

{

 

unsigned int top_value,duty_cycle;

// Calculate the Top Value // TOP = Board Clock Frequency / (2 x N x Notes Frequency) // Where N is Prescler: 8 topvalue=(F_CPU / (16 * note_frequency));

// Reset the TIMER1 16 bit Counter TCNT1H = 0; TCNT1L = 0;

// Set the TIMER1 Counter TOP value on ICR1H and ICR1L ICR1H = (top_value >> 8 ) & 0x00FF; ICR1L = top_value;

// Set the TIMER1 PWM Duty Cycle on OCR1AH and OCR1AL // Always use half of the TOP value (PWM Ducty Cycle ~ 50%) duty_cycle=top_value / 2;

OCR1AH=(duty_cycle >> 8 ) & 0x00FF;

OCR1AL=duty_cycle;

// Turn ON the TIMER1 Prescaler of 8 TCCR1B |= (1<<CS11);

// Notes Delay Duration _delay_ms(duration);

// Turn OFF the TIMER1 Prescaler of 8 TCCR1B &= ~(1<<CS11);

// Delay Between Each Notes 1/5 duration _delay_ms(duration * 1/5);

}

// Display LED function void DisplayLED(void)

{

if (ledstat) { PORTD=led_out;

led_out=led_out << 1; if (led_out >= 0x80) ledstat=0; } else { PORTD=led_out;

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

led_out=led_out >> 1; if (led_out <= 0x01) ledstat=1;

}

}

int main(void)

{

unsigned int notes[25]={C4,Cc4,D4,Dc4,E4,F4,Fc4,G4,Gc4,A4,Ac4,B4,

C5,Cc5,D5,Dc5,E5,F5,Fc5,G5,Gc5,A5,Ac5,B5,C6};

int icount; unsigned char pstat; unsigned int idelay;

// Initial PORT Used DDRD = 0b11111111;

// Set PORTD as Output

PORTD = 0b00000000; DDRB = 0b11111110; PORTB = 0b00000000;

// Set PB0 as Input and other as Output

// Initial the ADC Peripheral ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

// Use Free running Mode ADCSRB = 0b00000000;

// Disable digital input on Channel 0 DIDR0 = 0b00000001;

// Initial TIMER1 Phase and Frequency Correct PWM // Set the Timer/Counter Control Register TCCR1A = 0b11000000; // Set OC1A when up counting, Clear when down counting TCCR1B = 0b00010000; // Phase/Freq‐correct PWM, top value = ICR1, Prescaler: Off

// Initial Variables

icount=0;

pstat=1;

led_out=1;

ledstat=1;

for(;;) {

// Loop Forever

// Reading User Trimpot on Analog Channel 0

ADMUX=0;

// Start conversion by setting ADSC on ADCSRA Register ADCSRA |= (1<<ADSC);

// wait until convertion complete ADSC=0 ‐> Complete while (ADCSRA & (1<<ADSC));

// Get the ADC Result idelay=ADCW;

DisplayLED(); if (pstat) { PlayNotes(notes[icount++],idelay); if (icount > 24) {

}

icount=24;

pstat=0;

} else { PlayNotes(notes[icount‐‐],idelay);

if (icount < 0) {

}

}

icount=0;

pstat=1;

}

return 0;

// Standard Return Code

}

/* EOF: avrpwm03.c */

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

Togenerateacontrollabletone,weneedtoproducetheexactfrequencyoneachnotes,thenotes

frequencycouldbefoundatthiswebsiteaddresshttp://www.phy.mtu.edu/~suits/notefreqs.html.Inorder

togeneratetheC5notewehavetoproducethePWMfrequencyof523.23Hzat50%dutycycle.

ThereforebysettingtheWaveGenerationModeBitsWGM13=1,WGM12=0,WGM11=0,and

WGM10=0respectively,wechoosetheTIMER1PhaseandFrequencyCorrectPWMmodewhichhasTOP

valuesetonTIMER1InputCaptureRegistersICR1HandICR1L;thePulseWidthissetonTIMER1Output

CompareRegistersOCR1AandOCR1B.

CompareRegisters OCR1A and OCR1B .

Withtheprecalerbeingsetto8andboardfrequencyof1109200Hz,wecouldeasilycalculatetheTOP

valueoftheC5noteasfollow:

PWMFrequency=FreqClock/(2xNxTOP)=FreqClock/(16xTOP)

Or

TOP=FreqClock/(16xPWMFrequency)=11059200/(16x523)=1322

NowbyassigningtheTOPvaluetotheInputCaptureRegisters(ICR1HandICR1L)andhalfoftheTOP

valuetotheOutputCompareRegister(OCR1AHandOCR1AL)wecouldproducetheC5noteswith50%

dutycycleasshownonthisfollowingCcode:

// Calculate the Top Value // TOP = Board Clock Frequency / (2 x N x Notes Frequency) // Where N is Prescler: 8 topvalue=(F_CPU / (16 * note_frequency));

// Set the TIMER1 Counter TOP value on ICR1H and ICR1L ICR1H = (top_value >> 8 ) & 0x00FF; ICR1L = top_value;

// Set the TIMER1 PWM Duty Cycle on OCR1AH and OCR1AL // Always use half of the TOP value (PWM Ducty Cycle ~ 50%) duty_cycle=top_value / 2;

OCR1AH=(duty_cycle >> 8 ) & 0x00FF;

OCR1AL=duty_cycle;

BecausetheICR1HandICR1Larethe8­bitregisters,thereforeweusetheClanguageshiftright

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

operatortoassigntheupper8­bittop_valuetoICR1Handthelower8­bitTOPvaluetoICR1L.Weuse

similarprincipaltobothOCR1HandOCR1LforthePWMdutycyclevalue(duty_cycle).ThecompleteC

codeisimplementedinPlayNotes()function,whichacceptthefrequencyanddurationparametersto

producetheneededsound.TheAVRATMega168microcontrollerADCperipheralisusedtocontrolthe

playingnotesdelaybypassingthetrimpotvoltagereadingconnectedtoADCchannel0(PC0),wecould

controlthenotesdurationasshownonthisfollowingCcode:

// Reading User Trimpot on Analog Channel 0

ADMUX=0;

// Start conversion by setting ADSC on ADCSRA Register ADCSRA |= (1<<ADSC);

// wait until convertion complete ADSC=0 ‐> Complete while (ADCSRA & (1<<ADSC));

// Get the ADC Result idelay=ADCW;

PlayNotes(notes[icount++],idelay);

DigitalConverterAVRCProgramming ”articlesonthisblog TheRGBLEDLightandSoundShow

TheRGBLEDLightandSoundShow

OnthislasttutorialwewillputalltogethertheAVRATMega168basicPWMlessonsthatwe’velearnedand

makingsomeinterestingRGBLEDandSoundshowasshownonthisfollowingschematic:

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

ThisRGBlightandSoundshowprojectusedthewellknownLM386linearamplifierICfromNational

SemiconductorwhichrecentlyhasbeenacquiredbyTexasInstrument(April2011)toproduceaquite

loudsoundfromtheTIMER1PhaseandCorrectFrequencyPWMmodethroughthespeaker.TheTIMER1

OutputCompareChannelA(PB1)PWMsignalisbeingpassedthroughthepassivelowpassfilter(isalso

calledanintegratorcircuitforanonsinusoidalinputsignalsuchassquarewaveandtrianglewave)in ordertoshapethesquarewaveformstobecomethesinusoidalwaveformsbeforebeingamplifiedbythe

LM386IC.

Tomakethelowpassfilter(LPF)becomeagoodintegratorcircuitwehavetochoosetheLPFcutoff frequencymuchlessthanthelowestfrequencyproducedbythePWMsignalbutatthesametimestill

produceanadequatesignalleveltodrivetheLM386amplifierinput.ThecutofffrequencyofLPFcouldbe

calculatedasthisfollowingformula:

Frequency=1/(2xpixRC),wherepi=3.14159,RisresistanceinOhm,andCiscapacitanceinFarad

ThelowestfrequencyproducebyPWMsignalis262Hz(C4note),thereforebychoosingR=15KandC

=0.1uF,wecouldcalculatetheLPFcutofffrequencyasfollow:

Frequency=1/(2x3.14159x15000x0.0000001)=106.10Hz

Thismethodisusedtoensurethatwecouldgetaquitenicesoundproducedonthespeakerinsteadof

justusingrawsquarewavesignalasshownonthisfollowingoscilloscopepicture:

EachoftheRGBLEDcathodesisdrivenbyTIMER0FastPWMchannelA,channelB,andTIMER2Phase

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

CorrectPWMchannelBrespectively.ThefollowingisthecompleteCcodeforourRGBLEDLightand

SoundShowfinalproject:

//***************************************************************************

//

File Name

: avrpwm04.c

//

Version

: 1.0

// Description : AVR TIMER0 Phase and Frequency Correct PWM Mode

//

Author

: RWB

//

Target

: AVRJazz Ultimate 28PIN Board

// Compiler

: AVR‐GCC 4.3.3; avr‐libc 1.6.7 (WinAVR 20100110)

//

IDE

: Atmel AVR Studio 4.18

// Programmer

: AVRJazz Mega168 STK500 v2.0 Bootloader

//

: AVR Visual Studio 4.18, STK500 programmer

//

Last Updated : 22 March 2011

//*************************************************************************** #include <avr/io.h>

#include <util/delay.h> #include <avr/interrupt.h> #include <stdlib.h>

// Notes Frequency from http://www.phy.mtu.edu/~suits/notefreqs.html // The Original frequency value (decimal) is converted to the integer value #define C4 262 #define Cc4 277 #define D4 294 #define Dc4 311 #define E4 330 #define F4 349 #define Fc4 370 #define G4 392 #define Gc4 415 #define A4 440 #define Ac4 466 #define B4 494

#define C5 523 #define Cc5 554 #define D5 587 #define Dc5 622 #define E5 659 #define F5 698 #define Fc5 740 #define G5 783 #define Gc5 831 #define A5 880 #define Ac5 932 #define B5 988

#define C6 1047

volatile unsigned char duty_cyc_a,duty_cyc_b, duty_cyc_c,led_a,led_b,led_c; volatile unsigned int tempo;

// TIMER1 Overflow Interrupt

ISR(TIMER1_OVF_vect)

{

cli();

// Disable Interrupt

// Reading User Trimpot on Analog Channel 0 ADMUX = 0;

// Start conversion by setting ADSC on ADCSRA Register ADCSRA |= (1<<ADSC);

// wait until convertion complete ADSC=0 ‐> Complete while (ADCSRA & (1<<ADSC));

// Get the ADC Result tempo=ADCW;

if (led_a) { if (duty_cyc_a < 255) {

OCR0A=duty_cyc_a++;

 

}

else {

 

led_a=0;

 

}

}

else { if (duty_cyc_a > 0) {

 

OCR0A=duty_cyc_a‐‐;

 

}

else {

 

led_a=1;

duty_cyc_a=TCNT1L;

 

}

}

if (led_b) { if (duty_cyc_b < 255) {

OCR0B=duty_cyc_b++;

} else {

led_b=0;

}

} else { if (duty_cyc_b > 0) {

OCR0B=duty_cyc_b‐‐;

} else {

led_b=1;

duty_cyc_b=(unsigned char) rand() % 255; ;

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

}

}

if (led_c) { if (duty_cyc_c < 255) {

}

OCR2B=duty_cyc_c++;

else {

led_c=0;

}

} else { if (duty_cyc_c > 0) {

OCR2B=duty_cyc_c‐‐;

}

else {

led_c=1;

duty_cyc_c=TCNT1H;

}

}

sei();

// Enable Interrupt

}

// PlayNotes function

void PlayNotes(unsigned int note_frequency,unsigned int duration)

{

unsigned int top_value,duty_cycle;

// Calculate the Top Value // TOP = Board Clock Frequency / (2 x N x Notes Frequency) // Where N is Prescler: 8 topvalue=(F_CPU / (16 * note_frequency));

// Reset the TIMER1 16 bit Counter TCNT1H = 0; TCNT1L = 0;

// Set the TIMER1 Counter TOP value on ICR1H and ICR1L ICR1H = (top_value >> 8 ) & 0x00FF; ICR1L = top_value;

// Set the TIMER1 PWM Duty Cycle on OCR1AH and OCR1AL // Always use half of the TOP value (PWM Ducty Cycle ~ 50%) duty_cycle=top_value / 2;

OCR1AH=(duty_cycle >> 8 ) & 0x00FF;

OCR1AL=duty_cycle;

// Turn ON the TIMER1 Prescaler of 8 TCCR1B |= (1<<CS11);

// Notes Delay Duration _delay_ms(duration);

// Turn OFF the TIMER1 Prescaler of 8 TCCR1B &= ~(1<<CS11);

// Delay Between Each Notes _delay_ms(duration * 1/5);

}

int main(void)

{

unsigned char song_index;

// Initial PORT Used DDRD = 0b11111111; PORTD = 0b00000000; DDRB = 0b11111110; PORTB = 0b00000000;

// Set PORTD as Output

// Set PB0 as Input and other as Output

// Initial the ADC Peripheral ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

// Use Free running Mode ADCSRB = 0b00000000;

// Disable digital input on Channel 0 DIDR0 = 0b00000001;

// Initial TIMER0 Fast PWM // Fast PWM Frequency = fclk / (N * 256), Where N is the prescaler // f_PWM = 11059200 / (64 * 256) = 675 Hz

TCCR0A = 0b10100011; // Fast PWM 8 Bit, Clear OCA0/OCB0 on Compare Match, Set on TOP TCCR0B = 0b00000011; // Used 64 Prescaler

TCNT0 = 0; OCR0A = 0; OCR0B = 0;

// Reset TCNT0 // Initial the Output Compare register A & B

// Initial TIMER1 Phase and Frequency Correct PWM // Set the Timer/Counter Control Register TCCR1A = 0b11000000; // Set OC1A when up counting, Clear when down counting TCCR1B = 0b00010000; // Phase/Freq‐correct PWM, top value = ICR1, Prescaler: Off

TIMSK1 = (1<<TOIE1); // Enable Overflow Interrupt

// Initial TIMER2 Phase Correct PWM Mode

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

// Phase Correct PWM Frequency = fclk / (N * 512), Where N is the prescaler // f_PWM = 11059200 / (64 * 512) = 337.5 Hz

TCCR2A = 0b00100001; // Fast PWM 8 Bit, Clear OC2B on Compare Match, Set on TOP TCCR2B = 0b00000011; // Used 64 Prescaler

TCNT2 = 0; OCR2B = 0;

// Reset TCNT2 // Initial the Output Compare register A & B

duty_cyc_a=(unsigned char) rand() % 255;

led_a=1;

duty_cyc_b=(unsigned char) rand() % 255;

led_b=1;

duty_cyc_c=(unsigned char) rand() % 255;

led_c=1;

sei();

// Enable Interrupt

song_index=0;

tempo=0;

for(;;) {

// Loop Forever

// Playing "What a Wonderfull World" Song Notes PlayNotes(G4,300 + tempo); PlayNotes(A4,100 + tempo); PlayNotes(C5,500 + tempo); PlayNotes(C5,450 + tempo); PlayNotes(G5,1150 + tempo); PlayNotes(A5,350 + tempo); PlayNotes(A5,350 + tempo); PlayNotes(A5,150 + tempo); PlayNotes(G5,1150 + tempo); PlayNotes(F5,450 + tempo); PlayNotes(F5,300 + tempo); PlayNotes(F5,250 + tempo); PlayNotes(E5,1150 + tempo); PlayNotes(D5,600 + tempo); PlayNotes(E5,175 + tempo); PlayNotes(D5,100 + tempo); PlayNotes(C5,1050 + tempo);

PlayNotes(C5,550 + tempo); PlayNotes(C5,175 + tempo); PlayNotes(C5,100 + tempo); PlayNotes(C5,100 + tempo); PlayNotes(C5,150 + tempo); PlayNotes(C5,1300 + tempo); PlayNotes(C5,600 + tempo); PlayNotes(B4,200 + tempo); PlayNotes(C5,200); PlayNotes(D5,200 + tempo);

if (song_index >= 1) { PlayNotes(C5,1600 + tempo);

if (song_index == 3) { _delay_ms(100 + tempo); PlayNotes(C5,550 + tempo); PlayNotes(C5,175 + tempo); PlayNotes(C5,100 + tempo); PlayNotes(C5,100 + tempo); PlayNotes(C5,150 + tempo); PlayNotes(C5,1300 + tempo); PlayNotes(C5,800 + tempo); PlayNotes(B4,400 + tempo); PlayNotes(C5,300 + tempo); PlayNotes(D5,300 + tempo); PlayNotes(C5,2300 + tempo);

song_index = 0; } else {

song_index=2;

}

} else { PlayNotes(E5,1100 + tempo); PlayNotes(E5,800 + tempo); PlayNotes(D5,1600 + tempo);

song_index=1;

}

if (song_index == 2) { _delay_ms(100 + tempo);

PlayNotes(C5,450 + tempo); PlayNotes(D5,150 + tempo); PlayNotes(D5,50 + tempo); PlayNotes(D5,50 + tempo); PlayNotes(D5,1 + tempo); PlayNotes(D5,1000 + tempo); PlayNotes(G4,450 + tempo); PlayNotes(E5,150 + tempo); PlayNotes(E5,50 + tempo); PlayNotes(E5,50 + tempo); PlayNotes(E5,1 + tempo); PlayNotes(E5,1000 + tempo);

PlayNotes(C5,350 + tempo); PlayNotes(D5,250 + tempo); PlayNotes(D5,100 + tempo); PlayNotes(D5,75 + tempo); PlayNotes(D5,350 + tempo); PlayNotes(C5,150 + tempo); PlayNotes(D5,250 + tempo); PlayNotes(E5,1000 + tempo); PlayNotes(E5,250 + tempo); PlayNotes(G5,175 + tempo); PlayNotes(A5,450 + tempo); PlayNotes(A5,100 + tempo);

PlayNotes(E5,150 + tempo); PlayNotes(G5,1000 + tempo); PlayNotes(A5,100 + tempo); PlayNotes(A5,50 + tempo); PlayNotes(E5,150 + tempo); PlayNotes(G5,1000 + tempo);

PlayNotes(A5,100 + tempo); PlayNotes(A5,50 + tempo); PlayNotes(E5,150 + tempo); PlayNotes(G5,1000 + tempo); PlayNotes(F5,450 + tempo); PlayNotes(E5,650); PlayNotes(D5,1300 + tempo);

song_index =3;

}

}

return 0;

// Standard Return Code

}

/* EOF: avrpwm04.c */

FromtheCcodeaboveyoucouldseethatweusealltheavailableAVRATMega168microcontrollerPWM

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

sourcestodriveboththeRGBLEDandatthesametimeplaying“WhataWonderfulWorld”song.Byusing

theTIMER1overflowinterrupt(TOIE1=1inTIMER1interruptmaskregisterTIMSK1)wecoulddisplaythe

RGBLEDandatthesametimeplayingthesongnotes.

TheRGBLEDPWMdutycycleisachievedbyassigningbothrandomvalueandthe16­bitTIMER1counter

value(TCNT1HandTCNT1L)totheOutputCompareRegister(OCRn)inISR(TIMER1_OVF_vect)

functionroutine.WiththismethodwecouldgetthedesiredRGBLEDlighteffectwhichisdependonthe

songnotes.Ofcourseyoucouldexperimentwithotherregistervalueaswell(e.g.ICR1HandICR1L

registers).

Nowit’stimetowatchallthebasicAVRPWMexperimentswe’vedoneonthisfollowingvideo:

TheFinalThought

KnowingthebasicworkingprincipaloftheAtmelAVRmicrocontrollerPWMperipheralisoneofknowledge

thatshouldbelearnedbyanyonewhowanttoinvolveintheembeddedworldprofessionallyorjustasa

hobbyists.IhopethisbasicAVRPWMtutorialwillgiveyouasolidAVRPWMknowledgetobeusedinyour

nextembeddedproject.

BookmarksandShare

nextembeddedproject. BookmarksandShare RelatedPosts

RelatedPosts

18Responsesto“WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)

Peripheral”

14.08.11

Commentbyiziccoz.

#1

IsitpossibletomakePWMoutputonnonPWMoutput?

Forexample,IhaveATMEGA8whichhasthreePWMchannel,

butIneed4channelPWMonmyproject.Isitpossible?

Thanks.

Forexample,IhaveATMEGA8whichhasthreePWMchannel, butIneed4channelPWMonmyproject.Isitpossible? Thanks.
butIneed4channelPWMonmyproject.Isitpossible? Thanks. http://www.ermicro.com/blog/?p=1971 19/22

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

14.08.11

Commentbyrwb.

#2

Yes,youcouldreadtheworkingprincipleonthisfollowing

article:

20.08.11

Commentbyjoerfrada.

Hi,rwb.

#3

Ineedyourhelp.HowtomakePWMoutputwithL293Dmotor

DConAtmega8@4MHzexternalcrystal.BecauseAtmega8

makesUARTSerialRFRX/TX433MHz,butIgottheRFRX/TX

433MHz,itworks.PleaseexplainmeabouttomakePWM

outputwith4MHzexternalcrystal.

Ihopeyouranswersoon.

Regards,

JoeRonaldFlórezRada

fromColombia.

20.08.11

Commentbyrwb.

#4

YoucouldgetmoreinformationofhowtodrivetheL293Ddual

H­BridgemotorcontrollerwithPWMonthisfollowingarticles:

23.10.11

CommentbyBF1Quang.

#5

Whatagreatproject,I’vejustjoinedyourblog.I’mdoingmy

projectaboutrobotarm!Yourblogisverygreatandhavea

lotofinformationformetolearn.Thankyouverymuch!

Ihaveaquestionforyou,wouldyoupleasetoanswerme:­):

Howtopreciselycontrolservomotor(FutabaS3003)rotation

usingtrimport(varistor)!

SorryifImindyou!I’mlookingforwardtoyouransweror

clues!

Bestregards!

23.10.11

Commentbyrwb.

#6

Theservomovementbasicallyiscontrolledby1.5ms

(center),0.7–1.0ms(CW),and1.7–2.0ms(CCW)PWM

signal.ThereforebyprovidingthisPWMsignaloncertain

period(e.g.50ms)wecouldmovetheservosarmtothe

certaindegree.ThusbyconvertingthisPWMsignalperiodto thedegreeofmovementwecouldeasilymaptheanalog trimpotvalue(usedtheADCperipheral)totheservo

movement(e.g.5degree=50ms).Youcouldreadmore

aboutbasicservoonthisfollowingarticle:

25.10.11

CommentbyBF1Quang.

#7

I’vereadthatarticle!It’sreallyreallygrateful!:­),Thankyou

verymuch!AndmayIaskyouthatwhichPWMModeshould

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

beusedintheproject?I’musingAVRATmega8!

Niceday!

25.10.11

#8

Commentbyrwb.

YoucoulduseeitherfastorphasecorrectPWMmode.

21.05.12

#9

Thereisabigtrade­offbetweenbetterPWMresolutionand

higherPWMfrequency.

17.03.13

#10

CommentbyJohnOwensChina.

ThanksforthePWMinstructions. IhadtoaddthefollowingfunctiontoevenbuildonAVRStudio

6:

voiddelay_ms(intms)

{

for(inti=0;i<ms;i++)

{

delay_ms(1);

}

}

Thisisbecauseyoucanonlysendaconstantto_delay_ms.

However,itonlyproducesanoisy~300hzsoundandall3

ledsareonbutnotchanging. Arethereanyotherupdatesrequired? Ididn'thavethecrystalinthediagram,soIhavetriedboth

withoutthecrystalandusinga2Mhzxtal,bothwiththesame

result.The10KpotonPC0doesnothaveanyeffectonsound

orLEDoutput.

Thanksforyourhelp.

17.03.13

Commentbyrwb.

#11

Sinceyouuseddifferentcrystalfrequency,youneedtoadjust

thecodetosuitethecrystalfrequencyforthegeneratedPWM.

18.03.13

#12

CommentbyJohnOwensChina.

Thanks,Iwilltryboth.specifiedcrystalandchangingthe

code.

Whatisthe10KpotonPC0usedfor.Icouldnotseethis

mentionedinthetextorinthecode.

24.03.13

#13

CommentbyJohnOwensChina.

Ipurchasedthecorrectcrystal,butitstilldoesnotwork. MaybeIneedtosettheclocksourceinthefuses.ButIdon’t

knowhowtodothiswithAVRStudio6.

Canyoupleasetellmehowtosetthis?Isearchedthe

datasheetandtheAVRStudiohelpfile,butitseemslikeAVR

Studioparametersaredifferentthanwhatisshowninthedata

sheet.

Thanksforyourhelp.

John

31.05.13

Commentbymusteno.

#14

I`minterestedhowdidyouwriteasong.Iunderstandthe

02.09.2015.

WorkingwithAtmelAVRMicrocontrollerBasicPulseWidthModulation(PWM)Peripheral|ermicroblog

partforchords,butiwanttoknowhowyoumanagewith

delays.

02.06.13

Commentbyrwb.

#15

“TryandError”,andifyouamusicplayerthenthisstagewill

beshorter.

07.10.13

#16

Commentbyyaqub.

Iwantmakemicforinput­>lm386­>thenIwantread

frequencyandamplitudeinatmega.WhatshouldIdoorI

modify?

08.10.13

#17

Commentbyrwb.

Youwillneedtowriteyourowncodes,basicallyyouwantto

buildanoscilloscopeusingAVRATmegamicrocontroller

24.03.15

Commentbytushki.

hi

#18

actuallyiamusingArduinoDuecontrollerinwhichihaveto

generateSPWMsignals.canyouguidemehowtogenerate

SPWMsignals

freq.:50Hz

carrierfreq.:5000Hz

LeaveaComment

Youmustbeloggedintopostacomment.

Copyright©2008­2015Byermicro.PoweredbyWordPress.