- LiFePO4 Speicher Test         
Ergebnis 1 bis 10 von 28

Thema: PWM und SOFTUART gleichzeitig

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    32
    Beiträge
    1.578
    Meinst du den letzten Code von mir? Was vermisst du den daran?
    Ok, werds mal mit 6 Bytes insgesamt probieren.

    Gruß
    Chris

    EDIT:
    Habs jetzt mal so probiert mit Start- und Stop-Byte, jedoch tut sich nichts... PWM wird zwar erzeugt, aber sie verändert sich nicht, d.h. die Werte werden nicht korrekt eingelesen?!
    ATTINY2313:
    Code:
    $regfile = "attiny2313.dat"
    $crystal = 16000000
    $framesize = 20
    $hwstack = 20
    $swstack = 20
    $baud = 19200
    
    
    
    Config Timer0 = Timer , Prescale = 1                        '100kHz
    Timer0 = 96
    On Timer0 Servo_irq
    Enable Timer0
    
    
    Config Portd.2 = Output
    Config Portd.3 = Output
    Config Portd.4 = Output
    Config Portd.5 = Output
    
    Const Start_byte = 0
    Const Stop_byte = 127
    
    Dim _start As Byte
    Dim _stop As Byte
    
    Dim Servo(4) As Byte
    Dim _ist As Byte
    Dim _bl(4) As Byte
    Dim I As Byte
    
    Const Min_servo = 65
    Const Max_servo = 160
    Const Diff_servo = Max_servo - Min_servo
    
    For I = 1 To 4
    _bl(i) = Min_servo
    Servo(i) = _bl(i)
    Next I
    
    
    Enable Interrupts
    
    
    Do
    
    
    Inputbin _start
    While _start <> Start_byte                                  'warte auf start
     Inputbin _start
    Wend
    Inputbin _bl(1) ; _bl(2) ; _bl(3) ; _bl(4) ; _stop
    
    If _stop = Stop_byte Then
     For I = 1 To 4
      If _bl(i) < Min_servo Then _bl(i) = Min_servo
      If _bl(i) > Max_servo Then _bl(i) = Max_servo
      Servo(i) = _bl(i)
     Next I
    End If
    
    
    Loop
    
    End
    
    
    Servo_irq:
    Timer0 = 96
    Incr _ist
    If _ist >= 200 Then _ist = 0
    If Servo(1) > _ist Then
     Portd.2 = 1
    Else
     Portd.2 = 0
    End If
    If Servo(2) > _ist Then
     Portd.3 = 1
    Else
     Portd.3 = 0
    End If
    If Servo(3) > _ist Then
     Portd.4 = 1
    Else
     Portd.4 = 0
    End If
    If Servo(4) > _ist Then
     Portd.5 = 1
    Else
     Portd.5 = 0
    End If
    Return
    ATMEGA8:
    Code:
    $regfile = "m8def.dat"
    $crystal = 16000000
    $framesize = 80
    $hwstack = 80
    $swstack = 80
    $baud = 19200
    
    
    Config Serialout = Buffered , Size = 20
    
    
    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 = 0
    Const Stop_byte = 127
    
    Const _maxchannel = 4
    
    Dim Bufferbyte As Byte
    Dim Kanal(_maxchannel) As Byte
    Dim Channel As Byte
    Dim _bl(_maxchannel) As Byte
    Dim I As Byte
    
    Dim Max_kanal(_maxchannel) As Byte
    Dim Min_kanal(_maxchannel) As Byte
    Dim Diff_kanal(_maxchannel) As Byte
    
    
    For I = 1 To _maxchannel
     _bl(i) = 0
     Max_kanal(i) = 100
     Min_kanal(i) = 100
     Diff_kanal(i) = Max_kanal(i) - Min_kanal(i)
    Next I
    
    
    Enable Interrupts
    
    
    Do
    
    '(
    For I = 1 To _maxchannel
     If Kanal(i) > Max_kanal(i) Then
      Max_kanal(i) = Kanal(i)
      Diff_kanal(i) = Max_kanal(i) - Min_kanal(i)
     End If
     If Kanal(i) < Min_kanal(i) Then
      Min_kanal(i) = Kanal(i)
      Diff_kanal(i) = Max_kanal(i) - Min_kanal(i)
     End If
    Next I
    ')
    
    For I = 1 To _maxchannel
     _bl(i) = Kanal(i)                                          '- Min_kanal(i)
    Next I
    
    
    Printbin Start_byte ; _bl(1) ; _bl(2) ; _bl(3) ; _bl(4) ; Stop_byte
    
    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
    Wo könnte mein Problem sein?
    Geändert von Che Guevara (14.05.2011 um 21:53 Uhr)

  2. #2
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Bei der Datenübertragung kann ist keinen Fehler finden. Ich würde da noch mal einen testlaufen lassen mit ggf. 1) einer LED die Blinkt, wenn Fehlerhafte Daten erkannt werden und / oder am Sender ein festes Muster senden, damit man weiss ob es an der Sender oder Empfängerhälfte hakt.

    Der Servo Code sieht mir komisch bzw. Fehlerträchtig aus: bei 100 kHz Frequenz für den Interrupt bleibt schon nicht viel Rechenzeit über. Da wäre es ggf. besser die Servopulse nacheinander zu machen - so bekommt man dann auch eine ausreichend lange Periodendauer: normal sind da 20 ms vorgesehen, in dem Programm werden das nur 2 ms. Wenn man die Pules nacheinander macht, kann man auch die Zeit direkt vom Timer bestimmen lassen - man braucht dann also nur einen Interruptaufruf pro Servo und könnte ggf. auch noch etwas mehr an Auflösung bekommen. Beim Code im RN Wissen wird das auch so gemacht, so weit ich mich erinnere.

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.01.2006
    Beiträge
    4.555
    Das Problem kann schon Input selber sein, Suche mal in der Bascom Hilfe nach GET. Dort werden auch Link's zu alternativen I/O Möglichkeiten geboten.

    Gruß Richard

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    32
    Beiträge
    1.578
    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:
    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
    ATTINY2313:
    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
    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.
    Geändert von Che Guevara (15.05.2011 um 18:56 Uhr)

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    32
    Beiträge
    1.578
    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 ATMEGA funktionierte alles so mittelmäßig:
    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
    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....
    Hier mal der Code:
    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
    ABER:
    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:
    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)
    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?

    Vielen Dank
    Gruß
    Chris

  6. #6
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    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.

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    32
    Beiträge
    1.578
    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)

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.09.2007
    Ort
    Berlin
    Alter
    32
    Beiträge
    1.578
    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:
    Code:
    $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
    
    End
    Jetzt funktioniert wenigstens schon mal der Fernbedinungsteil Der PID-Regler macht aber trotzdem noch nichts... Außerdem habe ich gerade ein für mich unerklärliches Phänomen entdeckt:
    Wenn ich
    Code:
    _bl(4) = _bl(4) - _yawnow
    schreibe, dreht sich der Servo (_bl(4)) in beide möglichen Richtungen, abhängig von der Drehung des WM+ (i-wie logisch ^^)
    Schreibe ich allerdings
    Code:
    _bl(4) = _bl(4) + _yawnow
    (man achte auf das "+" statt "-")
    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

Ähnliche Themen

  1. 2 ISR gleichzeitig?
    Von DerSchatten im Forum C - Programmierung (GCC u.a.)
    Antworten: 15
    Letzter Beitrag: 26.01.2010, 09:48
  2. Problem ISP und USI als i2c gleichzeitig
    Von vklaffehn im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 16.08.2007, 14:46
  3. 8 Aufgaben gleichzeitig?
    Von Athlonxp2000 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 7
    Letzter Beitrag: 28.12.2006, 14:15
  4. 2 Interrupts gleichzeitig???
    Von x8r im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 23.01.2006, 18:49
  5. 16 IOs und LCD (quasi-gleichzeitig)
    Von lanzelot im Forum C-Control II
    Antworten: 13
    Letzter Beitrag: 01.02.2005, 04:21

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test