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.
Hallo,
hab mir jetzt ein neues Board gemacht, mit einem ATMEGA8 (@16MHz) und einem ATTINY2313 (@16MHz). Den Servo-Befehl hab ich mir jetzt selbst geschrieben, funktioniert sehr gut. Allerdings habe ich jetzt ein neues Problem, welches vorher schon angesprochen wurde (glaube ich); und zwar kann es passieren, dass die Synchronisation verloren geht, d.h. der Wert vom 1. Motor (ATMEGAwird beim ATTINY2313 plötzlich zum Wert für den 2. / 3. / 4. Motor... Jetzt brauche ich eine Art Check, ob die Daten auch richtig zugeordnet werden, z.b. mittels einem Anfangs- und einem End-Byte?! Wäre das sinnvoll, oder denkt ihr, es gäbe eine einfachere / bessere / schnellere Lösung?
Hier mal die Codes:
ATTINY2313:
ATMEGA8:Code:$regfile = "attiny2313.dat" $crystal = 16000000 $framesize = 30 $hwstack = 30 $swstack = 30 $baud = 115000 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 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 For I = 1 To 4 _bl(i) = Min_servo Servo(i) = _bl(i) Next I Enable Interrupts Do Inputbin _bl(1) , 4 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 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
Beim ATMEGA8 hab ich schon die Summensignal-Auswertung mit drinen! Das WM+ (welches noch an den ATMEGA8 kommt), wird erst später hinzugefügt, wenn das jetzt mal funktioniert.Code:$regfile = "m8def.dat" $crystal = 16000000 $framesize = 80 $hwstack = 80 $swstack = 80 $baud = 115000 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 _maxchannel = 4 Dim Bufferbyte As Byte Dim Kanal(_maxchannel) As Byte Dim Channel As Byte Dim _bl(4) As Byte Dim I As Byte For I = 1 To 4 _bl(i) = 0 Next I Enable Interrupts Wait 1 Do For I = 1 To 4 _bl(i) = 200 - Kanal(i) Next I Printbin _bl(1) ; 4 Loop End Getreceiver: If Channel > 0 And Channel < 5 Then Kanal(channel) = Timer2 End If Timer2 = 6 Incr Channel Return Detectrxpause: Channel = 0 Return
Zur Hardware:
RxD vom ATTINY2313 ist mit TxD vom ATMEGA8 verbunden, DITO für die anderen beiden.
Ansonsten gibts IMHO keine wichtigen Infos über die Hardware (bzw. der Rest ist Standart), falls doch, einfach fragen
Vielen Dank
Gruß
Chris
Beim jetzigen Code werden nur rund 100 Werte genutz. Da wäre also im Prinzip noch 1 Bit frei um die Werte für einen Motor (z.B. Servor 1) zu markieren. Statt direkt dem Servo-Wert zu übertagen einfach eine Konstante anziehen, so das der Wert übertragene Wert kleiner als 128 bleibt. Bei einem Servo dann zusätzlich das Bit 7 setzen,so dass man da werte von 128 - 255 hat und den Wert gut erkennen kann.
Ein extra Start und stopp Wert würde auch gehen - man hat ja wenigstens 20 ms für jeden Datensatz.
Ein hohe Baudrate wird funktionieren, aber es gibt damit eine steigende Gefahr das man ein Wert verloren geht - bei den wenigen Daten sollten auch 19200 Baud oder so reichen.
Also die 115kBaud funktionieren sehr gut (bei 16MHz 0% Fehler), aber ich denke, werd mal runter gehen, wenn du das sagst.
Aber dann tritt wieder ein Problem auf:
Der Inputbin-Befehl wartet solange, bis alle Arrays (also hier 4) gefüllt sind. D.h. wenn ich einmal die Werte falsch zugewiesen habe, dann zieht sich diese Falschzuweisung durch bis zum bitteren Ende
Deswegen müsste ich, wenn ich einen Sync Fehler regisitriet habe, "neu von Vorne beginnen". Aber wie??
Kann ich z.b. NUR beim 1. Wert das 7. Bit setzen und dann immer Abfragen, ob dieses gesetzt ist. Wenn nicht, dann muss ich neu Syncronisieren, indem ich eine Schleife einbaue, die auf das 7. gesetzte Bit wartet?! Hier mal ein Code:
Werde das jetzt gleich mal ausprobieren, melde mich dann wieder. Aber wäre trotzdem nett, wenn du mal drüber schauen könntest und mir sagen könntest, ob das eine gute Lösung ist oder ob ichs anders machen soll?!Code:Inputbin _bl(1) ; 4 If _bl(1).7 = 0 Then 'Fehler While _bl(1).7 = 0 Inputbin _bl(1) ; 1 Wend Inputbin _bl(2) ; 3 End If Reset _bl(1).7
Gruß
Chris
Lesezeichen