ACCURATE PWM METER - GREAT FOR TESTING SERVO SIGNALS

General discussion on mikroBasic.
Author
Message
xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

ACCURATE PWM METER - GREAT FOR TESTING SERVO SIGNALS

#1 Post by xor » 17 Jun 2008 05:24

The following code is a PWM Meter with a 2x16 LCD output which can display PWM Frequency, PWM DutyCycle in Percent, PWM Period in microseconds, and DutyCycle Period in microseconds.

It compiles to approx. 1700 words, making it a nice project that works with the free version of the compilers. The demo project was tested with a 16F877A, but will work nicely with a 18-pin 16F628A.

It is very accurate compared with commercial test instruments. Photos below.

Image
Image
Image

Code: Select all

'*******************************************************************************
'*******************************************************************************
'
'          SERVO PWM_METER USING 16F877A @ 8MHz; EasyPIC4 And 16x2 LCD
'           Displays PWM Period/Duty-Period And Frequency/Duty-Percent
'                  LCD Screen Toggles Using PORTA.0 Pushbutton
'
'    Code Compiled with mikroBasic 7.2 for 16F877A @ 8MHz & Default Configs
'                   by Warren Schroeder on June 15,2008
'
'       Demonstrates Use Of Input Capture Feature of CCP1 On Pin RC2
'
'*******************************************************************************
'*******************************************************************************

Const  Capture_RE as Byte = 5                    ' CCP1CON Value For Rising Edge
Const  Capture_FE as Byte = 4                    ' CCP1CON Value For Falling Edge

Dim    CCPR1      as Word Absolute $15 Volatile  '  CCPR1 location
Dim    Period     as Word                        '  Rising Edge to Rising Edge value
Dim    StartEdge  as Word                        '  First Rising Edge Timer1 value
Dim    DCEdge     as Word                        '  Falling Edge Timer1 value
Dim    DutyCycle  as Word                        '  Rising Edge to Falling Edge value
Dim    RisingEdge as Boolean                     '  Switch Edge Detection Flag
Dim    LCDOUT     as Boolean                     '  Switch LCD Screen Flag
dim    t0         as LongWord                    '  temp var
Dim    PerStr     as String[6] Absolute $20      '  Period String for LCD
Dim    DCStr      as String[6] Absolute $26      '  Duty Cycle String for LCD


sub procedure interrupt                          ' ISR to manage edge detection

    If RisingEdge Then
        CCP1CON   = Capture_FE                   ' set up to detect next edge
        StartEdge = CCPR1
        Period    = CCPR1 - DCEdge + DutyCycle
    Else
        CCP1CON   = Capture_RE                   ' set up to detect next edge
        DCEdge    = CCPR1
        DutyCycle = CCPR1 - StartEdge
    End If
    RisingEdge    = Not(RisingEdge)               ' toggle edge detection flag
    PIR1.CCP1IF   = 0                             ' clear CCP1 interrupt flag
    
end sub

sub procedure CCP_Setup()

    T1CON        = 16                            ' Timer1 prescaler = 2 = 1us
    CCP1CON      = Capture_RE                    ' RC2 is CCP1 Capture Input
    TRISC.2      = 1                             ' Tris RC2 as Input
    PIE1.CCP1IE  = 1                             ' Enable CCP1 interrupt
    PIR1.CCP1IF  = 0                             ' Clear CCP1 Interrupt Flag
    INTCON       = 192                           ' Global & Peripheral interrupts enabled
    T1CON.TMR1ON = 1                             ' Start Timer1
    
end sub

sub procedure AddDec(dim byref lcdstr as string[6])  ' Adds decimal to LCD output string
    dim t1,t2,t3 as byte
    FSR = @lcdstr
    t1 = INDF
    inc(FSR)
    t2 = INDF
    inc(FSR)
    t3 = INDF
    INDF = 46
    dec(FSR)
    INDF = t3
    dec(FSR)
    INDF = t2
    dec(FSR)
    INDF = t1
end sub

sub procedure LCD_Output_Manager()               ' manage LCD screen output between
    LCD_OUT(2,1,"                ")              '   Period/Duty-Period and
    If LCDOUT  Then                              '   Frequency/Duty-Percent
       LCD_OUT(1,1,"FREQUENCY  DUTY ")
       t0 = 100000000 div Period
       WordToStr(t0, PerStr)
       t0 = DutyCycle * 10000 div Period
       WordToStr(t0, DCStr)
       AddDec(PerStr)
       LCD_OUT(2,2,PerStr)
       LCD_OUT_CP("hz")
       AddDec(DCStr)
       LCD_OUT(2,11,DCStr)
       LCD_CHR_CP("%")
    Else
       LCD_OUT(1,1," PERIOD    DUTY ")
       WordToStr(Period, PerStr)
       LCD_OUT(2,1,PerStr)
       LCD_OUT_CP("us")
       WordToStr(DutyCycle, DCStr)
       LCD_OUT(2,10,DCStr)
       LCD_OUT_CP("us")
    End If
end sub
main:

    ADCON1     = 6                          ' disable adc's
    CMCON      = 7                          ' disable comparators
    PORTA      = 0
    PORTB      = 0
    PORTC      = 0
    PORTD      = 0
    TRISA      = 1                          ' RA0 is switch input pulled low active high
    TRISB      = 0
    TRISC      = 0
    TRISD      = 0
    RisingEdge = False
    LCDOUT     = False
    Period     = 0
    DutyCycle  = 0
    StartEdge  = 0
    DCEdge     = 0
    
    LCD_INIT(PORTD)
    LCD_CMD(LCD_CURSOR_OFF)
    CCP_Setup()
    
    While 1=1
       Delay_ms(100)                         ' LCD screen refresh delay
       LCD_Output_Manager()
       If PORTA.0 = 1 Then                   ' RA0 Button Manager;  If 1 Then....
           LCDOUT=NOT(LCDOUT)                ' toggle LCD Ouput Flag
           LCD_Output_Manager()              ' toggle LCD Screen
           While PORTA.0 = 1                 ' If RA0 still pressed then wait
              Delay_ms(5)                    '    until released
           Wend
       End If
    Wend
    
end.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

trust issues
Posts: 231
Joined: 14 Nov 2004 19:43

#2 Post by trust issues » 17 Jun 2008 09:35

Thanks Warren. Another great project to add to my computer :D

Have you tested the range of minimum and maximum PWM signals the software can calculate successfully/accuratly?

Charlie
Posts: 2744
Joined: 01 Dec 2004 22:29

#3 Post by Charlie » 17 Jun 2008 13:29

Thanks xor,

Another great project to add to the archives.
Regards Charlie M.

Copy'nPaste
Posts: 573
Joined: 25 Apr 2006 15:39
Location: Cape Town, South Africa

#4 Post by Copy'nPaste » 17 Jun 2008 15:43

Jeez xor, you do have the gift to make me see how little I know :oops:
One thing, most modern RC RX's use 3V tech, and that just doesn't trigger a 5V pic reliabily.
A single transistor before the pic would boost the waveform to 5V, but now you need to read the lows for the position pulses, and the highs for the period........
"Copy'nPaste"

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#5 Post by xor » 17 Jun 2008 16:55

Copy'nPaste wrote:Jeez xor, you do have the gift to make me see how little I know :oops:
One thing, most modern RC RX's use 3V tech, and that just doesn't trigger a 5V pic reliabily.
A single transistor before the pic would boost the waveform to 5V, but now you need to read the lows for the position pulses, and the highs for the period........
You can operate the PIC at 3V. Especially at low oscillator speeds of 4-8MHz. The example above is 8MHz, but easily changed to work at 4MHz.

The LCD might be a problem at 3V... but there are plenty of 3V models around now.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#6 Post by xor » 17 Jun 2008 17:24

trust issues wrote:Have you tested the range of minimum and maximum PWM signals the software can calculate successfully/accuratly?
No, I didn't test it over a great range. I developed it to easily test servo code output, mostly intended for those hobbyist without good test equipment.

A 16F628A running on the internal 4Mhz oscillator and a cheap 16x2 LCD is perfect for this application. $5 in parts and a free compiler and you've got an excellent compact test instrument.

I think that you can expect reliable PWM readings from 15Hz- 10KHz+. The resolution is excellent at 1us, but the PIC clock is "slow". While the timing mechanisms are very good, the internal code is relatively slow running and at high frequencies can begin to show signs of blocking or other problems.

Operating the PIC16 @20Mhz, or using a PIC18 at high-speed, can increase the range if you wanted to develop a more serious meter, including adding multiple ranges.
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

Philtkp
Posts: 307
Joined: 26 Apr 2006 00:58
Location: Tucson Arizona

#7 Post by Philtkp » 17 Jun 2008 18:42

Cant wait to try this out :D

Great work Warren (as always) . Now i can really see what some of my servos are doing (some are questionable).
I was just using a simple circuit with a 555 to test rotation and set to center

Thanks
Phil

Philtkp
Posts: 307
Joined: 26 Apr 2006 00:58
Location: Tucson Arizona

#8 Post by Philtkp » 18 Jun 2008 06:16

Warren,
This is sweet. only .01 difference between my meter and the LCD display

-Tested using my 555 circuit Frequency was 46.87Hz
-Tested using My USB contoller board. Frequency was 30.35Hz :shock:
I Need to look into that :oops:

Thanks
Phil

Philtkp
Posts: 307
Joined: 26 Apr 2006 00:58
Location: Tucson Arizona

#9 Post by Philtkp » 21 Jun 2008 06:52

Got the frequency from 30.35 to 49.99 by changing
TMR0H = Hi(-3774) ' load balance of 20ms in Timer0...high byte first
TMR0L = -3774

to
TMR0H = Hi(-2155) ' load balance of 20ms in Timer0...high byte first
TMR0L = -2155


Thanks for this tool XOR :D

Mancrius
Posts: 54
Joined: 13 Jul 2008 16:38

#10 Post by Mancrius » 16 Jul 2008 19:20

Hi Xor,

I was studying the code and I have a question...

If the frequency is about 1Hz, will the CCPR1 overflow the register ?

In fact I think it could happen if frequency is lower than 1/65536e-6 = 15,25Hz...

Am I right !? so what happen ?


Mancrius

xor
Posts: 5465
Joined: 18 May 2005 00:59
Location: NYC
Contact:

#11 Post by xor » 17 Jul 2008 00:39

Mancrius wrote:Hi Xor,

I was studying the code and I have a question...

If the frequency is about 1Hz, will the CCPR1 overflow the register ?

In fact I think it could happen if frequency is lower than 1/65536e-6 = 15,25Hz...
Am I right !?
Yes, I believe that's in the neigborhood.
so what happen ?
  • The bicycle is free. The Ferrari is not.... :roll:
[color=darkred][b]xor[/b][/color]
[url=http://circuit-ed.com]CircuitED -[/url]

Its_Alive
Posts: 27
Joined: 01 May 2008 20:46

#12 Post by Its_Alive » 23 Sep 2008 17:29

Hi and thanks for code.
Can anybody tell me what I need to change to make this work on a easypic 5 board. Thanks in advance for any help.

rverm
Posts: 135
Joined: 18 Nov 2007 04:16
Location: sunny florida

#13 Post by rverm » 24 Sep 2008 00:05

what change need to be made to run it on a 18242? i would like to try this in the vsm simulator software.

Charlie
Posts: 2744
Joined: 01 Dec 2004 22:29

#14 Post by Charlie » 25 Sep 2008 01:30

Hi Warren,

I am trying it on a EP4 with a LCD adapter and am not getting anything on the display.Any thoughts?
Regards Charlie M.

Philtkp
Posts: 307
Joined: 26 Apr 2006 00:58
Location: Tucson Arizona

#15 Post by Philtkp » 25 Sep 2008 01:36

Are you using a 16f877A? and which port are you using for the LCD

Post Reply

Return to “mikroBasic General”