Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
November 28, 2024, 04:50:31 16:50


Login with username, password and session length


Pages: [1]
Print
Author Topic: PIC based PPM (1-2ms servo signal) and PWM (variable frequency and DC)  (Read 4325 times)
0 Members and 1 Guest are viewing this topic.
thunderer
Junior Member
**
Offline Offline

Posts: 61

Thank You
-Given: 19
-Receive: 69


I try to be patient


« on: December 29, 2014, 01:46:48 01:46 »

It is based on a 12F617 (8 pin) PIC. It is a test tool, not a precision one. Some fellow shown some interest, so I said maybe others will be interested too.

The PIC reads 3 potentiometers (5-10kohm - not shown in the schematics but represented as 3 pin pinheads) and adjusts the PPM between 1 and 2ms (servo signal 5V), frequency (fixed frequencies from 500Hz to 200kHz - see code below), while the DC is from 0 to 100% depending on your potentiometer (you may put a multiturn for better accuracy - remember, we have 255 steps for DC).

The code is as follows:
Code:
program PPM_testbank

' Declarations section
dim adc0, adc1, adc3, count, i, PWMfreq_out   as word
dim PWMDC_out, state                          as byte
dim PPM_out                                   as longword

'   Set-up the PIC
sub procedure InitMain()
    OPTION_REG =   0x80              ' Pull-up disabled PORTB
    INTCON     =   0x00              ' No interrupt
    CMCON0     =   0x00              ' No COMP
    CCP1CON    =   0x0C              ' P1A (GP2) PWM
    ANSEL      =   0x0B              ' AN on GP0,1&4

    TRISIO     =   0x1B              ' GP2,5 outputs, rest of them inputs

    GPIO       =   0x00              ' Clear GPIO
end sub


'   Main program
Main:
  InitMain()
  ADC_Init()
  PWM1_Init(500)
  PWM1_Start()
  PWMDC_out = 127

  GPIO.5 = 0
  
  status = 1

Measure:
  while (TRUE)
' PPM master pot measurement
    adc3= ADC_read(3)
    count = 1000 + adc3 * 0.97752

    PPM_out = count * 0.026429

    for i = 1 to PPM_out
        GPIO.5 = 1
    next i
    GPIO.5 = 0
    Delay_ms(16)

' PWM DC% pot measurement
    adc1= ADC_read(1)
    PWMDC_out = adc1 * 0.097752 * 2.55
    
' PWM frequency pot measurement
    adc0= ADC_read(0)
    PWMfreq_out = adc0

    if PWMfreq_out < 100 then
       PWM1_Stop()
       PWM1_Init(500)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if
    
    if (PWMfreq_out >= 100) and (PWMfreq_out <= 200) then
       PWM1_Stop()
       PWM1_Init(1000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if

    if (PWMfreq_out >= 200) and (PWMfreq_out <= 300) then
       PWM1_Stop()
       PWM1_Init(2000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if
    
    if (PWMfreq_out >= 300) and (PWMfreq_out <= 400) then
       PWM1_Stop()
       PWM1_Init(3000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if

    if (PWMfreq_out >= 400) and (PWMfreq_out <= 500) then
       PWM1_Stop()
       PWM1_Init(4000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if
    
    if (PWMfreq_out >= 500) and (PWMfreq_out <= 600) then
       PWM1_Stop()
       PWM1_Init(5000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if

    if (PWMfreq_out >= 600) and (PWMfreq_out <= 700) then
       PWM1_Stop()
       PWM1_Init(10000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if

    if (PWMfreq_out >= 700) and (PWMfreq_out <= 800) then
       PWM1_Stop()
       PWM1_Init(20000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if
    
    if (PWMfreq_out >= 800) and (PWMfreq_out <= 900) then
       PWM1_Stop()
       PWM1_Init(50000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if

    if (PWMfreq_out >= 900) and (PWMfreq_out <= 1000) then
       PWM1_Stop()
       PWM1_Init(100000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if
    
    if PWMfreq_out > 1000 then
       PWM1_Stop()
       PWM1_Init(200000)
       PWM1_Start()
       PWM1_Set_Duty(PWMDC_out)
    end if

  wend

end.
« Last Edit: December 29, 2014, 01:48:50 01:48 by thunderer » Logged

Interested and hopefully helpful in: DC brushed motor control (mainly R/C - PPM/PWM), analog audio, PIC (mikrobasic PRO). Feel free to ask, and if I can, I will help. But only on forum topics, any started private conversation will continue in a public topic.
Signal
Active Member
***
Offline Offline

Posts: 200

Thank You
-Given: 113
-Receive: 81



« Reply #1 on: January 05, 2015, 12:38:43 12:38 »

... remember, we have 255 steps for DC ...

I do not remember such constraint for PIC12. Is it a specifics of used library?

I do remember though that BASIC is used in projects were you can allow yourself not to think about performance. So below is just my personal reaction on code that hurts my eyes.

Quote
    adc1= ADC_read(1)
    PWMDC_out = adc1 * 0.097752 * 2.55
I am sure that use of floating point arithmetic for integer conversion is not a reasonable solution. Especially for processor without FPU.
I suppose ADC_read() returns value from 0 to 1023 that you have to fit in byte variable PWMDC_out. Not arguing with this objective you can reach desirable result by one division by constant, that compiler should translate to simple shift (two rrf):
    PWMDC_out = ADC_read(1)/4

Quote
   adc3= ADC_read(3)
    count = 1000 + adc3 * 0.97752
    PPM_out = count * 0.026429
Here the range [0 1023] is converted to [26 52]. The same could be done by
    PPM_out = (1025 + ADC_read(3))*26/1024
or:
    PPM_out = 26 + (((ADC_read(3)/4)*27)/256) 'that could be processed mostly in 1-byte arithmetic.
Logged

Give a right name to a right game and play it right
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright © 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC