The second bit is that I rewrote the code for the microcontroller. Still having a lot of fun with it. I am actually very close to the code being at a truly testable stage. I am going to try and hook it up to a real servo soon to see if I get the results I am hoping for.
In the meantime, a new copy of the code. Main thing missing is a true randomization of the values of the servos.
I will continue to post the code as I develop it. I figure might be useful for someone else playing around with this stuff to have examples. Fun for me to show off as well... :) Here is the code up to this point.
;**********************************************************************
;
; Filename: MouthServos.asm
; Date: 6/14/2001
; File Version: v 0.5
;
;
;**********************************************************************
;
; Files required: P16F877.INC
;
;
;
;**********************************************************************
;
; Purpose:
; Program will drive a set number of servo motors. These servos
; will be moved to random locations for a duration of 1 to 3
; seconds. At that end of that period, they will move to a new
; location and the process repeats.
;
; Additional Info:
; Servo pulse: high pulse 1ms to 2ms in length determining servo position
; with a low pulse of approximately 40ms between high pulses.
;
; Completed:
; Servo array implemented (currently 2 elements but can be easily expanded up to expected 12)
; Init of servo array with preset values for new positions. randomizer not implemented yet.
;
; ToDo:
; Randomize new position and duration.
; Generate pulse based upon values.
;
;
;**********************************************************************
list p=16f887 ; list directive to define processor
#include; processor specific variable definitions
; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
__CONFIG _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
__CONFIG _CONFIG2, _WRT_OFF & _BOR21V
SERVOCOUNT EQU D'20'
MINTIMER EQU D'1000' ;smallest pulse for one end of servo positioning
MAXTIMER EQU D'2000' ;largest pulse for other end of servo positioning
TOTALTIMER EQU D'40000' ;max 40ms
; declare servo arrary
VARIABLES UDATA
;***************** Servo array start ****************
servo_start res 0
servo1_cycle res 1
servo1_duration res 1 ;server duration (value * 8) / 1000 = milliseconds
otherservos res 39 ;19 more servos
;***************** Servo array end ******************
temp_fsr res 1 ;used to swap out fsr
loop_count res 1 ;used in looping operations
first_time res 1 ;used to indicate first run through main loop
current_bit res 1 ;indicates current bit on current port to use
current_port res 1 ;indicates current port
debug_port res 1 ;used for debugging port problem, remove for final release
;**********************************************************************
RESET_VECTOR CODE 0x0000 ; processor reset vector
nop
goto start ; go to beginning of program
MAIN_PROG CODE
start
bsf first_time,0
bsf STATUS,RP0 ;move to bank 1
clrf TRISA ;set porta to all output
clrf TRISB ;set portb to all output
clrf TRISC ;set portc to all output
movlw b'00000010' ; configure Timer0. Time factor of x8
movwf OPTION_REG ; Maximum Prescaler
bsf STATUS,RP1 ;move to bank 3
clrf ANSEL ;set to digital instead of analog
clrf ANSELH
bcf STATUS,RP0 ;move to bank 0
bcf STATUS,RP1
BEGIN_PULSE
movlw b'00000001'
movwf current_bit ;set current bit to first bit.
movlw PORTA
movwf current_port ;starting port of A
movlw SERVOCOUNT
movwf loop_count ; loop for the number of servos we are using.
movlw servo_start ; start of the servo array
movwf FSR ; move the address into FSR
clrf T1CON
movlw 0x63 ;setup timer1 to lsat 40ms
movwf TMR1H
movlw 0xC0
movwf TMR1L
bsf T1CON,TMR1ON ;start the timer
bcf PIR1,TMR1IF ;clear the interuppt
BEGIN_SERVO_LOOP ;Do this for each servo
btfsc first_time,0 ;if first time, reset the servos
goto BEGIN_RESET_SERVO
decfsz INDF ;decrement the servo count. if not 0, skip to pulsing
goto BEGIN_PULSE_SERVO_HIGH
BEGIN_RESET_SERVO ;Its either first time or end of cycle, reset the servo to new duration and cycle
movlw d'32' ;set a new servo count TODO: Random value
movwf INDF
incf FSR
movlw d'187' ;move to center position of servo high byte TODO: Random value
movwf INDF
decf FSR
END_RESET_SERVO
BEGIN_PULSE_SERVO_HIGH
movf FSR,W
movwf temp_fsr ;save the fsr
movf current_port,W
movwf FSR ;FSR now has the correct port
movf current_bit,W
movwf INDF ;sets the appropriate bit. since only one servo is high at a time, no need to mask bits
movf temp_fsr,w
movwf FSR ;restore the FSR to point at servos
incf FSR ;move to the duration of the servo
movf INDF,W ;get the duration
sublw 0xFF ;max value of timer0
movwf TMR0 ;set the timer.
bcf INTCON,TMR0IF ;clear the flag interupt flag.
WAIT
btfss INTCON,TMR0IF ;is interupt set yet?
goto WAIT
incf FSR
END_PULSE_SERVO_HIGH
BEGIN_PULSE_SERVO_LOW
movf FSR,W
movwf temp_fsr ;save the fsr
movf current_port,W
movwf FSR ;FSR now has the correct port
clrf INDF ;pulse the port low
BEGIN_UPDATE_CHANNEL
;****** move to next channel (bit/port) for next servo
rlf current_bit
btfss STATUS,0 ;is carry bit set?
goto END_UPDATE_CHANNEL
bcf STATUS,0 ;clear the carry bit
incf current_port ;increment to the next port.
movlw b'00000001'
movwf current_bit ;reset to first bit.
END_UPDATE_CHANNEL
movf temp_fsr,W
movwf FSR ;restore the FSR to point at servos
END_PULSE_SERVO_LOW
decfsz loop_count,1 ;any servos left to process?
goto BEGIN_SERVO_LOOP
END_SERVO_LOOP
WAIT2
btfss PIR1,TMR1IF ;is interupt set yet?
goto WAIT2
bcf first_time,0
goto BEGIN_PULSE
END_PULSE
end
No comments:
Post a Comment