$regfile = "m168def.dat" $crystal = 16000000 $baud = 16000 $hwstack = 64 $swstack = 64 $framesize = 64 Const Servogain = 10 Const Pterm = -0.25 'all -ive as a +ive pulse lenght causes +ive turn Const Iterm = -0.0003 Const Dterm = -0.35 Const Kalmangpsweight = 0.5 Const Kalmangyroweight = 0.5 Const Propogation = 0.98 *(1 -kalmangyroweight) Const Servocontrolinput = 0.0015 *(1 -kalmangyroweight) 'need to check these with simcode Const Center = 6200 'needs to be checked with servo Const Conversionfactor = 16 'pwm timer counter is 16 times slower than sw pwm Const Lowerpwm = Center - 300 Const Upperpwm = Center + 300 Baud = 125000 Config Portd.4 = Output Config Portd.2 = Output Config Portd.5 = Output Config Portb.1 = Output Config Portd.3 = Input Config Portd.6 = Input Config Portd.7 = Input Config Portb.0 = Input Config Portc.4 = Input Config Portc.5 = Output Config Portc.2 = Output Config Portc.3 = Output Config Watchdog = 1024 'Config Spi = Soft , Din = Pinc.4 , Dout = Portc.5 , Ss = None , Clock = Portc.2 'Spiinit Config Timer1 = Timer , Prescale = 64 Config Timer0 = Timer , Prescale = 1024 Dim Rate As Integer , Temperature As Integer , Lsb As Byte , Msb As Byte 'melexis Dim Rateread As Byte , Tempread As Byte , Readmelexis As Byte , Mask As Word , Maskword As Word , Servoenable As Byte Dim Firstupdate As Byte , Servoexcitecount As Byte 'rest Dim S As Single , R As Single , Gpfloatone As Single , Gpfloattwo As Single , Oldheading As Single , Realrate As Single , Integral As Single , Filteredrate As Single , Servo As Single Dim Gpbyteone As Byte , Pulses As Byte , Error As Byte , Enablegroundcontrol As Byte Dim U As Integer , Gpintegerone As Integer , Targetheading As Single , Gpsheading As Single , Heading As Single Dim Gpwordone As Word , Pulselenght As Word Rateread = &B10010100 Tempread = &B10011100 Readmelexis = &B10000000 Maskword = &B0000111111111111 Pcmsk2 = &B01000000 'pcint22 enabled Pcmsk0 = &B00000001 'pcint0 enabled Groundcontrol Alias Portd.4 Rts Alias Pind.3 Cts Alias Portd.2 Servoone Alias Portd.5 Servotwo Alias Portb.1 Pulsesdetect Alias Pind.6 Inputone Alias Pinb.0 Inputtwo Alias Pind.7 Slave Alias Portc.3 Din Alias Pinc.4 Dout Alias Portc.5 Clock Alias Portc.2 Slave = 1 'Declare Sub Ground() Declare Sub Talktomelexis() 'Declare Sub Ascent() On Pcint0 Edge On Pcint2 Copy Set Pcifr.pcif2 Set Pcifr.pcif0 Enable Pcint2 Enable Pcint0 Groundcontrol = 0 Servotwo = 1 Servoone = 1 S = 0 Integral = 0 For Gpbyteone = 0 To 200 'to let us check servo alignment Waitms 15 Pulseout , Portd , 5 , Center Next Start Timer1 Start Timer0 Enable Interrupts Start Watchdog Do Reset Watchdog Waitms 15 If Pulselenght > 200 And Pulselenght < 600 And Timer1 < 20000 Then 'a valid and recent pulse Incr Pulses Else Pulses = 0 Groundcontrol = 0 End If If Pulses > 10 Then Groundcontrol = 1 'we enable servo relaying Pulses = 10 End If If Groundcontrol = 0 Then Servoone = 1 Pulseout , Portd , 5 , Center 'keep servo centered End If Call Talktomelexis() 'check gyro If Rts = 1 Then 'check for comms Disable Interrupts 'disable interrupts with first message Cts = 1 Inputbin Gpbyteone Cts = 0 If Gpbyteone = 1 Then 'if we get a descent command Firstupdate = 2 'means we treat the first gps update correctly Waitus 300 Printbin Rate ; Temperature ; Error ; Heading ; Filteredrate ; Pulselenght ; Pulses 'removes possible cause of a hang Goto Descent End If Waitus 300 Printbin Rate ; Temperature ; Error Servoone = 1 Incr Servoexcitecount If Servoexcitecount > 10 Then Servoexcitecount = 0 For Gpbyteone = 0 To 10 Pulseout , Portd , 5 , Lowerpwm 'wiggle servo Waitms 15 Next For Gpbyteone = 0 To 10 Pulseout , Portd , 5 , Upperpwm Waitms 15 Next End If End If Loop Descent: Do Reset Watchdog While Timer0 < 250 'wait for 16ms to elapse Wend Reset Timer0 If Pulselenght > 200 And Pulselenght < 600 And Timer1 < 20000 Then 'a valid and recent pulse Incr Pulses Else Pulses = 0 Groundcontrol = 0 End If If Pulses > 10 Then Groundcontrol = 1 'we enable servo relaying Pulses = 10 End If If Rts = 1 Then 'check for comms Cts = 1 Inputbin Gpbyteone , Gpsheading , Targetheading , Servoenable , Enablegroundcontrol Cts = 0 If Firstupdate = 0 Or Firstupdate = 1 Then 'ie we had another message not long ago Gpfloatone = Gpsheading - Oldheading 'so update the heading estimate If Gpfloatone < -180 Then 'otherwise we dont bother as we dont know what was happening Gpfloatone = Gpfloatone + 360 'one second ago End If If Gpfloatone > 180 Then Gpfloatone = Gpfloatone - 360 'get it in the right range End If If Firstupdate = 0 Then Gpfloatone = Kalmangpsweight * Gpfloatone 'if firstupdate=1, gpsgain=1 Else 'if firstupdate=1, set to zero Firstupdate = 0 End If Heading = Heading + Gpfloatone If Heading > 180 Then 'get heading in correct range Heading = Heading - 360 End If If Heading < -180 Then Heading = Heading + 360 End If Else 'ie if firstupdate=2 Targetheading = 0 'we set targetheading to zero for first update, as heading is relative Firstupdate = 1 'until we get more recent data, due to gps lag End If Oldheading = Heading ' always store the past heading If Enablegroundcontrol = 1 Then 'enable ground control Enable Interrupts Else Disable Interrupts End If Waitus 250 Printbin Rate ; Temperature ; Error ; Heading ; Filteredrate ; Pulselenght ; Pulses End If Call Talktomelexis() Gpintegerone = Rate Gpintegerone = Gpintegerone - 1009 'center position Gpfloatone = Gpintegerone Gpfloatone = Gpfloatone / 6.8265 Realrate = Gpfloatone 'now in degrees per second Gpfloatone = Gpfloatone * Kalmangyroweight 'gyro term Filteredrate = Propogation * Filteredrate 'propogation term Filteredrate = Filteredrate + Gpfloatone 'add them Gpfloatone = Servo * Servocontrolinput 'control term - need to use rx pwm if under ground control Filteredrate = Filteredrate + Gpfloatone 'add them Gpfloatone = Filteredrate / 62.5 'numerical integration over timestep Heading = Heading + Gpfloatone If Heading > 180 Then 'get heading in correct range Heading = Heading - 360 End If If Heading < -180 Then Heading = Heading + 360 End If Gpfloatone = Heading - Targetheading 'heading offset If Gpfloatone < -180 Then 'get it in the right range Gpfloatone = Gpfloatone + 360 End If If Gpfloatone > 180 Then Gpfloatone = Gpfloatone - 360 End If Integral = Integral + Gpfloatone 'i increment 'pid Gpfloattwo = Gpfloatone * Pterm 'P Gpfloatone = Dterm * Filteredrate 'D Gpfloatone = Gpfloatone + Gpfloattwo 'add d and p terms If Gpfloatone > 30 Then Gpfloatone = 30 'servo limits on d and p If Gpfloatone < -30 Then Gpfloatone = -30 Gpfloattwo = Integral * Iterm 'calculate I If Gpfloattwo > 25 Then Integral = 25 / Iterm 'wind up prevension If Gpfloattwo < -25 Then Integral = -25 / Iterm Gpfloatone = Gpfloatone + Gpfloattwo 'add I term Gpfloatone = Servogain * Gpfloatone 'servo dependant variable Servo = Gpfloatone 'store servo for control input Gpintegerone = Gpfloatone If Groundcontrol = 1 Then Gpfloatone = Pulselenght * Conversionfactor Servo = Gpfloatone - Center 'uses rx pwm if under ground control End If Gpintegerone = Gpintegerone + Center 'add on pwm center value If Groundcontrol = 0 And Servoenable = 1 Then Servoone = 1 'set pwm high Pulseout , Portd , 5 , Gpintegerone 'only if not under ground control End If Loop Edge: If Groundcontrol = 1 Then Servoone = Not Inputone 'copy If Inputone = 0 Then Pulselenght = Timer1 'read pwm End If Timer1 = 0 Return Copy: If Groundcontrol = 1 Then Servotwo = Not Inputtwo 'copy Return Sub Talktomelexis() Clock = 0 Dout = 0 Slave = 0 Error = 0 Waitus 1 For Gpbyteone = 7 To 0 Step -1 'spi out Dout = Rateread.gpbyteone Waitus 1 Clock = 1 Waitus 1 Clock = 0 Next For Gpbyteone = 15 To 0 Step -1 'extra clock cycles is in datasheet Waitus 1 Clock = 1 Waitus 1 Clock = 0 Next Waitus 1 Slave = 1 Waitus 300 Slave = 0 For Gpbyteone = 7 To 0 Step -1 'spi out Dout = Readmelexis.gpbyteone Waitus 1 Clock = 1 Waitus 1 Clock = 0 Next For Gpbyteone = 7 To 0 Step -1 'data in Waitus 1 Clock = 1 Msb.gpbyteone = Din Waitus 1 Clock = 0 Next For Gpbyteone = 7 To 0 Step -1 'another byte in Waitus 1 Clock = 1 Lsb.gpbyteone = Din Waitus 1 Clock = 0 Next Waitus 1 Slave = 1 Rate = Makeint(lsb , Msb) 'create integer Rate = Rate And Maskword 'mask it Shift Rate , Right , 1 'shift it If Msb.6 = 1 Then Error = 1 'check selftest feature Slave = 0 Waitus 1 For Gpbyteone = 7 To 0 Step -1 'do the same sort of thing for temp Dout = Tempread.gpbyteone Waitus 1 Clock = 1 Waitus 1 Clock = 0 Next For Gpbyteone = 15 To 0 Step -1 Waitus 1 Clock = 1 Waitus 1 Clock = 0 Next Waitus 1 Slave = 1 Waitus 300 Slave = 0 For Gpbyteone = 7 To 0 Step -1 Dout = Readmelexis.gpbyteone Waitus 1 Clock = 1 Waitus 1 Clock = 0 Next For Gpbyteone = 7 To 0 Step -1 Waitus 1 Clock = 1 Msb.gpbyteone = Din Waitus 1 Clock = 0 Next For Gpbyteone = 7 To 0 Step -1 Waitus 1 Clock = 1 Lsb.gpbyteone = Din Waitus 1 Clock = 0 Next Waitus 1 Slave = 1 Temperature = Makeint(lsb , Msb) If Msb.6 = 1 Then Error = 1 Temperature = Temperature And Maskword Shift Temperature , Right , 1 End Sub