![]() | ![]() | ![]() |
| |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
![]() |
| | Tools |
| | #1 | |
|
Hey Guys, As you probably know, I'm VERY new to all this. I'm playing about with some digital R/C servos now which operate at 3mS wavelength (1 - 2ms high for full movement). I've managed to come up with some VERY crude and pretty much useless code that outputs the correct signal for 1.5mS high (followed by 1.5ms low). This 'should' centre a servo. However, I want to make something a bit more useful than this. Can anyone suggest a better way of going about generating a software PWM output that is actually useable in real life applications? Please see my current messy code below: Quote:
| ||
| |
| | #2 |
|
I posted this code a while ago, it reads a pot on RA3 and moves a servo on RB3 to match the pot. Servos normally require a pulse between 1 and 2mS every 20mS to operate. Mike. Code: ;###############################################################################
; Title: ADC, Servo Demo
; Author: Mike Webb
; Date: 21 Nov 2006
;################################################################################
include "p16f88.inc"
errorlevel -302 ; stop the annoying " Register in operand not in bank 0." error.
__config _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_ON & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
__config _CONFIG2, _IESO_OFF & _FCMEN_OFF
;Just for Mike McLaren, here's some psuedo C code.
;main{
; while(1){
; W=ReadADC()>>2; //get 8 most significant bits of ADC
; ServoOut=1; //Turn on output
; Delay8(250); //delay 1mS
; If(W!=0) //skip if ADC=0
; Delay8(W); //delay W*8 clock cycles = 0 to 1,03mS
; ServoOut=0; //Turn off output
; W=256-W; //calculate off time to make total 2mS
; if(W!=0) //Skip if zero
; Delay8(W); //delay to make 2mS
; For(x=0;x<18;x++){ //Repeat 18 times
; Delay8(250); //Delay 8*250 clock cycles = 1mS
; }
; }
;}
; Setup Variables
cblock 0x20
Count
OnTime
endc
org 0h
nop ; required for ICD2
bcf STATUS,RP1; bank 0 or 2
bsf STATUS,RP0; select bank 1
movlw (0<<NOT_RBPU|0<<INTEDG|0<<T0CS|0<<T0SE|0<<PSA|B'000'<<PS0)
movwf OPTION_REG; setup option reg
bcf TRISB,3 ; make b3 output
movlw B'111'<<IRCF0; =b'01110000'
movwf OSCCON; select 8MHz clock
movlw b'00001000'; Select bit 3
movwf ANSEL; ADC on RA3
bcf STATUS,RP0; back to bank 0
Loop Call ReadADC; read A3
movwf OnTime; Store it for later
movlw d'250'; 250*8 = 2000 cycles = 1mS
bsf PORTB,3; Turn output on
call DelayW; delay the 1mS
movfw OnTime; Get value from ADC
btfss STATUS,Z; if it's zero don't do any delay
call DelayW; delay W*8 = 0 to 255 = 0 to 1.03 mS -- near enough
bcf PORTB,3; Turn output off - pulse is complete
comf OnTime,W; Complement ADC value
addlw 1; com and inc = negate.
btfsc STATUS,Z; Don't do a delay of zero
call DelayW; delay (256-ADC value)*8 = time required to get to 2mS
movlw d'18'; We need to delay another 18mS
movwf Count; so setup a counter
TimeLoop movlw d'250'; 250*8 = 2000 clock cycles = 1mS
call DelayW; do the delay
decfsz Count,F; repeat it?
goto TimeLoop; yes, go around again
goto Loop; Go back and do it all again
DelayW
; will delay W*8 cycles including the call/return
addlw 0xff; add -1 to W 1
btfsc STATUS,Z; =zero? 1/2
goto DoneDelay; yes, better get out of here 2
nop; delay a bit 1
goto $+1; delay a bit more 2
goto DelayW; go around again 2
DoneDelay return ; 2
ReadADC movlw b'01'<<ADCS0|b'011'<<CHS0|b'0'<<GO|b'1'<<ADON
movwf ADCON0; select pin A3 and 16 TOSC
bsf STATUS,RP0; bank 1
movlw b'0'<<ADFM|b'1'<<ADCS2|b'00'<<VCFG0
movwf ADCON1; Left justify
bcf STATUS,RP0; back to bank 0
movlw 5; wait 5*8 = 40 cycles
call DelayW; for ADC capacitor to charge
bsf ADCON0,GO; Start the conversion
WaitADC btfsc ADCON0,GO; Conversion complete?
goto WaitADC; No, so keep waiting
movfw ADRESH; return with result in W
return
END
Last edited by Pommie; 17th January 2008 at 01:09 AM. | |
| |
| | #3 |
|
Thanks Mike, I'll have a look into it tonight and see if I can understand it all ![]() Many Thanks - Trev | |
| |
| | #4 |
|
Hi Guys, Had a closer look at my code, I've been timing 150us instead of 1500us, that's where my problem is . After very crudely altering the timing to 1500us high and 1500us low, the servo correctly centres.With most digital servos you can update them at 333fps. Which means that they can be sent a 'high' signal every 3ms whilst still using the 1ms - 2ms high pulse to control the positioning. Internally the gearing / motor / pot of the digital servos are the same, the only real difference is that they use a microprocessor in the digitals instead of the old custom logic chip. I have a 50MHz oscilloscope en route so that I can look into this a bit closer .Thanks - Trev | |
| |
| | #5 |
|
Mike (Pommie); Thanks for adding the pseudo C code just for me (grin). I had already figured out that you were using 256 steps of 4 usecs. I suspect it wouldn't be too much more difficult to rewrite it for 1 usec resolution, would it? Code: ;
;
; int Pot = 0; // 0..1023
;
; While(1)
; {
; Pot = ReadADC(); // 0..1023
; ServoOut = 1; //
; DelayUS(1500-(1024/2)+Pot); // 988..2011 usecs
; ServoOut = 0; //
; DelayUS(20000-tADC-988-Pot); //
; }
Thanks for the info' on digital servos. I had no idea you could drive them with a 3 msec Servo period. That's pretty cool... Regards, Mike | |
| |
| | #6 | |
| Quote:
This has reminded me, I must have another go at that multi servo problem from last year. Mike. | ||
| |
| | #7 |
|
I am new to microcontrollers. I am going to build my first project "Push button controlled PWM" using PIC12F675. I want to control the duty cycle of 100Hz pulse from 0-100%. Two pushbuttons, one for increment and another for decrement of duty cycle. Resolution required is in steps of 2%. Kindly help me with code. Don't have knowledge and experience of programming. Thx. ![]() ashwal.patel@gmail.com | |
| |
|
| Tags |
| asm, pwm, software |
| Thread Tools | |
| Display Modes | |
| |
Similar | ||||
| Title | Starter | Forum | Replies | Latest |
| Drive 33 Servos With One PIC + USART | wschroeder | Micro Controllers | 45 | 25th October 2008 10:10 AM |
| PIC PWM outputs? | Andy1845c | Micro Controllers | 33 | 30th November 2007 04:06 AM |
| PWM using software AtoD | jeremygaughan | Micro Controllers | 11 | 28th November 2007 12:11 AM |
| PIC16F877A TX data to PC via serial cable | derrick826 | Micro Controllers | 21 | 8th October 2007 02:28 PM |
| Breadboard design software? | ThermalRunaway | General Electronics Chat | 10 | 24th July 2005 01:35 PM |