| CODE |
'$regfile "m163def.dat" $regfile "8535def.dat" $crystal = 8000000 ' ' Gyro balance bot ' $include "arc_10.bas" Declare Function Limit9bit(byval Value As Integer) As Integer Dim Angle As Integer Dim Rate As Integer Dim Iangle As Integer Dim Velocity As Integer Dim Old_position As Integer Dim Temp As Integer Dim Servo_integral As Integer Dim Torque As Integer Dim Rate_offset As Integer Dim Ivelocity As Integer Dim Velocity_err As Integer Dim Velocity_sp As Integer ' ' Rate gyro output is 8.518 counts/deg/sec. Divide this by Tau (or multiply by ' servo loop rate in hz) to get #counts per degree angular displacement. ' Const Init_rate_offset = 564 ' initial value Const One_degree = 426 ' 8.517 / 20 ms Const One_tenth_deg = 43 ' Const Kgyro_offset = 1500 ' Rate which we adjust gyro offset Const Kvelocity = -10 ' Wheel velocity feedback Const Krate = -1 ' Rate term Const Kangle = -5 ' angle term Const Kscale = 20 ' scaling factor. ' ' Initialize Hardware ' Config Adc = Single , Prescaler = Auto Start Adc 'Turn on power to ADC ' Config Timer0 = Timer , Prescale = 256 Const Timer0_reload = 256 - 25 ' Reload value to get 1250hz interrupt rate. On Timer0 Timer0_isr ' Our timer interrupt hanlder Enable Timer0 Enable Interrupts ' Config Pinb.4 = Output ' LED for winkie ' Call Initialize_pwm() Call Initialize_encoder() ' Dim Main_timer As Byte , Led As Integer , Velocity_timer As Integer Rate_offset = Init_rate_offset Velocity_sp = 0 Wait 1 ' Do Temp = Left_encoder() Velocity = Temp - Old_position Old_position = Temp Velocity_err = Velocity_sp - Velocity Ivelocity = Ivelocity + Velocity_err ' velocity error (future) ' Print Ivelocity Rate = Getadc(left_sharp) Rate = Rate - Rate_offset Iangle = Iangle + Rate Angle = Iangle / One_tenth_deg ' Temp = Ivelocity / Kgyro_offset ' Temp = Temp / 256 ' Rate_offset = Rate_offset + Temp ' correct gyro drift Torque = Iangle * Kangle Temp = Rate * Krate Torque = Torque + Temp Temp = Velocity_err * Kvelocity Torque = Torque + Temp Torque = Torque / Kscale Torque = Limit9bit(torque) Temp = Abs(angle) If Temp > 150 Then Torque = 0 ' stop if angle exceeds 15 deg Call Set_left_motor_pwm(torque) Call Set_right_motor_pwm(torque) ' ' State machine to flash LED at 1 hz. Note: the main loop code can use ' the value of Sys_timer to measure out time in 8 ms increments. ' Incr Led If Led = 5 Then Prog_led = 0 'enable low output (ON) Elseif Led = 50 Then Prog_led = 1 'disable output (OFF) Led = 0 'reset timer End If ' While Main_timer > 0 Idle Wend Main_timer = 25 'reset timer to 20 ms (50 hz) Loop Timer0_isr: ' ' The reload value for the timer is calculated, above, for a precise .8 ms ' overflow (e.g. 25 ticks). Since the interrupts may be turned off during ' overflow, the timer might increment a count or two. To account for this ' and maintain precise timing we read the current value of the counter and ' adjust the reload value by that amount. ' Timer0 = Timer0_reload + Timer0 'reload timer adjusted for overflow If Main_timer > 0 Then Decr Main_timer 'Count down main loop timer. End If Call Doencoder Return ' ' Limit value to +/- 255 for 9 bit PWM ' ' limit to some lower number to preserve H-Bridge when things oscillate. ' Function Limit9bit(byval Value As Integer) As Integer If Value > 150 Then Limit9bit = 150 Elseif Value < -150 Then Limit9bit = -150 Else Limit9bit = Value End If End Function $include "arc_10_pwm.bas" $include "arc_10_polled_encoder.bas" End 'end program |