William Sandqvist DA-omvandling, oftast PWM
William Sandqvist PWM med Timer0 75% 25% void main( void) { Duty = 0; /* start with zero DutyCycle */ TRISB = 0b ; /* PORTB.0 is output */ /* PORTB.1 is input */ OPTION = 0b ; /* Timer0 1/256 */ while (1) /* forever */ { char i; if (TMR0 < Duty) PWM_out = 1; else PWM_out = 0; Duty = GetDuty(); /* Be back in one TIMER0-tick ! */ MoreToDo(); } } Tillbaks inom ett Timer0-tick!
William Sandqvist PWM med Timer0 75% 25% /* Function */ char GetDuty( void) { char Duty; if( Contact == ON ) Duty = 191; /* 191/255 = 75% Dutycycle */ /* _______ __ */ /* _| |__| */ /* */ else Duty = 64; /* 64/255 = 25% Dutycycle */ /* __ __ */ /* _| |_______| */ /* */ return Duty; }
William Sandqvist PWM med Timer0 /* Function */ void MoreToDo( void) { } Gör lite nytta här, men … Missa inte nästa Timer0-tick!
William Sandqvist Valfri färg med RGB Led Difus plast behövs för att färgerna ska ”blandas”. Så här skulle man kunna göra …
William Sandqvist Valfri färg med RGB Led while (1) /* forever */ { if(PORTB.0==0) intensity =75; else intensity =255; R_Duty = 0; G_Duty = 0; B_Duty = 0; if( PORTB.3 ) R_Duty = intensity ; if( PORTB.2 ) G_Duty = intensity ; if( PORTB.1 ) B_Duty = intensity ; /* PWM-generation */ if (TMR0 < R_Duty) RA0 = ON; /* Red PWM */ else RA0 = OFF; if (TMR0 < G_Duty) RA1 = ON; /* Green PWM */ else RA1 = OFF; if (TMR0 < B_Duty) RB5 = ON; /* Blue PWM */ else RB5 = OFF; }
William Sandqvist Styr färg med slumptal … Många algoritmer för slumptal utnyttjar multiplikation och division, något som inte är midrange PIC-processorernas starkaste sida. Nedanstående algoritm bygger i stället på tekniken med "återkopplade shiftregister", som ger hyfsade slumptal utan allt för mycket kod... /* Random number function */ char rand( void ) { /* 0x0000 won't run... */ bit EXOR_out; static char rand_hi, rand_lo; if( !rand_hi && !rand_lo ) rand_lo = 0x01; EXOR_out = rand_lo.0; EXOR_out ^= rand_lo.2; EXOR_out ^= rand_lo.3; EXOR_out ^= rand_lo.5; Carry = EXOR_out; /* rotate right */ rand_hi = rr( rand_hi); rand_lo = rr( rand_lo); return rand_lo; }
Så här ser de första bits slumptalen ut … William Sandqvist char rand( void ); …
William Sandqvist CCP - PWM Det finns ett uppenbart behov av en självständig enhet för generering av PWM. CCP-enheten kan programmeras till detta!
William Sandqvist För PWM används TIMER2
William Sandqvist TIMER2
William Sandqvist Samplingsklocka Har man en reglerloop är det viktigt med en konstant samplings- frekvens. Blir Du lovad löneförhöjning med 500 kr/varv så vill Du nog gärna veta om det är: 500:-/tim 500:-/vecka 500:-/månad TIMER2 postscaler overflow kan an- vändas som samp- lingsklocka.
William Sandqvist TIMER2 servoupdate TIMER2 postscaler overflow kan an- vändas som samp- lingsklocka. Man kan få interrupt efter tex. var 4:e, var 8:e, var 16:e PWM-puls och då passa på att uppdatera PWM-signalen. ( Se programmet PIC-talker ).
William Sandqvist PWM frekvens T2CON postscale 1/1 … 1/16 ON/OFF prescale 1/1, 1/4, 1/16 PR2 förkortar räknecykeln Frekvensinställning görs således med ”prescale” och ”PR2”.
William Sandqvist PWM-mode PWM-mode = 11xx CCP1X, CCP1Y Två extra bitar
William Sandqvist PWM-frekvens och DutyCycle PWM-frekvens DutyCycle
William Sandqvist PWM till 1000! PWM-frekvens 1000 Hz DutyCycle 50% för att testsignal … 1000 Hz DutyCycle 50%
William Sandqvist pwm1k62x.c void main( void) { TRISB.3 = 0; /* CCP1 is output at RB3 ( pin 9 ) */ /* Setup TIMER 2 */ /* 0.xxxx.x.xx - x.0000.x.xx 1:1 postscaler x.xxxx.1.xx TMR2 on x.xxxx.x.01 1:4 prescaler */ T2CON = 0b ; PR2 = 249; /* PWM frequency 1000 Hz */ /* Setup CCP1 PWM-mode */ /* 00.x.x.xxxx -- xx.0.0.xxxx CCP1X=0 CCP1Y=0 xx.x.x.1111 PWM-mode (11--) */ CCP1CON = 0b ; /* 50% 10 bit Duty 0b = 500 */ CCPR1L = 125; /* 0b */ while(1) nop(); } Lyssna med hörluren, och mät frekvensen och DutyCyclen med Scopemeter123 PWM-enheten är helt självgående …
William Sandqvist
Varvtalsratt till LEGO-motor
William Sandqvist PWM till motor Enklast. PR2=255, ingen förkortning. Enklast. 8 bitars PWM, rör ej CCP1X=0 och CCP1Y=0. CCPR1L = Duty; /* %...100% */ PWM-frekvensen blir då vad den blir … ( Om PWM-frekvensen < Hz kan den ”höras” när motorn kör )
William Sandqvist Varvtalsratten Interruptrutinen /* read encoder new value */ trans.0 = quad_A; trans.1 = quad_B; /* compare with old value */ if( (trans == 0b00.01) && (count != 255) ) count ++; if( (trans == 0b01.00) && (count != 0) ) count --; /* replace old value with new value */ trans.2 = trans.0; trans.3 = trans.1; OBS! Max och mingränserna!
William Sandqvist DutyCycle while(1) { speed = count; CCPR1L = speed; /* new PWM-value */ } count uppdateras av interruptrutinen!
William Sandqvist Utmaningen – Fram/Back
William Sandqvist 1 bit Riktning i ”tal med tecken” int count; Kör moturs för negativa tal, de har teckenbiten = 1 Kör medurs för positiva tal, de har teckenbiten = 0 /* rotate cw or ccw */ PORTA.1 = count.7;
William Sandqvist ”tal med tecken” och invertering av Dutycycle Vid moturs rotationsriktning måste DutyCycle inverteras. Detta innebär att motorn går snabbt vid låg DutyCycle och att motorn går långsamt vid hög DutyCycle. Men detta stämmer ju helt med hur negativa tal representeras! Ökande negativa tal , , , … ger ökande moturs hastighet. Vi behöver därför inte göra någon extra invertering!
William Sandqvist 8 bitars hastighet ? Om pulsgivarens räknar hastigheten i en int så använder vi 7 bitar per riktning. PWM-enheten använder en char och behöver 8 bitar för full fart. Lösning: Multiplicera med 2. speed = count* 2; CCPR1L = speed; /* new PWM-value */ OBSERVERA! Nu behövs nya gränser för räknevärdet: if( (trans == 0b00.01) && (count != 127) ) count ++; if( (trans == 0b01.00) && (count != -128) ) count --;
William Sandqvist
Uni- eller Bipolär PWM PWM-signaler En bipolär PWM-signal kan köra motorn i två riktningar, men också hålla en motor stillastående med ett Hållmoment! Unipolär PWM signal kör en motor i en riktning.
William Sandqvist PIC16F690 har enhanced PWM! Byta rotationsriktning kan man då göra genom att styra över PWM-signalen till en annan utgång i stället för att invertera DutyCycle!
William Sandqvist Två drivsignaler (ex. halvbrygga) Undviker kortslutning! Två drivsignaler till helbrygga
William Sandqvist 4 drivsignaler Helbrygga
William Sandqvist Helbrygga Forward mode: PWM på P1D Reverse mode: PWM på P1B