hi Darrel,
i found a good code for controlling 8 servo motors and i tried it.
its very awsome and it contains a pc sofware too.
unfortunatily, it is written in mokrobasic and it contains some assembly codes.
since i m new to pic microcontrollers and i use only PBP, i didnt understand the code and its procedure.
i wish i can understand it so i can make my own code using PBP and microcode studio. and also to programm my own vb software.
could u explain this code and how it define 20ms periods.. etc.
u can find attached the full folder containing pc software and also pic firmware.
here is the code:
Code:
program SERVO8_USB_18F2550
'******************************************************************************************
'* 18F2550 PIC USB_HID 50Hz PWM SERVO CONTROLLER *
'* by W. Schroeder alias "xor" -- July 4, 2006 *
'* *
'* Compiles with mikroBASIC 4.03 and tested on the EasyPIC3 Development Board *
'* Uses mikroBASIC USB_HID Library and must include "USBdsc.pbas" and "HIDconstant.pbas" *
'* *
'* Also required is the free Visual Basic Servo Controller Demo program included with *
'* this file. This program has been tested on Windows XP with USB2.0. *
'* * *
'* Configuration settings for the 18F2550 are the same as the mikroBASIC 18F2550 HID *
'* example found in the mikroBASIC Examples folder in the mikroBASIC directory. *
'* These configurations are set up for an 8MHz crystal oscillator and through internal *
'* PLL settings this is increased to 48MHz. This also produces a very fast 12 MIPS. *
'* *
'* The EasyPIC3 board provides an easy connection to the PIC via a USB port. Please *
'* refer to the board schematic for ideas for your own circuit connections. *
'* *
'* For the purposes of this demo all output pins of PORTB are utilized. *
'* Servo0 is PORTB.0, Servo1 is PORTB.1, ......, Servo7 is PORTB.7 *
'* *
'* The range of PWM on-time is 800us to 2200us analogous with a resolution of 0 to 255 *
'* A value of 127/128 is considered 50% of servo rotation with an on-time of 1500us *
'* Timer0 in 16-bit mode is used to establish an accurate 20ms (50Hz) PWM interval *
'* *
'******************************************************************************************
'******************************************************************************************
include "USBdsc" ' this module must be included in the same folder as the main program
dim T0 as word absolute $FD6
dim old as byte
dim servoport as ^byte
dim _s0,_s1,_s2,_s3,_s4,_s5,_s6,_s7 as byte
dim
wrbuf as byte[2]
servo as byte[9]
wr_adr as word
sub procedure delay_810us
delay_us(810)
end sub
sub procedure interrupt
If INTCON.TMR0IF = 1 Then ' if 20ms interval
servoport^ = 255 ' turn on all servos
_s0 = servo[0] + 1 ' set up temp variables
_s1 = servo[1] + 1
_s2 = servo[2] + 1
_s3 = servo[3] + 1
_s4 = servo[4] + 1
_s5 = servo[5] + 1
_s6 = servo[6] + 1
_s7 = servo[7] + 1
old = 0
FSR0L = servoport
FSR0H = hi(servoport)
delay_810us ' this delay to hold position 0
TMR0L = 0
For old = 0 to 255 ' manage 8 outputs with 256 positions each
ASM ' very efficient PWM masking routine
movlw 0
decfsz main_global__s0, 1,0
iorlw 1
decfsz main_global__s1, 1,0
iorlw 2
decfsz main_global__s2, 1,0
iorlw 4
decfsz main_global__s3, 1,0
iorlw 8
decfsz main_global__s4, 1,0
iorlw 16
decfsz main_global__s5, 1,0
iorlw 32
decfsz main_global__s6, 1,0
iorlw 64
decfsz main_global__s7, 1,0
iorlw 128
andwf INDF0, 1,0
END ASM
While TMR0L = old ' wait until TMR0 increments
Wend
Next old ' all outputs are off at this point
T0= -3600 ' balance of time for 20ms cycle
INTCON.TMR0IF = 0 ' be ready to interrupt again for next interval
Else
HID_InterruptProc
End If
end sub
sub procedure Init_Main
INTCON2 = 0xF5
INTCON3 = 0xC0
RCON.IPEN = 0 ' disable Priority Levels on interrupts
PIE1 = 0 ' clear all interrupt enables
PIE2 = 0
PIR1 = 0
PIR2 = 0
ADCON1 = 15 ' digital IO
TRISA = 0
TRISB = 0
TRISC = 0
LATA = 0
LATB = 0
LATC = 0
end sub
sub procedure SERVO8_INIT(dim byref servo_port as byte,
dim port_config as byte)
servoport = @servo_port + 18 ' PORT TRIS ADDRESS
servoport^ = servoport^ And Not(port_config) ' SET TRIS
servoport = servoport - 9 ' PORT OUTPUT LATCH ADDRESS
T0CON = %00000101 ' prescaler = 64 or ~5us per increment
T0 = -4000 ' preset for 20ms
INTCON = %10100000 ' Timer0 Interrupt Enabled and Flag Cleared
T0CON.7 = 1 ' Timer0 On
end sub
main:
Init_Main
SERVO8_INIT(PORTB, 255)
HID_Enable(@servo, @wrbuf) ' @servo is equivalent to the Read_Buffer
Delay_mS(1000)
while true
If HID_READ <> 0 Then ' if USB package has arrived...servo positions are in Read_Buffer
wrbuf[0] = 255 ' 255 is verification value
HID_WRITE(@wrbuf, 1) ' reply to host with verification
End If
wend
HID_Disable
'** This code is necessary in order to make linker load the variables and HID_InterruptProc routine.
'** In real time it will never execute.
if false then
HID_InterruptProc
wr_adr = @DeviceDescr
wr_adr = @ConfigDescr
wr_adr = @InterfaceDescr
wr_adr = @HID_Descriptor
wr_adr = @EP1_RXDescr
wr_adr = @EP1_TXDescr
wr_adr = @HID_ReportDesc
wr_adr = @LangIDDescr
wr_adr = @ManufacturerDescr
wr_adr = @ProductDescr
wr_adr = @StrUnknownDescr
end if
end.
Bookmarks