So, ist ein bisschen später geworden, aber die Platine ist fertig und bestückt! Auf ihr befinden sich ein LM317 (SMD), 4 Wiederstande, 2 Kondensatoren, eine Wii Motion Plus und eine Nunchuk.
Ich kann beide Sensoren direkt hintereinander mittels I2C auslesen; beim WM+ bekomme ich akzeptable Werte (ich shifte die tatsächlichen Werte um 2 nach rechts, sprich ich teile durch 4), somit ist kein Drift mehr vorhanden (bzw. er ist normalweise schon so klein, dass er jetzt wegfällt). Hab zwar schon öfter gelesen, dass die WM+ ziemlich viel Drift hat, das kann ich jedoch nicht(!) bestätigen!
Leider verstehe ich den Nunchuk nicht so ganz... Einer der Werte (acc-z) steht für mich in keinem Verhältnis zu irgendeiner Bewegung der Platine?! ... Der Wert verändert sich zwar manchmal, aber ich wei0 nicht, wie genau ich die Platine bewegen muss, damit das passiert? Wo ist beim Nunchuk die Z-Achse?
Nun aber zu meiner eigentlichen Frage:
Wie kann ich die ACC-Daten mit den Gyros verrechnen? Irgendwo hab ich in letzer Zeit mal gelesen, dass man mit einem Kalman-Filter diese beiden Senoren kombinieren kann?! Hier im Forum gibt es ja bereits einen BASCOM-Code für einen Kalman, jedoch wei0 ich nicht, wo ich da die ACC-Werte einsetzen soll. Wäre toll, wenn mir das jemand erklären könnte?!
Hier mal mein momentaner Code:
Code:
$regfile = "m32def.dat"
$crystal = 16000000
$framesize = 150
$hwstack = 150
$swstack = 150
Declare Sub Pid_regulator()
Declare Sub Wmp_init()
Declare Sub Send_zero()
Declare Sub Read_wmp_data()
Declare Sub Set_wmp_offset()
Declare Sub Nunchuk_init()
Declare Sub Nunchuk_read()
Declare Sub Set_nunchuk_offset()
Declare Function Tastenabfrage() As Byte
Config Adc = Single , Prescaler = Auto
Start Adc
Config Pina.7 = Input
Porta.7 = 1
Dim Taste As Byte
Dim _direction As Byte
_direction = 1
$lib "I2C_TWI.LBX"
Config Scl = Portc.0
Config Sda = Portc.1
Config Twi = 100000
I2cinit
Config Lcd = 16 * 2
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5
Config Lcdbus = 4
Initlcd
Cursor Off
Cls
Locate 1 , 1
Lcd "*WM+ // NUNCHUK*"
Dim Nunchuk_buffer(6) As Byte
Dim Wmplus_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 _yawoffset_int As Integer
Dim _rolloffset_int As Integer
Dim _pitchoffset_int As Integer
Dim _yawnow As Integer
Dim _rollnow As Integer
Dim _pitchnow As Integer
Dim Acc_x As Byte
Dim Acc_y As Byte
Dim Acc_z As Byte
Dim Acc_x_now As Integer
Dim Acc_y_now As Integer
Dim Acc_z_now As Integer
Dim Acc_x_offset As Word
Dim Acc_y_offset As Word
Dim Acc_z_offset As Word
Dim Acc_x_offset_int As Integer
Dim Acc_y_offset_int As Integer
Dim Acc_z_offset_int As Integer
Dim Tmp As Byte
Dim I As Byte
Dim _yaw_kp_err As Integer
Dim _roll_kp_err As Integer
Dim _pitch_kp_err As Integer
Dim _yaw_ki_err As Integer
Dim _roll_ki_err As Integer
Dim _pitch_ki_err As Integer
Dim _yaw_ki_sum As Integer
Dim _roll_ki_sum As Integer
Dim _pitch_ki_sum As Integer
Dim _yaw_kd_err As Integer
Dim _roll_kd_err As Integer
Dim _pitch_kd_err As Integer
Dim _yaw_kd_old As Integer
Dim _roll_kd_old As Integer
Dim _pitch_kd_old As Integer
Dim _yaw_pid As Integer
Dim _roll_pid As Integer
Dim _pitch_pid As Integer
Dim _yaw_err As Integer
Dim _roll_err As Integer
Dim _pitch_err As Integer
Dim _sbl(4) As Integer
_sbl(1) = 0
_sbl(2) = 0
_sbl(3) = 0
_sbl(4) = 0
Const _yaw_kp = 1000
Const _roll_kp = 1000
Const _pitch_kp = 1000
Const _yaw_ki = 100
Const _roll_ki = 100
Const _pitch_ki = 100
Const _yaw_kd = 100
Const _roll_kd = 100
Const _pitch_kd = 100
Dim _yaw_filter As Integer
Dim _yaw_filter_2 As Integer
Dim _roll_filter As Integer
Dim _roll_filter_2 As Integer
Dim _pitch_filter As Integer
Dim _pitch_filter_2 As Integer
'DEBUG!!!
Dim Min_yaw As Integer
Dim Max_yaw As Integer
Dim Min_roll As Integer
Dim Max_roll As Integer
Dim Min_pitch As Integer
Dim Max_pitch As Integer
'########
Call Nunchuk_init()
Call Wmp_init()
Call Set_wmp_offset()
Call Set_nunchuk_offset()
Cls
Do
Call Read_wmp_data()
Call Nunchuk_read()
_yawnow = Yaw - _yawoffset_int
_rollnow = Roll - _rolloffset_int
_pitchnow = Pitch - _pitchoffset_int
Acc_x_now = Acc_x - Acc_x_offset_int
Acc_y_now = Acc_y - Acc_y_offset_int
Acc_z_now = Acc_z - Acc_z_offset_int
Call Pid_regulator()
If _yaw_pid < Min_yaw Then Min_yaw = _yaw_pid
If _yaw_pid > Max_yaw Then Max_yaw = _yaw_pid
If _roll_pid < Min_roll Then Min_roll = _roll_pid
If _roll_pid > Max_roll Then Max_roll = _roll_pid
If _pitch_pid < Min_pitch Then Min_pitch = _pitch_pid
If _pitch_pid > Max_pitch Then Max_pitch = _pitch_pid
Taste = Tastenabfrage()
If Taste <> 0 Then
If Taste = 1 Then Decr _direction
If Taste = 2 Then Incr _direction
If _direction > 3 Then _direction = 1
If _direction < 1 Then _direction = 3
End If
Cls
Locate 1 , 1
Lcd _yaw_pid ; " : " ; _roll_pid ; " : " ; _pitch_pid ; " "
Locate 2 , 1
If _direction = 1 Then
Lcd "YAW: " ; Min_yaw ; "/" ; Max_yaw ; " "
Elseif _direction = 2 Then
Lcd "ROLL: " ; Min_roll ; "/" ; Max_roll ; " "
Elseif _direction = 3 Then
Lcd "PITCH: " ; Min_pitch ; "/" ; Max_pitch ; " "
End If
'(
Cls
Locate 1 , 1
Lcd _yawnow
Locate 1 , 6
Lcd ": " ; _rollnow
Locate 1 , 11
Lcd ": " ; _pitchnow ; " "
Locate 2 , 1
Lcd Acc_x_now
Locate 2 , 6
Lcd ": " ; Acc_y_now
Locate 2 , 11
Lcd ": " ; Acc_z_now
Waitms 100
')
Loop
Sub Nunchuk_init()
I2cstart
I2cwbyte &HA4
I2cwbyte &H40
I2cwbyte &H00 .
I2cstop
End Sub
Sub Nunchuk_read()
I2cstart
I2cwbyte &HA4
I2cwbyte &H00
I2cstop
Waitms 1
Nunchuk_buffer(1) = 0
I2creceive &HA5 , Nunchuk_buffer(1) , 0 , 6
Acc_x = Nunchuk_buffer(3) Eor &H17
Acc_x = Acc_x + &H17
Acc_y = Nunchuk_buffer(4) Eor &H17
Acc_y = Acc_y + &H17
Acc_z = Nunchuk_buffer(5) Eor &H17
Acc_z = Acc_z + &H17
End Sub
Sub Set_nunchuk_offset()
Acc_x_offset = 0
Acc_y_offset = 0
Acc_z_offset = 0
For I = 1 To 100
Call Nunchuk_read()
Acc_x_offset = Acc_x_offset + Acc_x
Acc_y_offset = Acc_y_offset + Acc_y
Acc_z_offset = Acc_z_offset + Acc_z
Next I
Acc_x_offset = Acc_x_offset / 100
Acc_y_offset = Acc_y_offset / 100
Acc_z_offset = Acc_z_offset / 100
Acc_x_offset_int = Acc_x_offset
Acc_y_offset_int = Acc_y_offset
Acc_z_offset_int = Acc_z_offset
End Sub
Sub Wmp_init()
I2cstart
I2cwbyte &HA6
I2cwbyte &HFE
I2cwbyte &H04
I2cstop
End Sub
Sub Send_zero()
I2cstart
I2cwbyte &HA4
I2cwbyte &H00
I2cstop
End Sub
Sub Read_wmp_data()
Gosub Send_zero
I2creceive &HA4 , Wmplus_buffer(1) , 0 , 6
Yaw1 = Wmplus_buffer(1)
Roll1 = Wmplus_buffer(2)
Pitch1 = Wmplus_buffer(3)
Shift Wmplus_buffer(4) , Right , 2 : Yaw0 = Wmplus_buffer(4)
Shift Wmplus_buffer(5) , Right , 2 : Roll0 = Wmplus_buffer(5)
Shift Wmplus_buffer(6) , Right , 2 : Pitch0 = Wmplus_buffer(6)
Shift Yaw , Right , 2
Shift Roll , Right , 2
Shift Pitch , Right , 2
'IIR-Filter
'filter_wert = filter_wert * s + wert * (1.0-s)
_yaw_filter = _yaw_filter * 4
_yaw_filter = _yaw_filter / 10
_yaw_filter_2 = Yaw * 6
_yaw_filter_2 = _yaw_filter_2 / 10
_yaw_filter = _yaw_filter + _yaw_filter_2
Yaw = _yaw_filter
_roll_filter = _roll_filter * 4
_roll_filter = _roll_filter / 10
_roll_filter_2 = Roll * 6
_roll_filter_2 = _roll_filter_2 / 10
_roll_filter = _roll_filter + _roll_filter_2
Roll = _roll_filter
_pitch_filter = _pitch_filter * 4
_pitch_filter = _pitch_filter / 10
_pitch_filter_2 = Pitch * 6
_pitch_filter_2 = _pitch_filter_2 / 10
_pitch_filter = _pitch_filter + _pitch_filter_2
Pitch = _pitch_filter
End Sub
Sub Set_wmp_offset()
_yawoffset = 0
_rolloffset = 0
_pitchoffset = 0
For I = 1 To 100
Call Read_wmp_data()
_yawoffset = _yawoffset + Yaw
_rolloffset = _rolloffset + Roll
_pitchoffset = _pitchoffset + Pitch
Next I
_yawoffset = _yawoffset / 100
_rolloffset = _rolloffset / 100
_pitchoffset = _pitchoffset / 100
_yawoffset_int = _yawoffset + 10
_rolloffset_int = _rolloffset + 10
_pitchoffset_int = _pitchoffset + 10
End Sub
Sub Pid_regulator()
_yaw_err = _sbl(4) / 1
_yaw_err = _yaw_err - _yawnow
_roll_err = _sbl(3) / 5
_roll_err = _roll_err - _rollnow
_pitch_err = _sbl(2) / 5
_pitch_err = _pitch_err - _pitchnow
_yaw_kp_err = _yaw_kp_err * _yaw_kp
_yaw_kp_err = _yaw_err / 10
_roll_kp_err = _roll_kp_err * _roll_kp
_roll_kp_err = _roll_err / 10
_pitch_kp_err = _pitch_kp_err * _pitch_kp
_pitch_kp_err = _pitch_err / 10
_yaw_ki_err = _yaw_ki_err * _yaw_ki
_yaw_ki_err = _yaw_err / 50
_yaw_ki_sum = _yaw_ki_sum + _yaw_ki_err
_roll_ki_err = _roll_ki_err * _roll_ki
_roll_ki_err = _roll_err / 50
_roll_ki_sum = _roll_ki_sum + _roll_ki_err
_pitch_ki_err = _pitch_ki_err * _pitch_ki
_pitch_ki_err = _pitch_err / 50
_pitch_ki_sum = _pitch_ki_sum + _pitch_ki_err
_yaw_kd_err = _yaw_kd_err * _yaw_kd
_yaw_kd_err = _yaw_err / 50
_yaw_kd_err = _yaw_kd_old - _yaw_kd_err
_yaw_kd_old = _yaw_kd_old
_roll_kd_err = _roll_kd_err * _roll_kd
_roll_kd_err = _roll_err / 50
_roll_kd_err = _roll_kd_old - _roll_kd_err
_roll_kd_old = _roll_kd_old
_pitch_kd_err = _pitch_kd_err * _pitch_kd
_pitch_kd_err = _pitch_err / 50
_pitch_kd_err = _pitch_kd_old - _pitch_kd_err
_pitch_kd_old = _pitch_kd_old
_yaw_pid = _yaw_kp_err + _yaw_ki_sum
_yaw_pid = _yaw_pid + _yaw_kd_err
_roll_pid = _roll_kp_err + _roll_ki_sum
_roll_pid = _roll_pid + _roll_kd_err
_pitch_pid = _pitch_kp_err + _pitch_ki_sum
_pitch_pid = _pitch_pid + _pitch_kd_err
If _yaw_pid < -1000 Then _yaw_pid = -1000
If _yaw_pid > 1000 Then _yaw_pid = 1000
If _roll_pid < -1000 Then _roll_pid = -1000
If _roll_pid > 1000 Then _roll_pid = 1000
If _pitch_pid < -1000 Then _pitch_pid = -1000
If _pitch_pid > 1000 Then _pitch_pid = 1000
End Sub
Function Tastenabfrage() As Byte
Local Ws As Word
Tastenabfrage = 0
Start Adc
Ws = Getadc(7)
If Ws < 500 Then
Select Case Ws
Case 400 To 450
Tastenabfrage = 1
Case 330 To 380
Tastenabfrage = 2
Case 260 To 305
Tastenabfrage = 3
Case 180 To 220
Tastenabfrage = 4
Case 90 To 130
Tastenabfrage = 5
End Select
End If
Waitms 100
End Function
End
Wenn jemand ein Video vom Display sehen möchte, kann ichs schnell filmen! Die WM+ liegt seit ca. 30 Min neben mir und es gab noch keinen einzigen (!!!) "Ausbrecher". Ich denke, das genügt vollkommen zum fliegen?!
ABER:
Durch meine Division durch 4 verliere ich an Auflösung, d.h. ich muss auch die Werte für kp, ki, kd extrem hochschrauben... Denkt ihr, das ist ok oder würdet ihr das anders lösen?
Viele Fragen auf einmal, ich hoffe auf zahlreiche Antworten
Gruß
Chris
Lesezeichen