'---------------------------------------------------------------------------
' _____ _ _ _ _ _ _ _ _ _
' | __| |___| |_| |_ ___ ___ | | | | |_ ___ ___| |_|___
' | __| | -_| '_| _| . | _| | | | | | -_| -_| | | -_|
' |_____|_|___|_,_|_| |___|_| |_____|_|_|___|___|_|_|___|
'
' (c)2009 Elektor International Media B.V.
'---------------------------------------------------------------------------
'Version: WOF104 - Elektor Wheelie Open Firmware 1.04
'---------------------------------------------------------------------------
'Purpose:
' Elektor-Wheelie motor control source code
'---------------------------------------------------------------------------
'Description:
' On power on the LEDs are flashing in the order green-yellow-red
' If initialization fails the red LED is blinking and the Wheelie is blocked.
' Blinking 2 times = gyro failure, 3 times = adxl failure.
' If initialization has been successful the 3 LEDs show the battery status:
' green = battery full, yellow = battery empty and red = battery dead.
'---------------------------------------------------------------------------'
'Older sources:
' FW 2.6: Original Elekor firmware version 2.6 by Chris Krohne 2009
' based on the AT3329 Project of Reinhold Pieper
'---------------------------------------------------------------------------'
'Changes Log:
' WOF100:
' Starting point for improvements from the community. Equivalent to beta.4.
' WOF101:
' foot switch: security brake before power down
' Bug in WOF100 removed
' WOF102:
' foot switch: timeout inserted
' faster Code in Algo, thanks Thomas Scherer
' Telemetry added again
' Speedsensors and I²C added
' Testmode Switch
' first Steps for steering Control
' WOF103beta:
' adxl and gyro * 10 to prevent rounding errors
' WOF103:
' Finetuning
' WOF104:
' Batteryvalues corrected. The resistor R10 must be changed from 68k to 100k!!!!
' more Staus and Errorinfos for Telemetry and Display
' Voltage to Telemetry and Display
' Bug in Speed measuring fixed
' Steering depends on Speed now
' Steering is corrected by the speeddifference of the wheels
' Wheelie II is supported now
' First Zzaag tests
'
'---------------------------------------------------------------------------'
'ToDo:
' Improvement of steering control (Zeroposition depends on geocentre)
' Speed limit (6km/h-Limit to switch on and off)
' emergency brake at a fall (analyse Switch, Tilt and Gyro)
'---------------------------------------------------------------------------'
'Contact:
' Please post ideas, improvements and code into this thread in the Elektor forum:
' http://www.elektor.de/forum/foren-ubersicht/foren-zu-elektor-projekten/elektorwheelie.996934.lynkx
' Günter Gerold: tv@gerold-online.de
'---------------------------------------------------------------------------
$crystal = 16000000
$baud = 57600
$regfile = "m32def.dat"
$hwstack = 50 'Hardware stack
$swstack = 50 'Software stack
$framesize = 50 'Frame space
'---------------------------------------------------------------------------
'Switches
'---------------------------------------------------------------------------
'#####################
Const Test_enable = 1 'Turn on and off the Testmode here! (0 or 1)
'#####################
'#####################
Const I2c_enable = 0 'Turn the I²C-Geartoothsensors on and off here! (0 or 1)
'#####################
'#####################
Const Rocker_enable = 0 'Turn the X-Axis on and off here! (0 or 1)
'#####################
'#####################
Const Wheelie = 1 'Wheelie = 1, zzaag = 0 (0 or 1)
'#####################
'---------------------------------------------------------------------------
'I2C Part
'---------------------------------------------------------------------------
#if I2c_enable = 1
$lib "i2c_twi.lbx"
Config Twi = 400000
Config Scl = Portc.5
Config Sda = Portc.4
Dim Speed_array(4) As Byte
Dim Speed_left As Word At Speed_array(1) Overlay
Dim Speed_right As Word At Speed_array(3) Overlay
Dim Speed_left_out As Integer
Dim Speed_right_out As Integer
Dim Speed_sum As Integer
Dim Speed_single As Single
Dim Speed_diff As Integer
Dim Speed_correction As Integer
Dim Speed_error As Integer
Declare Sub Gear
#endif
'---------------------------------------------------------------------------
'End I2C Part
'---------------------------------------------------------------------------
'---------------------------------------------------------------------------
'Start X-Axis Part
'---------------------------------------------------------------------------
#if Rocker_enable = 1
Dim Ad_adxl_r As Long
Dim Ad_gyro_r As Long
Dim Total_adxl_gyro_r As Long
Dim Average_gyro_r As Long
Dim Tilt_angle_r As Long
Dim Angle_rate_r As Long
Dim Buf_r As Long
Dim Adxl_zero_r As Word
Dim Gyro_zero_r As Word
Const Total_looptime_r = 20 ' Looptime for filters
Const Total_looptime10_r = 2 ' Looptime for filters
Declare Sub Get_rocker_angle
Dim Test As Long
#endif
'---------------------------------------------------------------------------
'End X-Axis Part
'---------------------------------------------------------------------------
Config Serialin = Buffered , Size = 40 , Bytematch = 13
Config Serialout = Buffered , Size = 40
Echo Off
Pwm_al Alias Ocr1al 'Pin 19 PWM to right Motordriver
Pwm_bl Alias Ocr1bl 'Pin 18 PWM to left Motordriver
Led3 Alias Portb.4 'red LED
Led2 Alias Portb.3 'yellow LED
Led1 Alias Portb.2 'green LED
Config Watchdog = 32
Ddra = &B00000000
Ddrb = &B00011100
Portb = &B11100011
Ddrc = &B00001000
Portc = &B11111111
Ddrd = &B11110000
Portd = &B00001111
'A complete A/D-conversion uses 13 ADC clock cycles.
'Because of prescaling (divider = 128) 1 cycle takes 104 µs
Config Adc = Single , Prescaler = 128 , Reference = Off
Start Adc
'Timer0 as a 8 bit timer triggers interrupt service routine Ontimer0 every 16,32ms (on overflow).
'To speed up the interrupt intervall Timer0 is preset to 100. Now counting from 100 to 255.
'=> Calcutulation: 155 x 1024 x 62,5 ns = 10 ms
Config Timer0 = Timer , Prescale = 1024
On Timer0 Ontimer0
'Timer1 is used to generate both PWM signals (backward and forward).
'One of them is inverted.
Tccr1a = &B10110001
Tccr1b = 1
Ocr1al = 255
Dim Cw_change_a As Bit
Dim Cw_change_b As Bit
Dim Cw_old_a As Bit
Dim Cw_old_b As Bit
Dim Ad_adxl As Long
Dim Ad_gyro As Long
Dim Ad_batt As Integer
Dim Ad_swi As Integer
Dim Total_adxl_gyro As Long
Dim Average_gyro As Long
Dim Average_batt As Long
Dim Drivea As Integer
Dim Driveb As Integer
Dim Buf1 As Long
Dim Buf As Long
Dim Buf2 As Long
Dim Tilt_angle As Long
Dim Drive_a As Integer
Dim Drive_b As Integer
Dim Drivespeed As Long
Dim Steeringsignal As Long
Dim Anglecorrection As Long
Dim Angle_rate As Long
Dim Balance_moment As Long
Dim Mmode As Byte
Dim Drive_sum As Long
Dim Ad_rocker As Integer
Dim Timeout As Long
Dim Rockersq As Long
Dim Rocker_zero As Integer
Dim Adxl_zero As Long
Dim Gyro_zero As Long
Dim Errno As Byte
'************* Wheelie Hardware *****************
#if Wheelie = 1
Const Ad_kanal_fuss = 7 ' AD Kanal Fußschalter
Const Ad_kanal_adxl = 3
Const Ad_kanal_gyro = 5
Const Ad_kanal_batt = 0
Const Ad_kanal_rocker = 6
Const Ad_kanal_rocker_adxl = 2
Const Ad_kanal_rocker_gyro = 4
15v_off Alias Portc.3
Cw_ccw_a Alias Portd.6 'Pin 20 Direction right Motordriver
Cw_ccw_b Alias Portd.7 'Pin 21 Direction left Motordriver
'***************** Wheelie hardware Ende ************
#else
'***************** Zzaag Hardware ************
Const Ad_kanal_fuss = 4 ' AD Kanal Fußschalter
Const Ad_kanal_gyro = 3
Const Ad_kanal_adxl = 1
Const Ad_kanal_batt = 6
Const Ad_kanal_rocker = 5
15v_off Alias Portd.2
Config 15v_off = Output
15v_off = 1
Cw_ccw_a Alias Portd.7 'Pin 20 Direction right Motordriver
Cw_ccw_b Alias Portd.6 'Pin 21 Direction left Motordriver
#endif
'**************** Zzaag Harware Ende ***************
Const Total_looptime = 150 ' Looptime for filters
Const Total_looptime10 = 15 ' Looptime for filters
Const _run = 1
Const _standby = 0
Const _down = 3
Const Sw_down = 50 'Thershold for foot switch
Const Critical = 100 'Time from releasing the foot switch until begin to stop the Wheelie
Const Max_pwm = 180 'Maximum motor power
Const Mmax_pwm = -180 'Maximum motor power
Const Battdead = 732
Const Battok = 762
Declare Sub Get_tilt_angle
Declare Sub Set_pwm
Declare Sub Algo
Declare Sub Process
Declare Sub Checkbatt
Declare Sub Err_value
Declare Sub Init
Declare Sub Steering
'---------------------------------------------------------------------------
'Telemetry Part
'---------------------------------------------------------------------------
Declare Sub Checkserinp
Declare Sub Parser
Const Mymainchannel = 0
Const Idenditaet = "WOF104"
Dim Serinpstr As String * 63
Dim Serinpbuffer As String * 63
Dim Serinbuffarr(5) As Byte At Serinpbuffer Overlay
Dim Mnemonicbuffer As String * 4
Dim Mnemonicbufferarray(5) As Byte At Mnemonicbuffer Overlay
Dim Cr_received As Byte
Dim Strsize As Byte
Dim Mainchannel As Byte
Dim Subchannel As Word
Dim Wert As Single
Dim Frage As Bit
Dim Zeichenpos As Byte
Dim Zaehler As Byte
Dim Statustext As String * 8
Dim Doppelpunkt As String * 1
Doppelpunkt = ":"
Dim Istgleich As String * 1
Istgleich = "="
'---------------------------------------------------------------------------
'End Telemetry Part
'---------------------------------------------------------------------------
Pwm_al = 255
Pwm_bl = 0
Average_batt = Battok
Mmode = _standby
'LEDshow on start
Set Led1
Waitms 150
Set Led2
Waitms 150
Set Led3
Waitms 250
Reset Led1
Reset Led2
Reset Led3
'---------------------------------------------------------------------------
'Checking foot switch:
' When the Wheelie is switched on the foot switch should be closed (not pressed down).
' Otherwise the Wheelie would start. Therefore the foot switch is read 10 times
' and the mean of this values is compared with a threshold of 100.
' If this mean is smaller than all is okay. Otherwise an error occurs..
'---------------------------------------------------------------------------
'wait while the sensors drifting at power on.
Enable Interrupts
Gosub Init
Stop Watchdog
Waitms 200
15v_off = 0
Ad_swi = 0
For Buf = 1 To 10
Ad_swi = Ad_swi + Getadc(ad_kanal_fuss)
Waitms 1
Next Buf
'calculate middel'
Ad_swi = Ad_swi / 10
Waitms 2
'must be closed
If Ad_swi < 100 Then
Errno = 4
Print "2:11=14"
Goto Err_value
End If
#if Test_enable = 0
Start Watchdog
Enable Timer0
Statustext = Idenditaet
'---------------------------------------------------------------------------
'Main Loop:
' serial Output of Telemetry Data to PC or Display
'---------------------------------------------------------------------------
Do
If Cr_received = 1 Then 'wenn was im ser. Buffer ist abholen
Cr_received = 0
Input Serinpstr
'zum Abtrennen eines oder mehrerer LF am Anfang des Strings, das noch vom Vorgänger-String im Buffer steht
While Asc(serinpstr) = 10
Strsize = Len(serinpstr) - 1
Serinpstr = Right(serinpstr , Strsize)
Wend
'Hier ist der String empfangen und ein event. LF entfernt
Call Checkserinp
End If
'Das Senden der Telemetriedaten ist noch verbesserungsfähig ;-)
Waitms 8
Print "2:1=" ; Str(tilt_angle)
#if Rocker_enable = 1
Waitms 8
Print "2:2=" ; Str(tilt_angle_r)
#endif
Waitms 8
Print "2:3=" ; Str(steeringsignal)
Waitms 8
Print "2:4=" ; Str(balance_moment)
#if I2c_enable = 1
Waitms 8
Print "2:5=" ; Str(speed_correction)
Waitms 8
Print "2:6=" ; Str(speed_error)
#endif
Waitms 8
Print "2:7=" ; Str(drive_a)
Waitms 8
Print "2:8=" ; Str(drive_b)
#if I2c_enable = 1
Waitms 8
Print "2:9=" ; Str(speed_left_out)
Waitms 8
Print "2:10=" ; Str(speed_right_out)
#endif
If Zaehler > 100 Then
Zaehler = 0
Print "2:11=" ; Statustext
End If
Waitms 8
Print "2:12=" ; Str(ad_batt)
Loop
#else
Do
Waitms 5000
Drive_a = 20
Gosub Set_pwm
Waitms 5000
Drive_b = 20
Gosub Set_pwm
Waitms 5000
Drive_a = 0
Gosub Set_pwm
Waitms 5000
Drive_b = 0
Gosub Set_pwm
Waitms 5000
Drive_a = -20
Gosub Set_pwm
Waitms 5000
Drive_b = -20
Gosub Set_pwm
Waitms 5000
Drive_a = 0
Gosub Set_pwm
Waitms 5000
Drive_b = 0
Gosub Set_pwm
For Buf = 1 To 1000
Ad_rocker = Getadc(ad_kanal_rocker)
Rockersq = Rocker_zero - Ad_rocker
Steeringsignal = Rockersq
If Steeringsignal > 2 Then
Drive_a = 30
Drive_b = 0
Gosub Set_pwm
End If
If Steeringsignal < -2 Then
Drive_b = 30
Drive_a = 0
Gosub Set_pwm
End If
Waitms 10
Next Buf
Drive_a = 0
Drive_b = 0
Gosub Set_pwm
Loop
#endif
'---------------------------------------------------------------------------
'Ontimer0:
' This service routine contains control logic and start every 10ms.
' Exact time: 1/16 MHz * 1024 * (255-100) = 9,92 ms
'---------------------------------------------------------------------------
Ontimer0:
Reset Watchdog
Timer0 = 100
Gosub Get_tilt_angle
#if Rocker_enable = 1
Get_rocker_angle
#endif
Gosub Algo
#if I2c_enable = 1
Gosub Gear
#endif
Gosub Steering
Gosub Process
Gosub Set_pwm
Gosub Checkbatt
Incr Zaehler
Return
'---------------------------------------------------------------------------
'Get_tilt_angle:
' Measurement of all analog values (5 values).
' Using 104 µs per measurement total time is 520 µs.
' The values are used to build moving averages.
'---------------------------------------------------------------------------
Sub Get_tilt_angle
Ad_gyro = Getadc(ad_kanal_gyro)
Ad_gyro = 1024 - Ad_gyro 'Inverted value for Ad_gyro
Ad_adxl = Getadc(ad_kanal_adxl)
Ad_batt = Getadc(ad_kanal_batt)
Ad_rocker = Getadc(ad_kanal_rocker)
Ad_swi = 1024 - Getadc(ad_kanal_fuss) 'Inverted value for Ad_swi
Ad_adxl = Ad_adxl * 10
Ad_gyro = Ad_gyro * 10
'Subtract 1/250th of the value
Buf = Total_adxl_gyro / Total_looptime
Total_adxl_gyro = Total_adxl_gyro - Buf
Buf = Ad_adxl - Adxl_zero 'Deviation from horizontal position
Total_adxl_gyro = Total_adxl_gyro + Buf 'A new 1/250th value is added
'Filter for gyro
Buf1 = Average_gyro / Total_looptime
Average_gyro = Average_gyro - Buf1 'Subtract 1/250th of the value
Average_gyro = Average_gyro + Ad_gyro 'A new 1/250th value is added
Buf1 = Average_gyro / Total_looptime10 'Calculation of angular rate
Buf = Ad_gyro * 10
Buf1 = Buf1 - Buf 'Deviation from zero
Buf1 = Buf1 * 30
Angle_rate = Buf1 / 100 '3.5 * deviation rate
'Calculation of Tilt_angle
'correct the Tilt_angle with the Average of the gyro.
'The ADXL-Lowpass Filter terminate all fast Peaks.
'The Angleratepart rebuilds the correct flanks in Tilt_angle
Total_adxl_gyro = Total_adxl_gyro + Angle_rate
Buf = Total_looptime10 * 10
Tilt_angle = Total_adxl_gyro / Buf
Angle_rate = Angle_rate / 10
End Sub
'---------------------------------------------------------------------------
'Get_rocker_angle:
' calculate the tiltangle for the rocker
' this is done in the same way as Get_tilt_angle
'---------------------------------------------------------------------------
#if Rocker_enable = 1
Sub Get_rocker_angle
Ad_adxl_r = Getadc(ad_kanal_rocker_adxl)
Ad_adxl_r = Ad_adxl_r * 10
'Subtract 1/250th of the value
Buf_r = Total_adxl_gyro_r / Total_looptime_r
Total_adxl_gyro_r = Total_adxl_gyro_r - Buf_r
Buf_r = Ad_adxl_r - Adxl_zero_r
Total_adxl_gyro_r = Total_adxl_gyro_r + Buf_r
Buf = Total_looptime_r * 10
Buf = Buf / 2.7
Tilt_angle_r = Total_adxl_gyro_r / Buf
If Tilt_angle_r > 35 Then Tilt_angle_r = 35
If Tilt_angle_r < -35 Then Tilt_angle_r = -35
Tilt_angle_r = Tilt_angle_r / 2
End Sub
#endif
'---------------------------------------------------------------------------
'Algo:
' Calculation of motor current out of sensor values.
'---------------------------------------------------------------------------
Sub Algo
Balance_moment = Tilt_angle + Anglecorrection
Balance_moment = Angle_rate + Balance_moment
Balance_moment = Balance_moment * 17
Drive_sum = Drive_sum + Balance_moment
If Drive_sum > 55000 Then 'Limiting Drive_sum
Drive_sum = 55000
End If
If Drive_sum < -55000 Then 'Limiting Drive_sum
Drive_sum = -55000
End If
Buf = Drive_sum / 155
Buf1 = Balance_moment / 165
Drivespeed = Buf + Buf1
End Sub
'---------------------------------------------------------------------------
'Steering:
' Calculation of steering values.
'---------------------------------------------------------------------------
Sub Steering
Rockersq = Rocker_zero - Ad_rocker
#if I2c_enable = 1
Buf1 = Speed_sum / 70 'Steering depends on speed (new and cool)
Buf1 = Abs(buf1)
If Buf1 > 15 Then Buf1 = 15
Buf2 = 30 - Buf1
Buf2 = Buf2 / 3
If Rockersq > 35 Then Rockersq = 35
If Rockersq < -35 Then Rockersq = -35
Rockersq = Rockersq * Buf2
Rockersq = Rockersq / 12
Speed_error = Rockersq - Speed_correction
If Speed_error > 30 Then Speed_error = 30
If Speed_error < -30 Then Speed_error = -30
Rockersq = Rockersq + Speed_error
#else
Buf1 = Drive_sum / 20000 'Steering depends on power (old and ugly)
Buf1 = Abs(buf1)
If Buf1 < 1 Then Buf1 = 1
Rockersq = Rockersq / Buf1
'Some safety lines, limits steering: Drive_sum 55000 max = +-5
Buf1 = Drive_sum / 2000
Buf1 = Abs(buf1)
If Buf1 > 22 Then Buf1 = 22
Buf1 = 27 - Buf1
Buf2 = Buf1 * -1
If Rockersq > Buf1 Then Rockersq = Buf1
If Rockersq < Buf2 Then Rockersq = Buf2
#endif
Steeringsignal = Rockersq
Drive_a = Drivespeed - Steeringsignal
Drive_b = Drivespeed + Steeringsignal
End Sub
'---------------------------------------------------------------------------
'Process:
' Processing Wheelie states.
' On standby delete all values, so the motors standing still
'---------------------------------------------------------------------------
Sub Process
Select Case Mmode
Case _standby 'Foot switch is released:wating...
Drive_a = 0
Drive_b = 0
Drivespeed = 0
Anglecorrection = 0
Drive_sum = 0
Tilt_angle = 0
Total_adxl_gyro = 0
Timeout = 0
Statustext = "Standby"
If Ad_swi > Sw_down Then 'If foot switch is pressed: change Mmode to run
Gosub Init 'Initialize sensors
Mmode = _run
Statustext = "Drive!"
Timeout = 0
End If
Case _run 'Foot switch is pressed: action...
If Ad_swi < Sw_down Then 'If foot switch is released change Mmode to down
Mmode = _down
End If
Case _down
Stop Watchdog
Timeout = 0
For Buf1 = 1 To 255
If Drive_a = 0 And Drive_b = 0 Then
Exit For
End If
If Drive_a > 0 Then Decr Drive_a
If Drive_a < 0 Then Incr Drive_a
If Drive_b > 0 Then Decr Drive_b
If Drive_b < 0 Then Incr Drive_b
Waitms 25 'Loop speed
Gosub Set_pwm
Next Buf1
Mmode = _standby
Statustext = "Standby"
Start Watchdog
Case Else 'If an unknown state occurs then slow down
Mmode = _down
End Select
End Sub
'---------------------------------------------------------------------------
'Set_pwm:
' Limiting PWM and set direction flags.
'---------------------------------------------------------------------------
Sub Set_pwm
'Limiting PWM
If Drive_a > Max_pwm Then
Drive_a = Max_pwm
Elseif Drive_a < Mmax_pwm Then
Drive_a = Mmax_pwm
End If
If Drive_b > Max_pwm Then
Drive_b = Max_pwm
Elseif Drive_b < Mmax_pwm Then
Drive_b = Mmax_pwm
End If
Cw_old_a = Cw_ccw_a
Cw_old_b = Cw_ccw_b
'Set direction flag
If Drive_a < 0 Then
Cw_ccw_a = 1
Else
Cw_ccw_a = 0
End If
If Drive_b < 0 Then
Cw_ccw_b = 1
Else
Cw_ccw_b = 0
End If
If Cw_old_a <> Cw_ccw_a Then
Set Cw_change_a
Else
Reset Cw_change_a
End If
If Cw_old_b <> Cw_ccw_b Then
Set Cw_change_b
Else
Reset Cw_change_b
End If
Drivea = Abs(drive_a)
Driveb = Abs(drive_b)
'Inverse signal with 180° phaseshift to PWMb
Pwm_al = 255 - Drivea
Pwm_bl = Driveb
End Sub
'---------------------------------------------------------------------------
'CheckBatt:
' Battery state (voltage) is signaled with the 3 LEDs.
'---------------------------------------------------------------------------
Sub Checkbatt
'Moving average of battery voltage
Buf1 = Average_batt / 300
Average_batt = Average_batt - Buf1
Average_batt = Average_batt + Ad_batt
Buf1 = Average_batt / 300
'Set the right LED
If Buf1 > Battok Then
Set Led1
Reset Led2
Reset Led3
End If
If Buf1 < Battok Then
Set Led2
Reset Led3
Reset Led1
End If
If Buf1 < Battdead Then
Reset Led2
Reset Led1
Set Led3
End If
End Sub
'---------------------------------------------------------------------------
'Init:
' Calibration: Calculation of steering mid and platform horizontal position.
'---------------------------------------------------------------------------
Sub Init
'Calculate mid position of steering (Steering_zero)
Stop Watchdog
Ad_rocker = 0
For Buf = 1 To 10 'Mean out of 10 values
Ad_rocker = Ad_rocker + Getadc(ad_kanal_rocker)
Waitms 1
Next Buf
Rocker_zero = Ad_rocker / 10
'Calculate gyro horizontal position of platform
Ad_gyro = 0
For Buf = 1 To Total_looptime
Buf1 = Getadc(ad_kanal_gyro)
Buf1 = 1024 - Buf1
Buf1 = Buf1 * 10
Ad_gyro = Ad_gyro + Buf1
Waitms 2
Next Buf
Gyro_zero = Ad_gyro / Total_looptime
Average_gyro = Ad_gyro 'Preset Average_gyro
'Calculate ADXL horizontal position of platform
Ad_adxl = 0
For Buf = 1 To 100 'Mean out of 100 values
Buf1 = Getadc(ad_kanal_adxl)
Ad_adxl = Ad_adxl + Buf1
Waitms 2
Next Buf
Adxl_zero = Ad_adxl / 10
#if Rocker_enable = 1
'Calculate gyro horizontal position of platform
Ad_gyro_r = 0
For Buf = 1 To Total_looptime_r
Buf1 = Getadc(ad_kanal_rocker_gyro)
Buf1 = Buf1 * 10
Ad_gyro_r = Ad_gyro_r + Buf1
Waitms 2
Next Buf
Average_gyro_r = Ad_gyro_r
'Calculate ADXL horizontal position of platform
Buf1 = 0
For Buf = 1 To 100 'Mean out of 100 values
Ad_adxl_r = Getadc(ad_kanal_rocker_adxl)
Buf1 = Ad_adxl_r + Buf1
Waitms 2
Next Buf
Adxl_zero_r = Buf1 / 10
#endif
'Check if values are in tolerable range
If Adxl_zero < 4000 Then
Errno = 3
Goto Err_value
Print "2:11=10"
End If
If Adxl_zero > 6000 Then
Errno = 3
Goto Err_value
Print "2:11=11"
End If
If Gyro_zero < 5000 Then
Errno = 2
Goto Err_value
Print "2:11=12"
End If
If Gyro_zero > 6500 Then
Errno = 2
Goto Err_value
Print "2:11=13"
End If
Start Watchdog
End Sub
'---------------------------------------------------------------------------
'Err_value:
' On error the program is processing this routine endlessly.
' Switch the Wheelie off to reset.
'---------------------------------------------------------------------------
Sub Err_value
Stop Watchdog
Do
For Buf = 1 To Errno
Set Led3
Waitms 150
Reset Led3
Waitms 150
Next Buf
Wait 2
Loop
End Sub
'---------------------------------------------------------------------------
' Gear
'
' get values from the Geartoothsensors
'
'---------------------------------------------------------------------------
#if I2c_enable
Sub Gear
I2creceive &H40 , Speed_array(1) , 0 , 4 'Gearsensoren über I²C abfragen
Speed_left = 11810 / Speed_left 'umrechnen in km/h *10 damit wir eine Nachkommastelle ohne Single haben
Speed_right = 11810 / Speed_right 'der Wert müsste deshalb durch 10 geteilt werden
If Cw_ccw_b = 1 Then '1181 errechnet sich aus 64µs pro Timertakt des Gearprozessors und 2,1cm Wegstrecke pro Zahnrad
Speed_left_out = Speed_left * -1
Else
Speed_left_out = Speed_left
End If
If Cw_ccw_a = 1 Then
Speed_right_out = Speed_right * -1
Else
Speed_right_out = Speed_right
End If
Buf = Speed_sum / 5 'Mittelwert aus dem Durchschnitt der beiden Geschwindigkeiten bilden
Speed_sum = Speed_sum - Buf
Buf = Speed_left_out + Speed_right_out
Speed_sum = Speed_sum + Buf
Buf = Speed_diff / 5 'Mittelwert aus der Differenz der beiden Geschwindigkeiten bilden
Speed_diff = Speed_diff - Buf
Buf = Speed_left_out - Speed_right_out
Speed_diff = Speed_diff + Buf
Speed_correction = Speed_diff / 17
End Sub
#endif
'---------------------------------------------------------------------------
' Serial0charmatch
'
' Im Eingangspuffer wurde ein "13" empfangen
' Dieser eine Takt Interrupt verzögert theoretisch die Regelung!?!
'---------------------------------------------------------------------------
Serial0charmatch:
Cr_received = 1
Return
'---------------------------------------------------------------------------
' Checkserinp
'
' Hier ist der String abgeholt
' Der Mainchannel und der : wird geprüft
'---------------------------------------------------------------------------
Sub Checkserinp
If Asc(serinpstr) = 35 Then 'Strings mit # gleich weiterleiten
Print Serinpstr
Exit Sub
End If
If Asc(serinpstr) = 27 Then 'Strings mit ESC gleich weiterleiten
Print Serinpstr
Exit Sub
End If
Zeichenpos = Instr(serinpstr , ":")
If Zeichenpos > 0 Then ' Doppelpunkt Gefunden
If Instr(serinpstr , "*") > 0 And Instr(serinpstr , "*") < Zeichenpos Then
Print Serinpstr
Call Parser
Exit Sub
Else 'kein *
Serinpbuffer = Left(serinpstr , Zeichenpos)
Mainchannel = Val(serinpbuffer)
If Mainchannel = Mymainchannel Then
Call Parser
Exit Sub
Else
Print Serinpstr
Exit Sub
End If
End If
Else 'kein :
If Mainchannel = Mymainchannel Then 'Mainchannel müsste noch von vorigem Durchlauf drinstehen
Call Parser
Exit Sub
Else 'anderes Modul
Print Serinpstr
Exit Sub
End If
End If
End Sub
'---------------------------------------------------------------------------
' Parser
'
' Der Parser zerteilt die empfangene Zeichenkette in Moduladresse,
' Subchannel (Befehl) und Wert.
'---------------------------------------------------------------------------
Sub Parser
Dim I As Byte
Dim A As Byte
A = 1
Serinpbuffer = ""
Mnemonicbuffer = ""
Wert = 0
Subchannel = 0 'der ":" und alles davor kommt weg
Zeichenpos = Len(serinpstr) - Instr(serinpstr , Doppelpunkt)
Serinpbuffer = Right(serinpstr , Zeichenpos)
Mnemonicbuffer = ""
Zeichenpos = Instr(serinpbuffer , Istgleich)
If Zeichenpos = 0 Then Zeichenpos = Len(serinpbuffer)
For I = 1 To Zeichenpos 'Den ganzen String bis Ende oder = nach Zahlen durchsuchen
If Serinbuffarr(i) >= "0" And Serinbuffarr(i) <= "9" Then
Mnemonicbufferarray(a) = Serinbuffarr(i)
Incr A
Mnemonicbufferarray(a) = 0
End If
Next
Subchannel = Val(mnemonicbuffer) 'gefundene Zahl mit dem Mnemonic addieren
If Instr(serinpbuffer , Istgleich) > 0 Then '= ist vorhanden
Frage = 0
Else
Frage = 1
End If
Zeichenpos = Len(serinpbuffer) - Instr(serinpbuffer , Istgleich)
Serinpbuffer = Right(serinpbuffer , Zeichenpos) 'alles hinter = ist der Wert
Wert = Val(serinpbuffer)
'An dieser Stelle ist alles ausgewertet
'Mainchannel ist die Kartennummer des Befehls
'Subchannel ist der Befehl
'Wert ist der Wert der gesetzt werden soll
'Frage steht auf 1 wenn kein = im Datensatz vorgekommen ist
Select Case Subchannel
Case 1 'liest den ADXL-320 Wert
Serinpstr = "#0:ADX=" + Str(ad_adxl) + "!"
Print Serinpstr
Case 2 'liest den IDG-300 Wert
Serinpstr = "#0:IDG=" + Str(ad_gyro) + "!"
Print Serinpstr
Case 3
Serinpstr = "#0:IDN=" + Idenditaet
Print Serinpstr
Case 6
Serinpstr = "#0:BAT=" + Str(ad_batt) + "!"
Print Serinpstr
Case Else
Serinpstr = "#0:ERR=[Syntax Error]!"
Print Serinpstr
End Select
End Sub