Hoi,

ik zou via software een pwm-signaal willen opwekken (zoals zovelen hier al gevraagd hebben).
De meesten gebruiken een interrupt-routine,maar is dit echt noodzakelijk?
Stel:.
-timer0 loopt in vrijloop.
-timer0 > dutycycle dan uitgang laag.
-timer0 < dutycycle dan uitgang hoog.

dit geeft volgens mij een pwm-signaal,het werkt allesinds in een simulatie.
Wat denken jullie en wat zijn de nadelen?

PS: ik ben pas (vandaag) terug begonnen met pic's.

Greetz

Ik zou zeggen probeer het gewoon :)

Het kan inderdaad zo werken...

Ja, het kan, maar op die manier wordt de nauwkeurigheid wel erg laag. De meeste microcontrollers hebben daar speciale hardware voor aan boord, waarmee het veel nauwkeuriger kan, terwijl je de processor dan ook nog vrij hebt voor andere taken.

Als je meer kanalen nodig hebt dan dat je PWM hardware hebt, kun je weinig anders dan het in software doen. Het kan wel, als de frequentie maar laag genoeg is.

@SparkyGSX: Bedankt voor de duidelijke uitleg.
Nauwkeurigheid is in deze toepassing (simpele rgb controler) niet belangrijk.

Ik probeer nu al anderhalf uur te testen maar het lijkt onmogelijk.

EDIT:

probleem is opgelost,trisb:=0 werkt beter dan trisb:=255 als de poort output moet doen.

Zeer domme fout....

[Bericht gewijzigd door Stressy op (49%)]

Wat ik heb gedaan om nauwkeurig PWM te doen op vier outputs die daar volgens de hardware niet geschikt voor zijn is: Ik zet de pin hoog, ik neem de timer1 waarde, en reken uit wanneer ie weer laag moet. Dan zet ik een interrupt op de "output compare" van de timer, op die waarde. In de interrupt knal ik het pinnetje weer laag.

Hoge resolutie, weinig jitter, maar wel meer jitter dan met een hardware oplossing.

Ik begrijp nu waarom jullie interrupts gebruiken.
Als er delays gebruikt worden veranderd het pwm-signaal in "morse code".
Les geleert en tevens bedankt voor de tips.
Nu eens iets proberen met interrupt routine.

als je nu gewoon dmv een timer interrupt een vaste tijdbasis maakt, dan kan je in deze interrupt zoveel pwm kanalen bijhouden als je wilt.
gewoon per pwm kanaal een tellertje bijhouden en elke tick controlleren of dit tellertje boven of onder de pwm waarde ligt. Aan de hand hiervan pin hoog of laag maken

Dat zeg ik, het kan wel, als de frequentie maar niet te hoog is.

Voor een PWM frequentie van 100Hz en een resolutie van 8 bits heb je al een ISR frequentie van 25600Hz. Probeer op die manier maar eens een hogere resolutie of een hogere frequentie te halen; dat houd dus snel op.

Ik heb nu volgende code in de pic staan:


program RGBled;

{ Declarations section }
    var r,g,b          :byte;
        pwm1           :byte;
    
procedure interrupt();
begin

  if TestBit(INTCON, T0IF) = 1 then
  begin
    if pwm1=255 then pwm1:=0;
    pwm1 := pwm1 + 1;
    TMR0 := 50;
    if pwm1>r then portb.0:=0;
    if pwm1<r then portb.0:=1;
    if pwm1>g then portb.2:=0;
    if pwm1<g then portb.2:=1;
    if pwm1>b then portb.4:=0;
    if pwm1<b then portb.4:=1;
    ClearBit(INTCON, T0IF);
  end
end;


begin
 INTCON.GIE:=1;                                 //enable all interrupts
 INTCON.T0IE:=1;                                //enable timer0 interrupt
 INTCON.PEIE := 1;
 OPTION_REG.T0CS := 0;                          // bit 5 TMR0 Clock Source Select bit:0=Internal Clock (CLKO) / 1=Transition on T0CKI pin
 OPTION_REG.T0SE := 0;                          // bit 4 TMR0 Source Edge Select bit: 0=low/high / 1=high/low
 OPTION_REG.PSA  := 1;                          // bit 3 Prescaler Assignment bit: 0=Prescaler is assigned to the WDT
 OPTION_REG.PS2  := 0;                          // bits 2-0  PS2:PS0: Prescaler Rate Select bits
 OPTION_REG.PS1  := 0;
 OPTION_REG.PS0  := 0;
 CMCON:=7;
 trisb:=0;                                      //portb is all output
 portb:=0;   
 TMR0:=50;                                   //port b all 0
 r:=25;
 g:=90;
 b:=254;
 pwm1:=0;
 
  repeat
   begin
    if button(PortA,0,5,1) then r:=r-1;
    if button(PortA,1,5,1) then r:=r+1;

   end;
  until 1>1;

end.

Dit is MikroPascal,de pic draait nu op 4 Mhz maar zal uiteindelijk op 20 Mhz draaien.
Probleem is dat de leds zichtbaar knipperen op een lage dutycycle.
Tevens vraag ik me ook af als er niet teveel if's in de ISR staan?

Edit: Volgens Isis (simulator) haal ik een frequentie van 18 Hz,deze blijft constant onafhankelijk van de dutycycle.
De hoogste frequentie die ik behaal is om en bij de 45 Hz als ik TMR0 preload met 200.
Op 20 Mhz haal ik 217 Mhz,op zich genoeg voor mijn toepassing maar toch vind ik deze waarden belachelijk laag.
Nogmaals,deze "metingen" zijn virtueel,ik kan niet real world testen omdat ik geen scoop heb.

Edit2: Net even de code (met preload 200) in de pic gezet,de simulatie lijkt te kloppen,het knipperen is nu bijna niet zichtbaar.
Tips zijn echter altijd welkom.