Das ging ja schnell
Mit der PWM-ISR ist der Servo-Befehl gemeint.
Wenn ich die Werte (4 mal 1Byte) mit Printbin übertrage, woher weiß ich dann, welcher empfangene Wert für welchen Servo / BL Motor zuständig ist?
Gruß
Chris
Das ging ja schnell
Mit der PWM-ISR ist der Servo-Befehl gemeint.
Wenn ich die Werte (4 mal 1Byte) mit Printbin übertrage, woher weiß ich dann, welcher empfangene Wert für welchen Servo / BL Motor zuständig ist?
Gruß
Chris
Zum Zuordnen der Motoren kann eine Wert (z.B. 0 oder 255 ) nutzen der der PWM Wert nicht vor kommt. Der Wert markiert dann den Anfang der Daten. Mann muss dann halt 5 Bytes statt 4 übertragen. Die UART kann dann langsamer laufen.
Ich habs gerade ausprobiert mit Printbin und Inputbin, allerdings habe ich jetzt ein neueres, größeres Problem. Hier mein Code auf dem ATTINY45:
Mit dem Oszi überprüfe ich den Ausgang des Servo(1)-Signals. Die Werte (78 und 100) stimmen zwar, jedoch ändert sich das Signal nicht jede Sekunde (wait 1), sondern nur ca. alle 5 bis 6 Sekunden. Clockdiv/8 ist deaktiviert, Clock output ist deaktiviert,Code:$regfile = "attiny45.dat" $crystal = 8000000 $framesize = 30 $hwstack = 30 $swstack = 30 Open "COMB.0:38400,8,N,1" For Input As #1 Config Pinb.0 = Input Config Servos = 4 , Servo1 = Portb.3 , Servo2 = Portb.2 , Servo3 = Portb.4 , Servo4 = Portb.1 , Reload = 4 , Intervall = 10 Config Portb.1 = Output Config Portb.2 = Output Config Portb.3 = Output Config Portb.4 = Output Dim _bl(4) As Byte Dim _blold(4) As Byte Dim I As Byte Const Min_servo = 78 '900µs Const Max_servo = 170 '2000µs For I = 1 To 4 _bl(i) = Min_servo _blold(i) = _bl(i) Servo(i) = _bl(i) Next I Enable Interrupts Do Servo(1) = 78 Wait 1 Servo(1) = 100 Wait 1 '( Inputbin #1 , _bl(1) , _bl(2) , _bl(3) , _bl(4) For I = 1 To 4 If _bl(i) <> 0 And _bl(i) <> 255 Then If _bl(i) >= Min_servo And _bl(i) <= Max_servo Then Servo(i) = _bl(i) End If End If Next I ') Loop End
100010:Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 64 ms; [CKSEL=0010 SUT=10]; default value,
und bod ist deaktiviert.
Warum braucht mein AVR so lange? Liegts am TINY? Hab in der BASCOM-Hilfe was von $tiny gelesen, allerdings gehen damit 90% meiner Instructions nicht mehr
Gruß
Chris
Ok, aber warum ist dann das Timing so grottenschlecht?
EDIT: Habs gerade probiert, wenn ich die Servo-Funktion auskommentiere und nur einen Pin im Sekundentakt toggln lasse, dann funzts wunderbar. Mit der Servo-Funktion dauerts jedoch ca. 6sek bis die neuen Werte übernommen werden?!
Ja, habs grad ausprobiert, bei mir kommen zwar die korrekten High-impluse raus, die Pausezeit (normal 20ms) dauert bei mir jedoch 200ms. Habs mit reload 100 und intervall = 100 gemacht, genau wie im Hilfe-Dokument.
EDIT: Mir ist gerade aufgefallen, dass ich "Interval" mit 2 statt einem l geschrieben habe. Das erzeugt zwar keinen Fehler, jedoch stimmt dann das Timing nicht mehr! Jetzt, richtig geschrieben, funktioniert es perfekt!
Jetzt habe ich 2 Probleme:
1. Der Wertebereich zur Servoansteuerung (bei mir 8 bis 19) ist zu klein. Eigtl. soll das eine Tricopter-Steuerung werden, da brauch ich auch PID-Regler usw.. Ich denke, dass damit zu ungenau geregelt wird?!
2. Der neue Wert, der per UART reinkommt, wird erst nach einer geschätzten Minute auf die Servo-Ausgänge gegeben.
Hier mal die Codes:
ATMEGA8:
ATTINY45:Code:$regfile = "m8def.dat" $crystal = 16000000 $framesize = 100 $hwstack = 100 $swstack = 100 Open "COMD.4:38400,8,N,1" For Output As #1 Dim _bl(4) As Byte Dim Channel As Byte Dim Kanal(4) As Byte Dim I As Byte For I = 1 To 4 _bl(4) = 80 Next I 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 Enable Interrupts Do For I = 1 To 4 _bl(i) = 8 Next I Printbin #1 , _bl(1) , _bl(2) , _bl(3) , _bl(4) Wait 3 For I = 1 To 4 _bl(i) = 10 Next I Printbin #1 , _bl(1) , _bl(2) , _bl(3) , _bl(4) Wait 3 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 liegt mein Fehler?Code:$regfile = "attiny45.dat" $crystal = 8000000 $framesize = 40 $hwstack = 40 $swstack = 40 Open "COMB.0:38400,8,N,1" For Input As #1 Config Pinb.0 = Input Config Servos = 4 , Servo1 = Portb.3 , Servo2 = Portb.2 , Servo3 = Portb.4 , Servo4 = Portb.1 , Reload = 100 , Interval = 100 Config Portb.1 = Output Config Portb.2 = Output Config Portb.3 = Output Config Portb.4 = Output Dim _bl(4) As Byte Dim _blold(4) As Byte Dim I As Byte Const Min_servo = 8 '900µs Const Max_servo = 19 '2000µs For I = 1 To 4 _bl(i) = Min_servo _blold(i) = _bl(i) Servo(i) = _bl(i) Next I Enable Interrupts Wait 2 Do Inputbin #1 , _bl(1) , 4 For I = 1 To 4 If _bl(i) <> 0 And _bl(i) <> 255 Then If _bl(i) >= Min_servo And _bl(i) <= Max_servo Then Servo(i) = _bl(i) End If End If Next I Loop End
Gruß
Chris
Das Problem für die beschränkte Auflösung dürfte der Servo Befehl sein. Da wird man wohl einen altenativen Code für die Servofunktion brauchen, und ggf. das auch von Hand im Interrupt programmieren müssen. Als Ansatzpunkt könnte der Code dienen:
http://www.rn-wissen.de/index.php/Servoansteuerung.
Man wird eventuell die UART langsamer (z.B. 4800 Baud) laufen lassen müssen. So schnell wird es ohnehin nicht benötigt für die paar Bytes. Ein Problem ist, das sowohl die Software UART, als auch der Servo Befehl Interrupts nutzen, und die können sich gegenseitig stören. Es würde etwas einfacher mit einem Tiny2313 statt Tiny45: der hat eine Hardware UART und einen 16 Bit Timer.
Der Tiny45 hat auch knapp Pins - da ist man dann auf den internen Takt angewiesen, und der ist von der Genauigkeit grenzwertig für die UART - da sollte man dann schon die Wortlänge auf 5 oder 6 Bits reduzieren, also von jedem Byte nur ersten 5 oder 6 auch benutzen. Bei den zuletzt übertragenen Bits steigt die Fehlergefahr schon.
Woher weißt du es bei deiner Version?
Du kannst natürlich auch ein komplizierteres Protokoll nehmen anstelle von 1.Wert ist 1. Servo, 2. Wert ist 2.Servo usw. Aber wofür, wenn du immer 4 Werte sendest. Anders sieht es aus, wenn du z.B. nur die Werte sendest, die sich ändern. Aber das macht bei 4 Byte keinen Sinn, weil dann der Overhead zum Auswerten dann viel zu groß wird.
Womit du eher ein Problem bekommen könntest ist die Synchronisierung, falls dir mal aus irgendeinem Grund ein Wert verlorengeht.
Lesezeichen