Ok, das mit dem festen Senden von Daten und dem Blinken werd ich mal ausprobieren, damit ich weiß, was funktioniert und was nicht! Alternativ dazu möchte ich auch noch den PC über einen MAX232 anschließen, um die Input-Daten vom ATTINY ausgeben zu lassen. Mal sehen, was dabei rauskommt..
@Richard:
Kannst du mir sagen, wo der Unterschied zwischen Inputbin und Get liegt? Ich habe keinen gefunden, evtl. bin ich momentan etwas zu abgelenkt, ums zu sehen.. Wäre nett von dir.
Gruß
Chris
EDIT:
Habs jetzt endlich erfolgreich geschafft, das meiste so hinzubiegen, wie ich es will
Hier mal die Codes:
ATMEGA8:
ATTINY2313:Code:$regfile = "m8def.dat" $crystal = 16000000 $framesize = 80 $hwstack = 80 $swstack = 80 $baud = 115000 Config Timer2 = Timer , Prescale = 256 On Timer2 Detectrxpause Enable Timer2 Config Int1 = Rising On Int1 Getreceiver Enable Int1 Config Pind.3 = Input Portd.3 = 0 Const Start_byte = 127 Const _maxchannel = 4 Dim Bufferbyte As Byte Dim Kanal(_maxchannel) As Byte Dim Channel As Byte Dim _bl(_maxchannel) As Word Dim I As Byte Dim _crc As Word Enable Interrupts Do For I = 1 To 4 _bl(i) = 63200 Next I _crc = Crc16(_bl(1) , 4) Printbin Start_byte ; _bl(1) ; _bl(2) ; _bl(3) ; _bl(4) ; _crc Waitms 100 Loop End Getreceiver: If Channel > 0 And Channel < 5 Then Kanal(channel) = Timer2 End If Timer2 = 6 Incr Channel Return Detectrxpause: Channel = 0 Return
Der Unterschied liegt wirklich im Servo-Code! Danke für den Tip... Jetzt gehts auf die nächste Hürde zu, das Summensignal auf den Servo-Bereich umzuskalieren. Danach muss noch die WM+ eingebunden werden.Code:$regfile = "attiny2313.dat" $crystal = 16000000 $framesize = 30 $hwstack = 32 $swstack = 30 $baud = 115000 Config Timer1 = Timer , Prescale = 8 Timer1 = 62535 On Timer1 Servoirq Enable Timer1 Config Portd.2 = Output Config Portd.3 = Output Config Portd.4 = Output Config Portd.5 = Output Dim Kanal As Byte Dim Servo(4) As Word Dim _bl(4) As Word Dim I As Word Dim _crc As Word Dim _crcold As Word Dim _start As Byte 'min: 61535, mitte 62535, max 63535 = 2000 schritte Const Start_byte = 127 Const Min_servo = 63800 Const Max_servo = 61535 Const Diff_servo = Max_servo - Min_servo For I = 1 To 4 _bl(i) = Min_servo Servo(i) = _bl(i) Next I Enable Interrupts Wait 3 Do If Ischarwaiting() > 0 Then Inputbin _start If _start = Start_byte Then Inputbin _bl(1) , _bl(2) , _bl(3) , _bl(4) , _crc If _crc = Crc16(_bl(1) , 4) And _crc <> _crcold Then For I = 1 To 4 Servo(i) = _bl(i) Next I _crcold = _crc End If Else For I = 1 To 4 Servo(i) = Min_servo Next I End If End If Loop Servoirq: If Kanal = 0 Then If Portd.2 = 0 Then 'wenn port low Timer1 = Servo(1) 'dann timer auf entsprechende verzögerung Portd.2 = 1 'und port anschalten Else 'das hier passiert erst bei dem darauf folgenden interrupt Portd.2 = 0 'dann port wieder ausschalten Incr Kanal 'und den nächsten kanal bearbeiten End If End If If Kanal = 1 Then If Portd.3 = 0 Then Timer1 = Servo(2) Portd.3 = 1 Else Portd.3 = 0 Incr Kanal End If End If If Kanal = 2 Then If Portd.4 = 0 Then Timer1 = Servo(3) Portd.4 = 1 Else Portd.4 = 0 Incr Kanal End If End If If Kanal = 3 Then If Portd.5 = 0 Then Timer1 = Servo(4) Portd.5 = 1 Else Portd.5 = 0 Incr Kanal End If End If If Kanal = 4 Then Timer1 = 65530 '40000 | eine pause von ca. 12ms bis zum nächsten interrupt. Bei guten Servos oder Brushlessreglern kann man hier bis auf 65530 gehen ==> ansteuerfrequenz von ~ 200Hz Kanal = 0 End If Return End
Geändert von Che Guevara (15.05.2011 um 18:56 Uhr)
Hallo,
nachdem ich gestern ein paar Erfolge hatte, liefs heute leider nicht so gut... Ich habe das Gehäuse zusammengebaut, die Motoren und die Steuerung usw... befestigt und wollts mal ausprobieren. Jedoch habe ich ein paar Probleme:
Bei meinem ersten Code (hier gehts jetzt nur noch um den ATMEGAfunktionierte alles so mittelmäßig:
Wenn ich den Tricopter i-wie gedreht habe, haben die Motoren und der Servo darauf reagiert, jedoch fing dann das Ganze zu schwingen an. Dann dachte ich mir, bevor ich da jetzt optimiere, baue ich lieber gleich einen PID-Regler ein. Gesagt, getan....Code:$regfile = "m8def.dat" $crystal = 16000000 $framesize = 80 $hwstack = 80 $swstack = 80 $baud = 115200 Declare Sub Wmp_init() Declare Sub Send_zero() Declare Sub Read_data() Declare Sub Set_offset() $lib "I2C_TWI.LBX" 'Hardware I2C Config Scl = Portc.5 'Ports for I2C-Bus Config Sda = Portc.4 Config Twi = 400000 I2cinit Config Timer1 = Timer , Prescale = 1 On Timer1 Pausedetect Enable Timer1 Config Int1 = Falling On Int1 Measure Enable Int1 Config Pind.3 = Input Portd.3 = 0 Const Start_byte = 127 Const _maxchannel = 4 Dim Bufferbyte As Byte Dim Kanal(_maxchannel) As Word Dim Channel As Byte Dim _bl(_maxchannel) As Word Dim I As Byte Dim _crc As Word Dim _sbl(_maxchannel) As Integer Dim Buffer(6) As Byte Dim Yaw As Word Dim Yaw0 As Byte At Yaw + 1 Overlay Dim Yaw1 As Byte At Yaw Overlay Dim Roll As Word Dim Roll0 As Byte At Roll + 1 Overlay Dim Roll1 As Byte At Roll Overlay Dim Pitch As Word Dim Pitch0 As Byte At Pitch + 1 Overlay Dim Pitch1 As Byte At Pitch Overlay Dim _yawoffset As Long Dim _rolloffset As Long Dim _pitchoffset As Long Dim _yawnow As Integer Dim _rollnow As Integer Dim _pitchnow As Integer Call Wmp_init() Waitms 500 Call Set_offset() Enable Interrupts 'Empfänger: '29000 < kanal(x) < 64000 'mitte = (64000 + 29000) / 2 = 93000 / 2 = 46500 'Ausschlag: 17500 'Servo-Funktion: 'min: 63800, mitte: 62667.5 , max: 61535 --> 2265 Schritte Do Call Read_data() For I = 1 To 4 _sbl(i) = Kanal(i) - 17500 _sbl(i) = _sbl(i) / 15.4525386 Next I _sbl(2) = _sbl(2) - 600 _sbl(3) = _sbl(3) - 500 _bl(1) = 62667.5 + _sbl(1) _bl(2) = _bl(1) - _sbl(3) _bl(3) = _bl(1) + _sbl(3) _bl(1) = _bl(1) - _sbl(2) '_bl(4) = 62535 + _sbl(4) '############################## _yawnow = Yaw - _yawoffset _yawnow = _yawnow / 2 _rollnow = Roll - _rolloffset _rollnow = _rollnow / 2 _pitchnow = Pitch - _pitchoffset _pitchnow = _pitchnow / 2 '############################## _bl(1) = _bl(1) - _pitchnow _bl(2) = _bl(2) - _rollnow _bl(3) = _bl(3) + _rollnow _bl(4) = 62535 + _yawnow _bl(4) = _bl(4) + _sbl(4) _crc = Crc16(_bl(1) , 4) Printbin Start_byte ; _bl(1) ; _bl(2) ; _bl(3) ; _bl(4) ; _crc 'Waitms 100 Loop Measure: If Channel > 0 And Channel < 5 Then Kanal(channel) = Timer1 End If Timer1 = 1536 Incr Channel Return Pausedetect: Channel = 0 Return Sub Wmp_init() I2cstart I2cwbyte &HA6 ' sends memory address I2cwbyte &HFE ' WM+ activation I2cwbyte &H04 . ' Now Adress changes to &HA4 I2cstop End Sub Sub Send_zero() I2cstart I2cwbyte &HA4 ' sends memory address I2cwbyte &H00 ' sends zero before receiving I2cstop Waitms 1 End Sub Sub Read_data() Gosub Send_zero ' sends zero before receiving I2creceive &HA4 , Buffer(1) , 0 , 6 ' receive 6 bytes Yaw1 = Buffer(1) Roll1 = Buffer(2) ' Low Bytes Pitch1 = Buffer(3) Shift Buffer(4) , Right , 2 : Yaw0 = Buffer(4) Shift Buffer(5) , Right , 2 : Roll0 = Buffer(5) ' High Bytes Shift Buffer(6) , Right , 2 : Pitch0 = Buffer(6) End Sub Sub Set_offset() _yawoffset = 0 _rolloffset = 0 _pitchoffset = 0 For I = 1 To 50 Call Read_data _yawoffset = _yawoffset + Yaw _rolloffset = _rolloffset + Roll _pitchoffset = _pitchoffset + Pitch Next I _yawoffset = _yawoffset / 50 _rolloffset = _rolloffset / 50 _pitchoffset = _pitchoffset / 50 End Sub End
Hier mal der Code:
ABER:Code:$regfile = "m8def.dat" $crystal = 16000000 $framesize = 80 $hwstack = 80 $swstack = 80 $baud = 115200 Declare Sub Wmp_init() Declare Sub Send_zero() Declare Sub Read_data() Declare Sub Set_offset() $lib "I2C_TWI.LBX" 'Hardware I2C Config Scl = Portc.5 'Ports for I2C-Bus Config Sda = Portc.4 Config Twi = 400000 I2cinit Config Timer1 = Timer , Prescale = 1 On Timer1 Pausedetect Enable Timer1 Config Int1 = Falling On Int1 Measure Enable Int1 Config Pind.3 = Input Portd.3 = 0 Const Start_byte = 127 Const _maxchannel = 4 Dim Bufferbyte As Byte Dim Kanal(_maxchannel) As Word Dim Channel As Byte Dim _bl(_maxchannel) As Word Dim I As Byte Dim _crc As Word Dim _sbl(_maxchannel) As Integer Dim Buffer(6) As Byte Dim Yaw As Word Dim Yaw0 As Byte At Yaw + 1 Overlay Dim Yaw1 As Byte At Yaw Overlay Dim Roll As Word Dim Roll0 As Byte At Roll + 1 Overlay Dim Roll1 As Byte At Roll Overlay Dim Pitch As Word Dim Pitch0 As Byte At Pitch + 1 Overlay Dim Pitch1 As Byte At Pitch Overlay Dim _yawoffset As Long Dim _rolloffset As Long Dim _pitchoffset As Long Dim _yawnow As Integer Dim _rollnow As Integer Dim _pitchnow As Integer Dim Signal(3) As Integer Dim Pid(3) As Integer Dim Kp_err(3) As Integer Dim Ki_err(3) As Integer Dim Kd_err(3) As Integer Dim Ki_sum(3) As Integer Dim Kd_old(3) As Integer Dim Kp(3) As Single Dim Ki(3) As Single Dim Kd(3) As Single Kp(1) = 0.10 Kp(2) = 1 Kp(3) = 1 Ki(1) = 0 Ki(2) = 0 Ki(3) = 0 Kd(1) = 0 Kd(2) = 0 Kd(3) = 0 Call Wmp_init() Waitms 500 Call Set_offset() Enable Interrupts 'Empfänger: '29000 < kanal(x) < 64000 'mitte = (64000 + 29000) / 2 = 93000 / 2 = 46500 'Ausschlag: 17500 'Servo-Funktion: 'min: 63800, mitte: 62667.5 , max: 61535 --> 2265 Schritte Const _bl1offset = 0 Const _bl2offset = 0 Const _bl3offset = 0 Do For I = 1 To 4 _sbl(i) = Kanal(i) - 17500 _sbl(i) = _sbl(i) / 15.4525386 Next I _sbl(2) = _sbl(2) - 600 _sbl(3) = _sbl(3) - 500 _bl(1) = 62667.5 + _sbl(1) _bl(2) = _bl(1) - _sbl(3) _bl(3) = _bl(1) + _sbl(3) _bl(1) = _bl(1) - _sbl(2) _bl(4) = 62535 + _sbl(4) _bl(1) = _bl(1) + _bl1offset _bl(2) = _bl(2) + _bl2offset _bl(3) = _bl(3) + _bl3offset Call Read_data() _yawnow = Yaw - _yawoffset _rollnow = Roll - _rolloffset _pitchnow = Pitch - _pitchoffset Signal(1) = _yawnow Signal(2) = _rollnow Signal(3) = _pitchnow For I = 1 To 3 'Proportional Kp_err(i) = Signal(i) * Kp(i) 'Kp_err(i) = Kp_err(i) / 10 'Integral Ki_err(i) = Signal(i) * Ki(i) 'Ki_err(i) = Ki_err(i) / 10 Ki_sum(i) = Ki_sum(i) + Ki_err(i) 'Differential Kd_err(i) = Signal(i) * Kd(i) 'Kd_err(i) = Kd_err(i) / 10 Kd_err(i) = Kd_old(i) - Kd_err(i) Kd_old(i) = Kd_err(i) 'Aufsummieren Pid(i) = Kp_err(i) + Ki_sum(i) Pid(i) = Pid(i) + Kd_err(i) Next I 'Pid(1) --> Yaw-PID 'Pid(2) --> Roll-PID 'Pid(3) --> Pitch-PID _bl(1) = _bl(1) - Pid(3) _bl(2) = _bl(2) - Pid(2) _bl(3) = _bl(3) + Pid(2) _bl(4) = _bl(4) + Pid(1) _crc = Crc16(_bl(1) , 4) Printbin Start_byte ; _bl(1) ; _bl(2) ; _bl(3) ; _bl(4) ; _crc Loop Measure: If Channel > 0 And Channel < 5 Then Kanal(channel) = Timer1 End If Timer1 = 1536 Incr Channel Return Pausedetect: Channel = 0 Return Sub Wmp_init() I2cstart I2cwbyte &HA6 ' sends memory address I2cwbyte &HFE ' WM+ activation I2cwbyte &H04 . ' Now Adress changes to &HA4 I2cstop End Sub Sub Send_zero() I2cstart I2cwbyte &HA4 ' sends memory address I2cwbyte &H00 ' sends zero before receiving I2cstop Waitms 1 End Sub Sub Read_data() Gosub Send_zero ' sends zero before receiving I2creceive &HA4 , Buffer(1) , 0 , 6 ' receive 6 bytes Yaw1 = Buffer(1) Roll1 = Buffer(2) ' Low Bytes Pitch1 = Buffer(3) Shift Buffer(4) , Right , 2 : Yaw0 = Buffer(4) Shift Buffer(5) , Right , 2 : Roll0 = Buffer(5) ' High Bytes Shift Buffer(6) , Right , 2 : Pitch0 = Buffer(6) End Sub Sub Set_offset() _yawoffset = 0 _rolloffset = 0 _pitchoffset = 0 For I = 1 To 50 Call Read_data _yawoffset = _yawoffset + Yaw _rolloffset = _rolloffset + Roll _pitchoffset = _pitchoffset + Pitch Next I _yawoffset = _yawoffset / 50 _rolloffset = _rolloffset / 50 _pitchoffset = _pitchoffset / 50 End Sub End
Egal welche Werte ich für Kp einsetze (hab von 0.1 bis 1000 alles probiert), die Motoren / der Servo reagieren auf keinerlei Bewegung, selbst wenn ich das Teil innerhalb von ca. 0.5sek um 180° drehe. Aber warum? Der Offset vom WM+ liegt bei ca. 8000, das wird auch richtig berechnet.. Nur mit dem PID-Regler klappts nicht?! Wer kann miir weiterhelfen?
Dann habe ich noch eine Frage:
Im Programm stehen die Maximal und Minimal Werte des Empfängers und der Servos. Eigentlich sollte man die Knüppelposition doch so umrechnen können:
Jedoch laufen dann die Motoren nicht so wie sie sollen. Normalerweise sollte doch Motor 1 (_bl(1)) nicht laufen, wenn der 1. Stick unten ist und die volle Drehzahl erreichen, wenn der Stick oben ist.. Das ist bei mir aber nicht so. Habe ich einen Denkfehler?Code:For I = 1 To 4 _sbl(i) = Kanal(i) - 46500 '-17500 < _sbl(i) < +17500 _sbl(i) = _sbl(i) / 15.4525386 '-1132 < _sbl(i) < +1132 Next I _bl(1) = 62667 - _sbl(1)
Vielen Dank
Gruß
Chris
Beim PID Code kommt mir die Berechnung des Ableitungsteils komisch vor: als alter Wert für die Differenzbildung wird bereits die Differenz gespeichert. Ich hätte da erwartet das man sich den Wert ohne die Differenzbildung merkt. So wie ich es kenne wird auch einfach die alte Regelabweichung gemerkt, also noch vor der Multiplikation mit Kd - das ist aber vielleicht auch nur Geschmackssache.
So ein PID Regler ist nicht ganz einfach einzustellen. Der erste Test wäre erstmal nur als Proportionalregler, also Ki = Kd = 0.
Beim Code für den Servo Controller (Tiny2313) kommt mir die ISR komisch vor: die Kanalnummer wird in den IF Abfragen erhöht. Wenn man mit Kanalnr 0 anfängt paßt dann erst die NR 0 und dann auch noch die 1 usw. Durch die Kanalnr. ist eigentlich auch der Zustand der Ports festgelegt und muss nicht extra Abgefragt werden. Also immer einen IO-Pin setzen und einen IO-Pin Löschen.
Bei meinem jetzigen / obigen Code habe ich Ki und Kd auf 0 gesetzt, lediglich für Kp habe ich versch. Werte eingesetzt...
Der Code für die Servos funktioniert einwandfrei, er läuft jetzt seit ca. 1 std im Dauerbetrieb ohne auch nur einen einzigen Fehler
Gruß
Chris
EDIT:
@Besserwessi: Versteh mich bitte nicht falsch, aber ich möchte am ATTINY2313 ungerne noch etwas verändern, solange es so funktioniert.. Das Teil hat mich schon genug Nerven gekostet, sodass ich wirklich froh bin, dass alles läuft! Für Anregungen, Tips, whatever bin ich aber trotzdem dankbar![]()
Geändert von Che Guevara (16.05.2011 um 18:36 Uhr)
So, nach ein paar zeitraubenden Tests habe ich jetzt herausgefunden, dass meine oben genannten Empfänger-werte nicht stimmten ...
Leider weichen die Werte von Kanal zu Kanal geringfügig ab, sodass ich für jeden Kanal mit anderen Werten rechnen muss.
Hier mal mein momentaner Code:
Jetzt funktioniert wenigstens schon mal der FernbedinungsteilCode:$regfile = "m8def.dat" $crystal = 16000000 $framesize = 80 $hwstack = 80 $swstack = 80 $baud = 38400 '115200 Declare Sub Wmp_init() Declare Sub Send_zero() Declare Sub Read_data() Declare Sub Set_offset() $lib "I2C_TWI.LBX" 'Hardware I2C Config Scl = Portc.5 'Ports for I2C-Bus Config Sda = Portc.4 Config Twi = 400000 I2cinit Config Timer1 = Timer , Prescale = 1 On Timer1 Pausedetect Enable Timer1 Config Int1 = Falling On Int1 Measure Enable Int1 Config Pind.3 = Input Portd.3 = 0 Const Start_byte = 127 Const _maxchannel = 4 Dim Bufferbyte As Byte Dim Kanal(_maxchannel) As Word Dim Channel As Byte Dim _bl(_maxchannel) As Word Dim I As Byte Dim _crc As Word Dim _sbl(_maxchannel) As Integer Dim Buffer(6) As Byte Dim Yaw As Word Dim Yaw0 As Byte At Yaw + 1 Overlay Dim Yaw1 As Byte At Yaw Overlay Dim Roll As Word Dim Roll0 As Byte At Roll + 1 Overlay Dim Roll1 As Byte At Roll Overlay Dim Pitch As Word Dim Pitch0 As Byte At Pitch + 1 Overlay Dim Pitch1 As Byte At Pitch Overlay Dim _yawoffset As Long Dim _rolloffset As Long Dim _pitchoffset As Long Dim _yawnow As Integer Dim _rollnow As Integer Dim _pitchnow As Integer Dim Signal(3) As Integer Dim Pid(3) As Integer Dim Kp_err(3) As Integer Dim Ki_err(3) As Integer Dim Kd_err(3) As Integer Dim Ki_sum(3) As Integer Dim Kd_old(3) As Integer Dim Kp(3) As Single Dim Ki(3) As Single Dim Kd(3) As Single Kp(1) = 0.50 Kp(2) = 0.50 Kp(3) = 0.50 Ki(1) = 0 Ki(2) = 0 Ki(3) = 0 Kd(1) = 0 Kd(2) = 0 Kd(3) = 0 Call Wmp_init() Waitms 500 Call Set_offset() 'Servo-Funktion: 'min: 63800, mitte: 62667.5 , max: 61535 --> 2265 Schritte Dim _empfmiddle(4) As Word Dim _empfmin(4) As Word Dim _empfmax(4) As Word Dim _empfdiv(4) As Word _empfmiddle(1) = 26500 _empfmiddle(2) = 23800 _empfmiddle(3) = 25300 _empfmiddle(4) = 22250 _empfmin(1) = 14300 _empfmin(2) = 14650 _empfmin(3) = 17100 _empfmin(4) = 14750 _empfmax(1) = 32300 _empfmax(2) = 32600 _empfmax(3) = 32600 _empfmax(4) = 30500 For I = 1 To 4 _empfdiv(i) = _empfmiddle(i) - _empfmin(i) _empfdiv(i) = _empfdiv(i) / 2265 _empfdiv(i) = _empfdiv(i) * 2 Next I Const _bl1offset = 0 Const _bl2offset = 0 Const _bl3offset = 0 Const _bl4offset = 700 Enable Interrupts Do For I = 1 To 4 _sbl(i) = Kanal(i) - _empfmiddle(i) _sbl(i) = _sbl(i) / _empfdiv(i) Next I _bl(1) = 62667 - _sbl(1) _bl(2) = _bl(1) - _sbl(3) _bl(3) = _bl(1) + _sbl(3) _bl(1) = _bl(1) + _sbl(2) _bl(4) = 62667 + _sbl(4) _bl(1) = _bl(1) + _bl1offset _bl(2) = _bl(2) + _bl2offset _bl(3) = _bl(3) + _bl3offset _bl(4) = _bl(4) + _bl4offset Call Read_data() _yawnow = Yaw - _yawoffset _rollnow = Roll - _rolloffset _pitchnow = Pitch - _pitchoffset Signal(1) = _yawnow Signal(2) = _rollnow Signal(3) = _pitchnow For I = 1 To 3 'Proportional Kp_err(i) = Signal(i) * Kp(i) 'Kp_err(i) = Kp_err(i) / 10 'Integral Ki_err(i) = Signal(i) * Ki(i) 'Ki_err(i) = Ki_err(i) / 10 Ki_sum(i) = Ki_sum(i) + Ki_err(i) 'Differential Kd_err(i) = Signal(i) * Kd(i) 'Kd_err(i) = Kd_err(i) / 10 Kd_err(i) = Kd_old(i) - Kd_err(i) Kd_old(i) = Kd_err(i) 'Aufsummieren Pid(i) = Kp_err(i) + Ki_sum(i) Pid(i) = Pid(i) + Kd_err(i) Next I 'Pid(1) --> Yaw-PID 'Pid(2) --> Roll-PID 'Pid(3) --> Pitch-PID _yawnow = _yawnow / 2 _bl(1) = _bl(1) - Pid(3) _bl(2) = _bl(2) - Pid(2) _bl(3) = _bl(3) + Pid(2) _bl(4) = _bl(4) '- _yawnow _crc = Crc16(_bl(1) , 4) Printbin Start_byte ; _bl(1) ; _bl(2) ; _bl(3) ; _bl(4) ; _crc Loop Measure: If Channel > 0 And Channel < 5 Then Kanal(channel) = Timer1 End If Timer1 = 1536 Incr Channel Return Pausedetect: Channel = 0 Return Sub Wmp_init() I2cstart I2cwbyte &HA6 ' sends memory address I2cwbyte &HFE ' WM+ activation I2cwbyte &H04 . ' Now Adress changes to &HA4 I2cstop End Sub Sub Send_zero() I2cstart I2cwbyte &HA4 ' sends memory address I2cwbyte &H00 ' sends zero before receiving I2cstop Waitms 1 End Sub Sub Read_data() Gosub Send_zero ' sends zero before receiving I2creceive &HA4 , Buffer(1) , 0 , 6 ' receive 6 bytes Yaw1 = Buffer(1) Roll1 = Buffer(2) ' Low Bytes Pitch1 = Buffer(3) Shift Buffer(4) , Right , 2 : Yaw0 = Buffer(4) Shift Buffer(5) , Right , 2 : Roll0 = Buffer(5) ' High Bytes Shift Buffer(6) , Right , 2 : Pitch0 = Buffer(6) End Sub Sub Set_offset() _yawoffset = 0 _rolloffset = 0 _pitchoffset = 0 For I = 1 To 50 Call Read_data _yawoffset = _yawoffset + Yaw _rolloffset = _rolloffset + Roll _pitchoffset = _pitchoffset + Pitch Next I _yawoffset = _yawoffset / 50 _rolloffset = _rolloffset / 50 _pitchoffset = _pitchoffset / 50 End Sub EndDer PID-Regler macht aber trotzdem noch nichts... Außerdem habe ich gerade ein für mich unerklärliches Phänomen entdeckt:
Wenn ich
schreibe, dreht sich der Servo (_bl(4)) in beide möglichen Richtungen, abhängig von der Drehung des WM+ (i-wie logisch ^^)Code:_bl(4) = _bl(4) - _yawnow
Schreibe ich allerdings
(man achte auf das "+" statt "-")Code:_bl(4) = _bl(4) + _yawnow
so dreht er sich nur in eine Richtung (der Servo), die andere geht nur mit der Fernbedinung, jedoch nicht durch drehen des WM+?!
Kann sich das jemand erklären? Oder ist es evtl. ein Bug?
Übrigens habe ich jetzt die Baudrate auf beiden Chips auf 38.4k gesenkt, sollte auch genügen und der Fehler beträgt hier nur 0.2%.
Aber dazu habe ich auch noch eine Frage:
Ist es nicht egal, wie groß der Fehler in Prozent ist, wenn beide Chips die gleiche Baudraten-Einstellung und den gleichen Quarz haben? Dann hebt sich doch der Fehler des einen durch den Fehler des anderen auf, oder sehe ich das Falsch?
Gruß
Chris
Der komische Effekt mit _bl(4) +- _yawnow könnte durch die Datentypen verursacht werden. _bl(4) ist Word und _yawnow ist Integer. Da könnte es Probleme mit Überläufen kommen, wenn das Ergebnis nicht mehr in eine Interger variable paßt. Normal wird Word und Integer bei der Addition / Subtraction ja gleich bearbeitet, nur ist dann nicht klar wie man das Ergebnis Interpretieren soll - ist das dann ein Word oder Integer.
Ein Fehler in der Baudrate sollte sich auch beide µCs gleich auswirken. Es kann aber kleine Unterschiede geben, weil die Teiler für die Baudrate ggf. etwas anders sind. Tiny2313 und Mega8 sollte hier aber gleich sein.
Lesezeichen