Another PWM post

Thread Starter

MCrowe

Joined May 29, 2011
69
Sooo, I think i've gone almost completely crazy trying to figure this out.

I know its asking a lot, but if any one feels they could offer any advice could you please, please have a look at this for me. I've spent so long trying to figure this out and tried everything I can think of but to no avail.

The strange part is, it works perfectly if I use Period of 10000.
Like this,
Rich (BB code):
  MOVLW HIGH D'10000'  ; (20000 / (number of channel used 1...8))
  MOVWF PeriodH
  MOVLW LOW D'10000'
  MOVWF PeriodL
AND

A test BIT of BIT 2. Shown below.

Rich (BB code):
   BTFSS PortShadow,2 ; IF PAST NUMBER OF REQUIRED SERVOS SKIP NEXT.


But as soon as I change the Period to a different value, with a different test BIT, it doesn't work any more.
It reduced the Frequency to something like 12hz. instead of 50hz. Please help if you can. Thanks.



Rich (BB code):
  ; PINTERRUPT VECTOR JUMP ADDRESS
; ---------------------------------------------------------------------
 
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        org  H'04'   ; INTERRUPT VECTOR JUMP ADDRESS..  
        movwf   W_ISR           ; save main program context       
        swapf   STATUS,W      ;                                 
        movwf   S_ISR            ; save STATUS reg                
        clrf    STATUS            ; force bank 0                    
        movfW   FSR              ;                                 
        movwf   F_ISR           ; save FSR from MAIN               
        movfw ISR_FSRsave    ; Restore FSR for Interrupt    
        movwf FSR                ;          
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
;*****************************************************************************
;just used to work out if any pins are high or all pins are low. 
 
 BTFSC PortFlag,0  ; CHECK IF FLAG (PORTD) BIT IS HIGH   ;*
 GOTO DriveHigh  ; SKIPPED IF PORTD IS ALREADY ZEROS.  ;*
 
 ;else will SHIFT HIGH BIT.. making curret bit low.     ;*
;*****************************************************************************
 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;DriveLow
 
;this section uses servo pulse to work out period, & sets servo high into timer.
;select servo based on indirect addressing. 
;also calculate servo low time (period) and store in period register.  
 
       movfw   INDF           ; Servo[x] pulse. low byte, 600..2400   
       SUBWF   PeriodL,F     ; CALCULATES LOW BYTE  SAVES IN PeriodL 
       MOVWF CCPR1L        ; should put servoLx in timer low       
 
       incf    FSR,F            ;                                 
       movfw   INDF           ; Servo[x] pulse high byte, 600..2400   
       BTFSS  STATUS,C    ; Test if Carry occured.
       DECF PeriodH,F  ; If Carry occured, decrement PeriodH 
       SUBWF   PeriodH,F  ; CALCULATES HIGH BYTE SAVES IN PeriodH 
       MOVWF CCPR1H      ; should put servoHx in timer High
 
;Sets Pin High (Pin is SHIFTED in next part of Subroutine.)
      MOVFW PortShadow
      MOVWF PORTD
      BSF  PortFlag,0     ; Set FLAG for test at start.
      incf    FSR,F         ; INCREMENTS FSR ready for next time.
      GOTO ISR_EXIT     
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DriveHigh        ;drives all pins low and set servo x low time (period)
;this section set Servo into timer.
      MOVFW  PeriodH     ;# ;Period times were calculated 
      MOVWF  CCPR1H     ;# ;So now can just store in Timeer Register.
      MOVFW  PeriodL     ;#  (20,000 / (between 1&8) - Servo High Time.)
      MOVWF  CCPR1L     ;#
 
      MOVLW  b'00000000'  ;# PORTD low for Low part of Servo signal.
      MOVWF  PORTD      ;#
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;RESTORE PERIOD TIME 
  MOVLW HIGH D'5000'  ; (20000 / (number of channel used 1...8))
  MOVWF PeriodH
  MOVLW LOW D'5000'
  MOVWF PeriodL
;^^^^^^^^^^^^^^^^^^^^^^^^
;Clears PORTFLAG ready decision next time, and rotates PortShadow PIN.
      bcf  PortFlag,0          ; so next run selects for Low part of signal
      clrc                          ; clear carry to stop high bit being brough in.
      RLF  PortShadow,F     ; 00000001 <----- rotate bits Port Shadow.
;need to check incase I moved bit into carry.
;TESTS WHAT CHANNEL I AM UP TO. WILL NEED TO TEST CARRY IF I WANT FULL 8 BITS.
     BTFSS PortShadow,4 ; IF PAST NUMBER OF REQUIRED SERVOS SKIP NEXT.    
    GOTO ISR_EXIT         ; go to end if ISR.
    MOVLW B'00000001'   ; If TIME FOR RESET, reset Count and Pin Select. 
    MOVWF PortShadow  ; reset PortShadow to initial position '10000000'
    movlw   Servo           ; add Servo[0] base address  
    movwf   FSR             ; setup indirect address 
    GOTO ISR_EXIT
 
ISR_EXIT
;^^^^^^^^^^^^^^^^^^^^^^^^^^
BCF  PIR1,2      ;BIT 2 IS CCP1F (CCP1 INTERUPT FLAG BIT) CLEAR 
;^^^^^^^^^^^^^^^^^^^^^^^^^^^
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
        movfw FSR              
        movwf ISR_FSRsave      ; Save FSR from INTERRUPT            
        movfw   F_ISR                                             
        movwf   FSR                ; restore FSR                     
        swapf   S_ISR,W                                           
        movwf   STATUS          ; restore STATUS                 
        swapf   W_ISR,F          ; don't screw up STATUS           
        swapf   W_ISR,W         ; restore W-reg                   
        retfie                         ; return from interrupt           
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 

MMcLaren

Joined Feb 14, 2010
861
Nope... Got the WDT turned off. But I have tried adjusting the period (timer value) and it doesn't appear to change anything. So my best guess would be that its causing an interrupt on overflow of the 16 bit timer. maybe?? I can't figure out whats wrong with it. I was trying to adapt MMcLarens program, but couldn't get the timing to work at all. I ended up making my own for two servos, using on CCP timer and it works!!! Took a while, lots of mucking around but finally got something working.
During simulation, I found a mistake in the example program I posted. The "special event trigger" CCP mode wasn't set correctly and TMR1 wasn't being cleared. I apologize.

Please make the following changes (red);

Rich (BB code):
;
;  initialize CCP module to "special event trigger" mode which
;  resets Timer 1 on the "special event trigger" compare match
;
         movlw   b'00001011'     ; '00001011'                      |B0
                                 ; '00------' unused
                                 ; '--00----' unused, CCP1X:CCP1Y
                                 ; '----1011' special event mode
         movwf    CCP1CON        ; setup CCP module
 
Last edited:

Thread Starter

MCrowe

Joined May 29, 2011
69
Hey, Thanks, Yeah I did actually find that but even after I changed it, it still didn't work. That aside, I dont suppose you have any hints about why my code doesn't work??

The idea is different from yours. Instead of having all the Highs occuring one after the other, mine sererates them by a value, depending on how many PWM's you are using. If you have 2 PWMs then the two highs are seperated by 10,000. 4 PWMs they are seperated by 5,000... But it doesn't work. Well, it works for 2 PWMs but thats all. Im completely stuck, and going crazy.
 

Thread Starter

MCrowe

Joined May 29, 2011
69
Mmm, so it may appear ive wasted 20 hours or so on this one simple problem when all I needed to do was output the result on a different Port. I.e. not PortD. Still dont, know why this would be the case but it seems PortD doesn't work well for this application on my Eval board. I suspect MMcLarens program would have worked as well (after I fixed the timer mode problem) as it was doing the same thing as my program. Still no idea why it does doesn't work on PortD but does on PortB but at least im getting somewhere now.

P.S. How do I post code with correct spacing? Can you post the code with the Tabs and such in place, straight from MPLAB? Mine comes in all messed even with code tags. And I suspect the font type is wrong. Verdana or something like that.
 

MMcLaren

Joined Feb 14, 2010
861
Mmm, so it may appear ive wasted 20 hours or so on this one simple problem ...
Another reason to learn how to use the MPLAB simulator and 'watch' window. I found the problem in my program in about 30 seconds. I was watching several variables as well as PORT1 and TMR1 and I put a breakpoint on the first instruction in the ISR. When I hit the "run" button and after the program stopped in the ISR I noticed that TMR1 had not been reset to 0x0000.

P.S. How do I post code with correct spacing? Can you post the code with the Tabs and such in place, straight from MPLAB? Mine comes in all messed even with code tags. And I suspect the font type is wrong. Verdana or something like that.
I've had problems with tabs in code on several different forums so I wrote a simple BASIC program to copy a file line-by-line to the console while replacing tab characters with spaces.

Rich (BB code):
'
'  Forum Code-Tag-Fix v1.1 by Mike McLaren, K8LH
'
'  replaces <tab> characters with spaces (tabs = 8).  adds
'  an additional space character to lines beginning with a
'  space for Microchip Forum.  does not alter source file.
'
'  Instructions
'
'  1 - select your source file from the File Dialog
'  2 - select output text displayed in console window
'  3 - copy to clipboard using <ctrl-C> or <edit> <copy>
'  4 - paste between code tags in your Forum post
'
'  JustBASIC v1.01 (free version)
'
   tabs = 8       ' 8 (assembly) or 4 (C)
   postmode = 0   ' 1, replace tabs, add leading space
                  ' 0, replace tabs only

   filedialog "Source File?", "*.asm", fileName$

   if fileName$ <> "" then
     open fileName$ for input as #f
     while eof(#f) > -1
       line input #f, aLine$ : hpos=1
       if postmode then
         if (left$(aLine$,1)=" ") then print " ";
         if (left$(aLine$,1)=chr$(9)) then print " ";
       end if
       for x = 1 to len(aLine$)
         if (mid$(aLine$,x,1)<>chr$(9)) then
           print mid$(aLine$,x,1); : hpos=hpos+1
         else
           while hpos MOD tabs <> 0
             print " "; : hpos=hpos+1
           wend
           print " "; : hpos=hpos+1
         end if
       next x
       print
     wend
     close #f
   end if
   end
 
Last edited:

Thread Starter

MCrowe

Joined May 29, 2011
69
I tried the simulator, I really did... But i couldn't figure it out. At least not enough to help. I think the thing I was missing was the 'watch' window. I had it running (simulating) but it spent so long in loops routines I would get sick of waiting and couldn't figure out how to advance it out of the loop. Also it didn't appear to run Interrupts, but maybe that was just me not waiting long enough.

I guess I should put a bit more effort into figuring out the Simulator. At the moment im just using a bank of light (8 bits) and also a subroutine that send a character to Hyperterminal. oh and a multimeter of course. It amazing what you can diagnose by sending different character to hyperterminal at specific points in your program.

Any way, as I said, I figured out what was wrong with your program. At least the 'special function mode thing' but even though I checked everything else it still wasn't working. I now suspect it was hardware related. Oh well. At least things are moving again.
 

Markd77

Joined Sep 7, 2009
2,806
You will probably find breakpoints useful. Just double click to the left of the line of code and it will stop there when you press run.
 

Thread Starter

MCrowe

Joined May 29, 2011
69
You will probably find breakpoints useful. Just double click to the left of the line of code and it will stop there when you press run.
Yo, got it. I will give that a try next time I get stuck. I remember seeing that but wasn't sure what it did.. And the simulator still does interrupts and such? and by 'and such', I really just mean interrupts.
 

Markd77

Joined Sep 7, 2009
2,806
It works fine for the interrupts I've used, I'm not sure if there are any exceptions.

Another useful thing if you are stepping through code one line at a time is the "step over". If you click that or press F8 when you are on a line like "call delay" then it just goes to the next line (delay is executed, just quickly). "step out" does a similar thing if you are already in the delay.
 
Top