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







Zitieren

Lesezeichen