Hallo, für den Bau eines “elektrischen Insekts” benötige ich eine Steuerung für 18 Servos. Meine Grundidee ist, einen AVR für die Grundsteuerung der Bewegung des "Tierchens" zu benutzen, der seriell die entsprechenden Datan an die Servotreiber (also die ICs, die die Servos selber steuern) übermittelt. Auf der Suche nach einem solchen IC habe ich in einem Elektor-Buch das IC mit der Bezeichnung FT639 entdeckt, welches angeblich bei www.elabinc.com erhältlich sein soll (habe es dort aber nicht entdeckt). Es soll in der Lage sein, jeden Servo in 256 Stufen (auf 180Grad) zu bewegen, was meiner Anwendung sehr entgegenkommen würde. Da das mein erster Schritt in Richtung Servosteuerung ist, wollte ich hier vorher nachhören, welche Möglichkeiten es vielleicht sonst noch gibt, vielleicht kennt ja sogar jemand einen besser erhältlichen Baustein, der möglicherweise sogar noch mehr Servos ansteuern kann. Viele Grüsse!
Du koenntest auf 2 Pins des AVR PPM-Signale fuer jeweils 10 Servos erzeugen und jeweils einen CD4017B Dekadenzaehler nachschalten. Einfache Empfaenger machen das im Prinzip auch so...
Ein weiterer AVR als Servocontroller wäre super!!! Ist die Frage, wo man ein entsprechendes Programm findet. Nebenbei habe ich einen 20-fach-Servocontroller entdeckt, den SD20 http://www.robot-electronics.co.uk/shop/Servox39s2010.htm Der Haupt-AVR wird wahrscheinlich schon ziemlich ausgelastet sein. Aber ein M8 oder M16 als "Servo-Helfer" wäre eine coole Sache!
...aber mal Hand aufs Herz: so eim M16 o.ä. wird ja wohl kaum in der Lage sein können, 18 Servos zu steuern. Der bräuchte dann ja neben den beiden Hardware-PWM-Ausgängen noch 16 Software-PWM-ausgänge... nebenbei: wie soll das mit dem CD4017B funktionieren? Würden die Servos ihre Position halten?
Wolfram schrieb: > ...aber mal Hand aufs Herz: > > so eim M16 o.ä. wird ja wohl kaum in der Lage sein können, 18 Servos zu > steuern. Der bräuchte dann ja neben den beiden Hardware-PWM-Ausgängen > noch 16 Software-PWM-ausgänge... Wenn ich mir das Timing und die Empfangsroutine meiner 8 Kanal Servosteuerung mit einem Mega16 anschaue sollte es absolut kein Problem sein die auf 16 oder mehr Kanäle zu erweitern. Ich kann einfach per RS232 bzw. UART den Gewünschten Servo und Stellwinkel auswählen und fertig. Dazu noch spezifische Kommandos wie "Jedes zweite Servo auf Winkel X fahren". So könnte man auch wiederholende Bewegungen einprogrammieren. Ein Kommando für "Geradeaus laufen", eines für "lauf nach Links" und so weiter. Mfg, Peter
Ein Atmega8 reicht dafür gut aus, selbst schon mal gemacht. Wenn Bedarf besteht, räum ich den Code mal auf und poste. Hab das vor 3 Jahren geschrieben...
Der SD20 wird über I2C angesprochen. Glaube, er läßt sich deshalb per AVR nicht direkt ansteuern. Experten, was meint Ihr?
@Andreas R.: an dem Code habe ich Interesse. Wie wird der M8er denn in dem Fall angesteuert, wie viele Servos sind max. möglich und wie viele Stufen gibt es auf 180 Grad Servobewegung? @Peter F.: was müsste man denn ändern, um den M16 18 Servos steuern zu lassen? Die Servobewegungen selber wollte ich über den "Haupt-AVR" abwickeln, wahrscheinlich muss jeder Servo einzeln kalibriert werden.
> so eim M16 o.ä. wird ja wohl kaum in der Lage sein können, 18 Servos zu > steuern. Der bräuchte dann ja neben den beiden Hardware-PWM-Ausgängen > noch 16 Software-PWM-ausgänge... Aber sicher ist er das, jedenfalls für die klassischen Modellbauservos. Jedenfalls dann, wenn er genug Pins hat und nicht mehr viel anderes tun muss.
Also für einen AVR sind 20 Servos kein Problem, alle 2Millisekunden zwei Interrupts mit minimalem Aufwand, und das wars. Schätzungsweise sind es 400Takte die du alle 2ms an die Servos abtreten müsstes.(ich gebe zu bedenken dass er in 2ms locker 30000 Takte ausführt) So ein Servo muss nämlich nur alle 20ms mit einem 1-2ms andauernden High-Pegel angesteuert werden, die dafür zuständigen Interrupts werden nur am Beginn und am Ende dieser Flanken ausgelöst. Das ist mit einem 16Bit Timer und zwei Output-Compare-Registern mit ebenso 2Output-Compare-Interrupts, die jeweils während einer 20ms Zeitscheibe 10 1-2ms-Flanken für ebensoviele Servos erzeugen, leicht machber.
Also wenn das so ist, würde ich gerne einen M16 für die Steuerung von 18 Modellbau-Servos programmieren. Das Problem wird aber sein, dass ich zwar schon mal ein bisschen bei C und ASM reingeschnuppert habe, ansonsten aber in Bascom programmiere, was für meine "makroskopischen" Steuerzwecke völlig ausreicht. Für so eine Servosteuerung wird das eher nix sein, schätze ich. Aber wir können ja erst mal "hinten" anfangen. Dann ergeben sich folgende Fragen: -Welche Anschlüsse sollen für die Servos benutzt werden und welche läßt man lieber frei? (RX läßt man wahrscheinlich besser frei ;)) -Wie hoch muß der Controller mindestens getaktet sein (Energiesparen) und ist ein externer Oszi notwendig? -Wie sollen die Steuerdaten übermittelt werden (Baudrate etc.)?
Hier steuert ein Mega48 mit 1MHz getaktet 7 Servos im Hintergrund (Interrupt): http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html 6 Positionen werden per ADC von Kreuzknüppeln eingelesen, die 7. per Taster. Es sollte kein Problem sein, die Positionen in einem Array im SRAM zu halten. Es sollte auch kein Problem sein, die Kette auf bis zu 12 Servos zu erweitern und mit der zweiten Compare-Einheit weitere 12 Impulse zu erzeugen. Die 20ms werden dann zwar nicht eingehalten (wenn eine Kette fertig ist, beginnt sie einfach von vorn), das macht aber nichts, die Servos laufen auch mit mit nicht so exaktem Impulsabstand zufriedenstellend. In einer Steuerung für Bahnschranken (langsame Bewegung erwünscht) beträgt der Impulsabstand 64ms, das funktioniert wunderbar und braucht weniger Strom. Also ein Mega8515 (wegen der Pins) kann ohne weiteres 24 Servos (an 3 Ports) ansteuern, deren Positionswerte im SRAM gehalten werden und vom Mega8515 selbst berechnet werden können. Ein anderer Controller kann dann über SPI (braucht keinen Quarz, der Mega8515 kann dabei mit 1MHz intern laufen) oder U(S)ART (braucht im Synchronmode auch keinen Quarz) Befehle zum Bewegungsablauf (vordefinierte Sequenzen im Flash oder EEP) senden. Der 8515 wird sich bei 1MHz Takt dabei langweilen und über 70% der Rechenzeit im Sleep verbringen, effiziente Programmierung in ASM (oder C vom Könner) vorausgesetzt. Wenn es unbedingt sein muss, dann geht das auch in BASCOM, dann braucht es allerdings einen 16MHz-Quarz, um das Pensum zu schaffen. ...
> -Wie hoch muß der Controller mindestens getaktet sein (Energiesparen) > und ist ein externer Oszi notwendig? Externer Oszi auf jeden Fall, da das Timing stimmen sollte. Energiesparen würd ich mal vergessen - die Servos fressen um Grössenordnungen mehr Saft als dass der Controller noch interessieren würde. Und ja, um C oder Assembler wirst du kaum herumkommen. Ist aber auch nicht weiter schlimm, denn so lernst du den Prozessor wirklich verstehen und kannst ihn - auch was das Timing angeht - wirklich genau steuern.
> Externer Oszi auf jeden Fall, da das Timing stimmen sollte. Naja, für halbwegs reproduzierbare Servopositionen reicht der interne Oszillator völlig aus. Ein Quarz wird erst bei Verwendung von UART (asynchrone Betriebsart) erforderlich. > Und ja, um C oder Assembler wirst du kaum herumkommen. C alleine wird nicht reichen, ohne ASM-Grundkenntnisse (also das Wissen, was auf dem AVR-Kern machbar ist und wie man den C-Compiler dazu bringt, es so und nicht anders zu compilieren) kann man auch in C keinen effizienten Code schreiben, denn der AVR kann kein C. ;-) Bei Verwendung von zwei der oben erwähnten 4017-Ringzähler reicht ein Tiny2313 völlig aus, 18 oder 20 Servos zu steuern (18 bei Einhaltung der 20ms, 20 bei freiem Rundlauf). Bei 1MHz Timertakt (bei 1MHz oder 8MHz CPU-Takt) sind zwischen 1,0ms und 2,0ms 1000 Schritte, zwischen den Servo-Endlagen (etwa 0,7ms..2,3ms) etwa 1600 Schritte, das ist eine recht brauchbare Auflösung, die wird ein preiswertes Servo nicht exakt umsetzen können (ist ja auch nicht nötig). ;-) ...
@Wolfram: Lass dich nicht verunsichern. Ohne Assembler gehts auch, man muss in dem Fall nur wissen was ein Interrupt oder Timer-Counter macht. Ich würde zwar auch C empfehlen glaube aber nicht, dass das mit Bascom unmöglich ist.
Danke für die Infos! Bascom besitzt ja auch eine eigene Servo-Routine. Ich hatte mal ein wenig damit rumexperimentiert. Mein Ergebnis war, dass man einen Servo mit einer Auflösung von 100 Schritten auf 180 Grad gut benutzen kann. Dann hatte ich es mit 8 Servos versucht, das Ergebnis war katastrophal: die Auflösung ging auf ungefähr 20 Schritte pro 180 Grad zurück, gleichzeitig tuckerten die Servos nur so vor sich hin, hatten überhaupt keine Kraft meht. Ok, jetzt muss ich noch mal überlegen... Ein Servo wird über einen kontinuierlichen Puls gesteuert. Die Pulslänge von ca. 1 bis 2 mS entscheidet über die Servostellung. Die Zeit zwischen den Pulsen ist nicht so kritisch und wird meistens mit 40 bis 50 mS veranschlagt. Stimmt das so?
Gut, die fertigen Bascom Routinen sind also Mist. Ich schätze aber mal selbst in Bascom kann man 16Bit-Timer mit zwei Output-Compare-Interrupts betreiben. 40 50ms sind etwas viel. Je näher du an 20ms kommst desto besser, bei analogen Servos wirkt sich nämlich die Rate mit der du die Servos ansteuerst auch auf die Kraft aus.
schau dir den ssc32 an, ist open source. Das ist ein Servo controller fuer 32 servos mit dem atmega8.
> glaube aber nicht, dass das mit Bascom unmöglich ist.
Unmöglich wird es in Bascom nicht, aber sehr wackelig. Das hat folgende
Gründe (kein Anspruch auf Vollständigkeit):
- Bascom hält die Variablen im SRAM, in ASM kann man gezielt mit
Registern arbeiten, was bedeutend schneller geht.
- Bascom sichert bei Aufruf einer ISR alle 32 Register. Das kostet
128 Takte, die in der ISR zusätzlich verbraucht werden. In ASM kann
man die in der ISR benötigten Variablen in Exklusiv-Registern
halten (also einige Register nur für die ISR reservieren), so dass
in der ISR neben der eigentlichen Arbeit nur das SREG gesichert
werden muss, und das am besten auch in einem Exklusivregister.
Es gibt zwar in Bascom die Möglichkeit, das Sichern der Register
zu verhindern, dazu muss man aber sehr genau wissen, was man macht.
Es sind also neben sehr guten Basic-Kenntnissen auch fundierte ASM-
Kenntnisse erforderlich.
- Das Kern-Programm (Erzeugung der 24 Servoimpulse gemäß der
Positionswerte, die per SPI empfangen werden) ist so klein und
überschaubar, dass es ein ideales ASM-Einsteigerprojekt ist.
Ich würde eine Lösung mit Mega8515 favorisieren und erstmal nur
Impulserzeugung und SPI-Slave implementieren.
Oder UART statt SPI, dann aber mit Baudraten-Quarz 7,3728 MHz, was eine
geringe Stauchung der Positionswerte (Faktor 0,9216) zur Folge hat (eine
Millisekunde entspricht dann nicht mehr dem Wert 1000, sondern dem Wert
921,6, also 922).
Da der Mega8515 in Hardware multiplizieren kann, bietet es sich an, die
zu übertragenden Positionswerte so klein zu halten, dass sie in ein Byte
passen. Z.B. Wertebereich von 0 bis 249, wobei die Werte ab 250 bis 255
als Kennung (mit "Gerätenummer", also Adresse des gewünschten
Servotreibers) genommen werden, also dass der nächste Wert Kanal 0 des
adressierten 8515 entspricht (alle nicht adressierten 8515 hören einfach
nicht zu, bis sie ihre eigene Adresse emfangen). Ein Telegramm besteht
dann aus der Kanal-0-Kennung (mit Geräteadresse) und 24 Bytes Daten für
die Positionen der Kanäle 0 bis 23, hat also insgesamt 25 Bytes.
Damit kann die Schnittstelle zum Hauptcontroller (der durchaus mit
Bascom programmiert sein darf) sehr einfach und überschaubar gehalten
werden, der Hauptcontroller kann damit aber bis zu 16 "Servotreiber" mit
je bis zu 24 Servos über nur eine einzige Leitung (TXD) per UART
ansteuern. Die RXD-Leitungen der Mega8515 werden dazu einfach parallel
geschaltet.
Dieses Protokoll ist natürlich auch per SPI nutzbar, falls am
Hauptcontroller UART nicht mehr frei sein sollte. Die Übertragung
braucht auch nur unidirektional zu sein, da Servos keine Rückgabewerte
haben.
Irgendwie hätte ich Lust, das Programm dazu zu schreiben. Leider fehlt
mir dazu die Zeit und auch die Motivation. Denn ich selbst brauche es
nicht, ich baue keine Roboter...
...
Korrektur... Bei Positionswerten von 0 bis 249 bleiben natürlich nur 6 Geräteadressen. Irgendwie ging ich von 240 Werten + 16 Adressen aus. Sinnvoll könnte aus sein, die Werte auf 180 zu begrenzen und als Grad zu betrachten. Im Mega8515 reicht dann eine Multiplikation mit 10 und Addition von 600, um den Bereich von 600 bis 2400 abzudecken, der von Anschlag zu Anschlag reichen dürfte. ...
hallo hannes, danke für die anregungen! ich werde jetzt erst mal ein paar tests unter bascom durchführen bezüglich der servo-stellwerte und des haltevermögens vorgegebener werte. die servo-adressierung und das datenübertrgagungsprotokoll wären dann der nächste schritt.
> danke für die anregungen!
Na dann gibt es noch ein paar weitere Anregungen in Form meiner
Schmierzettel zum Thema... ;-)
(Ist natürlich nur so aus dem Hut gekritzelt, da wird noch dieser oder
jener Fehler drin sein...)
...
Den ersten Fehler habe ich schon entdeckt: STD z+32,r1 muss natürlich STD z+16,r1 heißen... ;-) ...
Mal ne kurze Zwischenfrage: Kann man bei Bascom im Output-Modus nicht gezielt einzelne Pins mit pinx.y setzen? Sonst mache ich das immer so: config porta = output porta = 1 (pina.0 wird auf high gesetzt) dagegen config porta = output pina.0 = 1 funktioniert nicht! config pina.0 = output pina.0 = 1 funktioniert auch nicht!
Man kann (auch) in Bascom den I/O-Registern die Werte zuweisen. Dazu schaut man sich mal im Datenblatt des AVRs an, welche I/O-Register zu einem Port gehören und spricht diese direkt an. Was in ASM so aussieht: ldi r16,0b00001111 out ddrb,r16 kann in Bascom etwa so aussehen: ddrb=&b00001111 Da der AVR keinen Maschinenbefehl zum Ausgeben einer Konstante an ein I/O-Register kennt, muss der Compiler da was draus machen, was der AVR kennt. Im besten Fall kommt das ASM-Beispiel bei heraus. Das direkte Zuweisen von Werten zu I/O-Registern hat gegenüber den Config-Anweisungen den Vorteil, dass man flexibler ist, also Hardware-Features nutzen kann, die von Config nicht unterstützt werden. ...
>Man kann (auch) in Bascom den I/O-Registern die Werte zuweisen. Dazu >schaut man sich mal im Datenblatt des AVRs an, welche I/O-Register zu >einem Port gehören und spricht diese direkt an. Hannes, du hast da was falsch verstanden: Der Poster hat ein Problem damit in der PortX.PinY-Schreibweise einen Portpin zu setzen. Das ist eher ein Bascom-betreffendes Problem... Darüber sollte es im Handbuch eine Erklärung geben...
> in der PortX.PinY-Schreibweise Dafür gibt es glaube Set und Reset, ich bin aber jetzt zu faul, in der Hilfe nachzuschauen, noch dazu, wo ich ein Bascom-Muffel bin. Trotzdem stehe ich dazu, dass das Verwenden der Config-Anweisung für im AVR vorhandene Features kontraproduktiv ist. Für Software-Module ist Config ok, aber für die interne Hardware nicht, da fördert es nur die Unwissenheit betreffs der Möglichkeiten der Hardware. ...
Hm, trotzdem merkwürdig, dass Bascom den Befehl PinX.Y=Z nicht zur Verfügung stellt. (in der Hilfe wird pin... nur in Verbindung mit input aufgeführt) Einerlei... Ich hab die Sache jetzt anders in den Griff bekommen und die Steuerung erst mal für einen Port, also 8 Servos fertiggestellt. Das funktioniert auch prima; nun stellt sich nur langsam die Frage, in welcher Form die Daten vom Hauptcontroller (M32) an den Servosteuerer (M8) übermittelt werden sollen. Gibt es irgendwelche Standards bezüglich Parität, Baudrate, Stopbit usw., welche sich hier anbieten würden (bin mit dem UART nicht so vertraut)? Reicht es, die Daten wie beim Midi-Protokoll einseitig zu senden oder wäre eine Rückmeldung (Handshake?) empfehlenswert? So weit ich weiß, kann man den Oszillator vom M32 so einstellen, dass er einen zweiten Controller direkt mittakten kann, das wäre sicher auch gut im Hinblick auf die zu übertragenden Daten...
> trotzdem merkwürdig, dass Bascom den Befehl PinX.Y=Z > nicht zur Verfügung stellt. Wieso? Marc hat sich für set Portx.y reset Portx.y und toggle Portx.y entschieden, reicht Dir das nicht? Mit Pinx.y hat das übrigens keinen Sinn. Nur einige ganz neue AVRs erlauben damit das Togglen. Du solltest Dir nochmal die I/O-Register PORTx, DDRx und PINx genauer ansehen. ...
Übrigens, Hannes, Danke für das Posting des "Schmierzettels"! Ich bin beeindruckt!!! Wenn das jetzt mit Bascom nicht geklappt hätte, wäre mein nächster Schritt Richtung ASM gewesen. Aber aufgeschoben ist nicht aufgehoben ;) Kann noch mal jemand was zum Thema Datenübertragung von Controller zu Controller posten? Ich wollte das fertige Programm wenn alles klappt nämlich allgemein zur Verfügung stellen und da ist es sicher interessant die Frage zu klären, welches Datenübertragungsprotokoll hier sinnvoll ist (damit auch jemand anderes was damit anfangen kann und ich quasi nicht nur mein eigenes Süppchen koche).
> Kann noch mal jemand was zum Thema Datenübertragung von Controller zu > Controller posten? Naja, da müsstest Du Dich mal im Roboternetz umsehen. Ich vermute, dass sich da schon Andere Gedanken gemacht haben. Wenn ich es machen müsste, würde ich zusehen, dass jedes Byte für sich einen unmissverständlichen Sinn ergibt. Ich dachte an: 0..179 Positionswert eines Servos 240..255 Startkennung (Kanal 0) mit Geräte-Adresse (alle nicht adressierten Geräte hören weg, bis eigene Adresse kommt) 180..211 Voreinstellung der Servonummer, wenn nur die Position eines einzelnen Servos verändert werden muss 212..239 Befehlscodes für spätere Erweiterungen (z.B. Ausführen vordefinierter Ablaufsequenzen aus dem Flash) Das ergäbe folgende Möglichkeiten (für Mega8515 mit 32 Servo-Kanälen, Quarz und UART-RX): - Telegramm mit 33 Bytes für alle 32 Servos: Gerätenummer (gilt als Startkennung, setzt Index auf 0), 32 Positionsdaten - Telegramm mit 3 Bytes für Einzelservo: Gerätenummer (240..255), Servonummer (180..211), Position (0..179) - Telegramm mit 5 Bytes für 2 beliebige Einzelservos: Gerätenummer, Servonummer1, Position1, Servonummer2, Position2 - Telegramm für beliebige Servogruppen: Gerätenummer, Servonummer1, Position, Position des nächsten Servos, Position des übernächsten Servos, ..., Servonummer2, Position, Position, ... Die Gerätenummer (240..255) dient also zur Auswahl des Controllers (bis zu 16 möglich) und zum Positionieren des Index (Servonummer) auf das erste Servo. Die Servonummer (180..211) verstellt den Index (Schreibpointer). Die Position (0..179) wird an den aktuellen Index geschrieben und der Index wird um 1 erhöht. Wird dabei das Array-Ende erreicht, wird RX deaktiviert. Um RX wieder zu aktivieren, muss die Gerätenummer empfangen werden. Die Verbindung erfolg unidirektional. Der Master muss (über TXD) senden, die (an RXD parallelgeschalteten) Slaves empfangen nur. Das ergibt keinerlei Kollisionen. Mit der Baudrate würde ich (trotz Baudratenquarz) auf dem Teppich bleiben, also 19200 oder 38400 Baud. Ein Teil der Gerätenummern kann übrigens für Sensor-Controller verwendet werden, die dann eine bidirektionale UART-Übertragung brauchen. Über die Gerätenummer wählt man ihn aus und aktiviert ihn, mit einem Befehlscode sagt man ihm, was man von ihm will, worauf er das Gewünschte zurücksendet. Hier sind die TXD-Leitungen mehrerer Slaves mit Dioden zu entkoppeln (gemeinsamer PullUp). Da immer nur ein Slave senden darf, gibt es keine Kollisionen. Und da der Master den Slave zuvor ansprechen muss, weiß der Master auch, was ihm gesendet wird und wie er die Daten zu interpretieren hat. Aber wie gesagt, ich würde es so machen, wenn ich vor dem Problem stünde, wie es die Roboterfreaks machen, weiß ich nicht. ...
Man könnte die Kommunikation zwischen den Controllern auch mit 9 Bits machen... Oder so wie beim DMX-Protokoll. Da sind niemandem Grenzen gesetzt.
also die stellwerte der servos sind 0 bis 241 auf 180 grad. Hm, hm, hm, da gibts ja ganz schön viele möglichkeiten für die datenübertragung. was ich mir auch noch überlegt hatte, war eine startwertübermittlung der servos, die im controller dauerhaft gespeichert bleiben. so würde man wilde zuckungen vermeiden ;) ich werde mal beim roboternetz nachfragen, welches datenübertragungsprotokoll sich anbietet... @hannes: als kleines asm-einsteigerprojekt hatte ich überlegt, eine led 10 mal blinken zu lassen. kann man irgendwo im netzt was zur asm-programmierung in bezug auf avr-controller finden?
> also die stellwerte der servos sind 0 bis 241 auf 180 grad. Nöö, ich dachte an 0 bis 179 (oder von mir aus 180). Danach kommen 32 Werte, die dazu dienen, den Zeiger auf die Servonummer (Datensatz-Index) zu verändern, um einzelne Servos gezielt ansprechen zu können, ohne immer die Positionsdaten aller Servos übertragen zu müssen. Dies geht dann bis 211, wenn man von 32 Servos ausgeht. Und danach sind noch einige Nummern frei (212 bis 239). Diese können für komplexere Kommandos genutzt werden. > Hm, hm, hm, da gibts ja ganz schön viele möglichkeiten für die > datenübertragung. Das ist ja der Sinn der Sache. Der Hauptcontroller kann sich im Einzelfall aussuchen, welche Variante im Einzelfall am effektivsten ist. Sind viele Positionen gleichzeitig zu ändern, dann lohnt sich das Telegramm mit allen Werten. Sind nur wenige Positionen zu ändern, dann lohnt sich der Einsatz der Servonummer, also der Manipulation des Zeigers auf die Datensätze. > was ich mir auch noch überlegt hatte, war eine startwertübermittlung der > servos, die im controller dauerhaft gespeichert bleiben. > so würde man wilde zuckungen vermeiden ;) Nichts leichter als das... (sagte Fredderick) Man nehme eine Nummer aus dem Kommando-Bereich, auf die der Controller die akuellen Positionsdaten ins EEP schreibt. Die Reset-Routine prüft dann den EEP-Inhalt und setzt diesen als Startwert ins RAM-Array, falls die Daten im gültigen Bereich (also unter 180) liegen. Sind die Daten ungültig, wird die entsprechende Position mit Mittelstellung (90) initialisiert. Um dieses Feature einfach zu halten, sollte die Skalierung des Positionswertes auf das Timer-Intervall in die Servo-ISRs verlagert werden, die paar Takte zusätzlich verkraften die ISRs noch. > ich werde mal beim roboternetz nachfragen, welches > datenübertragungsprotokoll sich anbietet... Na ich habe Dir doch ein Protokoll vorgeschlagen, das sehr einfach zu bedienen ist und trotzdem recht flexibel ist. Wo steht denn geschrieben, dass Dein Robbi mit denen anderer Bastler kompatibel sein muss? Wenn das Protokoll von Anderen für gut empfunden wird, werden diese es auch nutzen. > @hannes: als kleines asm-einsteigerprojekt hatte ich überlegt, eine led > 10 mal blinken zu lassen. kann man irgendwo im netzt was zur > asm-programmierung in bezug auf avr-controller finden? Das hiesige Forum hat ein AVR-Tutorial (eigentlich 2, eins für ASM und eins für C). Dann gibt es noch das AVR-ASM-Tutorial von Herrn Schmidt, das ist für die ersten Schritte auch verdammt gut. Falls Du ein paar ASM-Programme analysieren möchtest, so findest Du bei mir ein paar Quelltexte: http://www.hanneslux.de/avr/index.html ...
kurze Zwischenmeldung: im Roboterforum hat eben jemand vorgeschlagen, die Daten parallel zu übermitteln.
Wolfram schrieb: > kurze Zwischenmeldung: > > im Roboterforum hat eben jemand vorgeschlagen, die Daten parallel zu > übermitteln. Mit welcher Begründung? Das ist Pinverschwendung.
> im Roboterforum hat eben jemand vorgeschlagen, Es geht nicht darum, was Jemand vorgeschlagen hat, sondern darum, ob sich schon ein bereits bestehendes Protokoll als "Standard" durchgesetzt hat. Ist dies der Fall, dann wäre es vermutlich nicht schlecht, sich daran zu halten und mein Konzept zu verwerfen. Ist dies nicht der Fall, dann lohnt es sich, über mein Konzept nachzudenken. Ich bin am Überlegen, ob es nicht sinnvoll ist, die UART-Übertragung doch bidirektional zu machen, gestattet es doch eine Rückmeldung bei komplexeren Kommandos. Sobald ich etwas Zeit und Muße finde, werde ich das Konzept mal in Software gießen, eine Kleinversion mit Tiny2313 (14 Servos, ohne Rückkanal) und die Maxi-Version mit Mega8515 (32 Servos, mit Rückkanal, da hier (später mal) komplexere Kommandos eingebaut werden können). Vielleicht wird es auch noch eine mittlere Version mit Mega8 (18 Servos, mit Rückkanal). Oder nur eine der drei Möglichkeiten? Zum 4017: Ich hätte damit kein Problem, obwohl ich persönlich eine Einchip-Lösung bevorzuge. Mir ist also ein einzelner Mega8515 lieber als ein kleinerer AVR und mehrere 4017, schon wegen der Platine. Und wenn ich mehr als zwei Logik-ICs durch einen AVR ersetzen kann, so mach' ich das auch (sofern es nicht um hohe Frequenzen geht, die der AVR nicht schafft). Die Ansteuerung der 4017 direkt vom Zentralcontroller dürfte den Roboterbauern Probleme bereiten, da sie in Bascom werkeln und mangels Ressourcen kaum neben dem Hauptsteuerprogramm noch das Timing für 3 oder 4 4017 beherrschen werden. Da halte ich es schon für sinnvoll, das Timing der Servosteuerung auf einen (oder mehrere) eigenen AVR zu auszulagern und diesen per UART mit Daten zu versorgen. Das Senden eines simplen UART-Telegramms ist auch in Bascom mal so nebenher möglich. ...
Hannes Lux schrieb: > Die Ansteuerung der 4017 direkt vom Zentralcontroller dürfte den > Roboterbauern Probleme bereiten, da sie in Bascom werkeln und mangels > Ressourcen kaum neben dem Hauptsteuerprogramm noch das Timing für 3 oder > 4 4017 beherrschen werden. Ich habe zugegebenermassen von Bascom gar keine Ahnung, aber sehr Zeitkritisch ist das eigentlich nicht - wenn man das PPM-Signal vom Timer generieren laesst. Und im Interrupt alle 2ms 2 mal den Timer mit einem neuen Wert laden sollte auch Bascom koennen, auch wenn es mit 3 oder 4 Timern parallel gemacht wird?
Im Prinzip ja, aber Bascom sichert in der ISR alle Register, auch die, die nicht benutzt werden. Bei mehreren "Ketten" werden die ISRs gelegentlich Schlange stehen, da sie aufgrund der unnötigen Sicherung unnötig lange dauern. Das wird etwas Jitter verursachen. Ich würde es jedenfalls versuchen zu vermeiden... ...
Hannes Lux schrieb: > Im Prinzip ja, aber Bascom sichert in der ISR alle Register, auch die, > die nicht benutzt werden. Bei mehreren "Ketten" werden die ISRs > gelegentlich Schlange stehen, da sie aufgrund der unnötigen Sicherung > unnötig lange dauern. Das wird etwas Jitter verursachen. Ich würde es > jedenfalls versuchen zu vermeiden... Naja, der Signalwechsel sollte ja vom Timer vor Ausloesen des Interrupts gemacht werden und danach sind mindestens 0.3ms Zeit. Allerdings weiss ich jetzt auch nicht auswendig, bei welchem Controller wie viele Timer direkt einen Pin triggern koennen - und so reichlich hat der AVR ja Timer auch nicht. Aber 2 fuer 18 Kanaele sollten viele koennen. Ich denke, das sollte unterm Strich sogar genauer sein als mit den Slave-AVRs, die dann jeweils n Pins bedienen muessen.
Ohne Begründung. Parallele Übertragung kommt bei dem Projekt auch nicht wirklich in Frage. Jemand anderes hatte I2C vorgeschlagen. Ich meine, irgendwo gelesen zu haben, dass das von Controller zu Controller Zusatzhardware erfordert, bin nicht ganz sicher. Kenne mich wie gesagt mit serieller Datenübertragung auch nicht richtig aus. Zum 4017: Ich will auf jeden Fall eine ein-Chip-Lösung realisieren, ansonsten ist die Idee nicht schlecht! Komplexe Steuerkomanndos sollen erst mal aussen vorbleiben. Im Roboterforum hatte jemand vorgeschlagen, Drucksensoren an den Füssen anzubringen, die dem Servotreiber direkt mitteilen, ob der jeweilige Fuss sicher auf der Erde "gelandet" ist. All das soll bei meinem Projekt der Hauptcontroller machen. Entsprechend würde es sich anbieten, die Datenübertragung wie folgt aussehen zu lassen: -unidirektional ("Ein-Draht") -9600Baud -zwei Bit pro Befehl, Bit 1 für Servonummer, Bit 2 für den Stellwinkel Jetzt überlege ich, was man unter Parität, Startbit und Stopbit versteht... letztere werden sicher den Datenbits vorangestellt oder angehangen. Wie sieht es wohl mit einem Buffer aus? Braucht man den und wie groß sollte er sein. Prinzipiell muss das Hauptsystem ohnehin ein paar Milisekunden Pause einlegen zwischen zwei Servobefehlen, weil mehrere gleichzeitig anlaufende Servos peakmässig riesig Strom fressen, selbst bei guten Akkus geht da schon mal kurzzeitig die Versorgungsspannung in die Knie. Andere Slave-Systeme sollen übrigens erst mal nicht angeschlossen sein, notfalls würde ich dem Hauptcontroller zum Senden der Servoinfos noch einen Software-Uart zur Verfügung stellen. Ach ja, zum Testen der Schnittstelle würde ich gerne Testdaten über die serielle Schnittstelle an den Servocontroller senden, da gibt es doch so Konsolenprogramme; glaube, auch bei Bascom... Ansonsten müssen noch die Pegel von PC und µC per Max232 o.ä. aneinander angepasst werden, schätze ich. Ich glaube, am besten ist es jetzt erst mal, dafür zu sorgen, dass ich zum Testen seriell Daten vom PC an den Controller senden kann. Was braucht man dazu für Hardware? (das ist sicher im Moment erst mal der wichtigste Punkt) PS: @Hannes: großartige Platinenfräsmaschine hast Du da gebaut, Kompliment!!!
ist in diesem Zusammenhang folgender Schaltplan zu empfehlen? http://www.coolcircuit.com/circuit/rs232_driver/ (MAX232(Full duplex)) Man findet ja manchmal auch andere Anschlussbelegungen für TX und RX...
>-zwei Bit pro Befehl, Bit 1 für Servonummer, Bit 2 für den Stellwinkel Mit 2 Bit kommst du nicht weit. Das wären 2 Servos mit 2 Stellungen... Nimmer lieber den Eightpack (auch Byte genannt)! Wenn du eh nur in eine Richtung in einem Gerät deine Daten übermitteln willst, dann brauchst du keine RS232. Da reichen 5V völlig aus (solange die Quelle genug Strom liefert und die Senke möglichst hochohmig ist). >Drucksensoren an den Füssen >anzubringen, die dem Servotreiber direkt mitteilen, ob der jeweilige >Fuss sicher auf der Erde "gelandet" ist. Also einfache Taster... Langsam hast du aber dann doch ein Pinproblem. Das wird nichts mehr mit nur einem Controller...
UART zwischen Controllern im Nahbereich erfordert keine Pegelanpassung. Einfach TXD (Datenausgang) des Sendenden an RXD (Dateneingang) des Empfangenden schalten und gut ist... Nur wenn mehrere Transmitter (Sendende) sich eine Leitung teilen müssen, muss man sie durch Dioden oder zweistufige Transistorschaltungen entkoppeln und einen PullUp-Widerstand einsetzen. Dies wird aber erst nötig, wenn mehrere Controller Daten zum Master senden sollen. UART zum PC (auch über USB-Serial-Adapter) erfordert Pegelwandler. MAX232 ist die Standardlösung. Wenn Du Dir selbst nicht traust, dann nimm die Bausätze oder Module von Conrad oder Pollin. In Bascom sprichst Du UART mit dem Print-Befehl an. Oder halt direkt, durch Schreiben auf UDR (wie man es in ASM macht). Wenn Du die zu übertragende Sequenz in einem Array (Bytes) hältst, dann sollte das Versenden des Arrays auch in Bascom kein Problem sein. Notfalls mittels Zählschleife. Deine Bitzuweisung kann ich nicht nachvollziehen, ich vermute ein Missverständnis. Die oben genannte Zuordnung der Zahlenwerte zu Positionen, Servonummern, Kommandos und Gerätenummern hat schon ihren Sinn. Auch die Kommandos würde ich im Hinterkopf behalten. Dein Hauptcontroller würde sich freuen, wenn er ein Kommando zum Laufen geben könnte anstatt jede Position jedes Servos in jedem Zwischenschritt einzeln übertragen (befehlen) zu müssen. Sie UART einfach als eine Schnittstelle an, die mit einem Zugriff ein Byte überträgt. Um Startbit, Stoppbit und Parität musst Du Dich nicht kümmern, das macht die Hardware. Eine übliche und halbwegs sichere Einstellung ist 9600 Baud, 8 Datenbits, keine Paritätsprüfung, 2 Stoppbits. Auf dem PC ist der Einsatz des Terminal-Programms "hterm" von Tobias Hammer sinnvoll, ein Link dazu findest Du in der Linksammlung dieses Forums. Die Fräse wird nicht mehr genutzt, ich ätze meine Platinen inzwischen mittels Tonertransfer. Bin nur noch nicht zum Abbauen gekommen. Sie hat mir aber über etliche Jahre gute Dienste geleistet. So, ich will/muss jetzt aber erstmal an meinem Tiny85-Loksoundmodul weiterstricken (Anlasser, Diesel, Horn, Glocke)... ...
Achja, Drucksensoren (Taster)... Ein Mega8535 muss ja nicht 32 Servos steuern. Steuert er nur 24 Servos, bleiben 8 Eingänge für die Taster übrig. Sie können dann auf dem "kurzrn Weg" behandelt werden... ...
Hallo, ja, ein Fehler meinerseits. Ich meinte natürlich -zwei Bytes pro Befehl, Byte 1 für Servonummer, Byte 2 für den Stellwinkel!!! (bei einem Bit pro Servo und Winkel müsste man wohl eine serielle Schnittstelle in der seriellen Schnittstelle anbringen ;)) Nein, ich selber will, wenn überhaupt, die Drucksensoren an den Hauptcontroller anschließen. Der Haxapodengang (sechsbeiniger Roboter) ist so komplex, dass ich das auch alles lieber erst mal über den Hauptprozessor abwickle. Das mit dem Max232 traue ich mir schon zu, keine Bange. Habe auch noch ein oder zwei Exemplare in der Bastelkiste. Eine Frage dazu hab ich aber noch: die 5V für den Max, kann man die aus der seriellen Schnittstelle beziehen? Ansonsten würde ich das µC-Board anzapfen... Viel Spaß und Erfolg beim Tiny85-Loksoundmodul-Weiterentwickeln!
so, die schaltung mit dem max232 ist mittlerweile aufgebaut und ein kurzer test über die bascom-konsole hat gezeigt, dass alles funktioniert, habe ein paar tastaturzeichen rübergeschickt. wenn jemand einen tipp hat, wie man unter bascom statt chr$-dingern echte zahlen (8-bit) empfangen kann, immer her damit! ich werde aber übers wochenende auch noch mal selber die materie näher betrachten...
>wenn jemand einen tipp hat, wie man unter bascom statt chr$-dingern >echte zahlen (8-bit) empfangen kann, immer her damit! die chr$-Dingens sind 8Bit breite Zahlen, nur als (erweiterter) ASCII-Zeichensatz. Zeig doch mal, wie du das da machst bzw. was du machen willst. Ich habe auch keine Ahnung vom Bascom-Vokabular, aber gewisse Erfahrung in anderen Basic-Dialekten.
Hallo, Danke für das Hilfe-Angebot! Ich hänge einfach das wilde Testprogramm unten an. Leider funktioniert es nicht ohne den „enable Interrupt“-Befehl. Einen Interrupt will ich nämlich im späteren Programm vermeiden (wg. Zeitverschiebungen). Ich vermute mal, das die Variable Na zur reinen Zahlenübermittlung besser als Byte definiert sein würde. Es sind aber noch ein paar andere Fragen offen, später mehr... $regfile = "m32def.dat" $crystal = 8000000 $baud = 9600 ' use baud rate $hwstack = 32 ' default use 32 for the hardware stack $swstack = 10 ' default use 10 for the SW stack $framesize = 40 ' default use 40 for the frame space 'LCD Config Lcd = 20 * 4 Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , Db7 = Portb.5 , E = Portb.1 , Rs = Portb.0 Display On Cls Waitms 250 'first compile and run this program with the line below remarked Config Serialin = Buffered , Size = 20 Dim Na As String * 10 'the enabling of interrupts is not needed for the normal serial mode 'So the line below must be remarked to for the first test 'Enable Interrupts Lcd "Start" Do 'get a char from the UART If Ischarwaiting() = 1 Then 'was there a char? Input Na Lcd Na 'print it End If Wait 1 'wait 1 second Loop
Bascom liefert die Datei "BASCAVR.chm" mit. Mit der solltest Du Dich mal ein bissel anfreunden. Mit DIM kannst Du Variablen und Arrays deklarieren. Es gibt dabei den Variablentyp "Byte". Mit PRINT kann man Variablen per UART ausgeben, vermutlich auch Variablen vom Type Byte. Wird das zu komplex weil evtl. die CHR$()-Funktion nötig wird, dann kann man die Variable auch einfach an UART übergeben. Das müsste mit "Udr = varname" gehen. Davor ist natürlich zu prüfen, ob UART bereits fertig ist, dafür gibt es ein Statusflag, ist im Datenblatt genau beschrieben. ...
Also ich hab die Bascom-Konsole jetzt verworfen und sende die Daten mit dem PC per Qbasicprogramm an den Controller. Qbasic sendet: print#1, chr$(a); chr$(b) Bascom empfängt mit: If Ischarwaiting() = 1 Then ... a=waitkey() b=waitkey() wobei a und b als bytes dimensioniert sind und a die Servonummer darstellt und b den Stellwinkel. Funktioniert prima. Scheint mir allerdings doch ein Umweg zu sein... ...wenn man statt Chr$(a) direkt die Variable a sendet, kommt beim Controller Unsinn an. Das liegt wahrscheinlich am Waitkey()-Befehl, der eine Chr$-Variable erwartet. Stellt sich also die Frage, mit welchem Befehl man direkt eine 8-Bit-Zahl empfangen kann. Ich tippe mal auf get# o.ä., werde es später nachsehen und ausprobieren. PS: ja, die Bascom-Hilfsdatei kenn ich schon ;)
Im Register UDR steht das empfangene Byte. Mach Dir eine Variable als Byte auf und wirf erst dann, wenn das Bit RXC im Register UCSRA wieder auf 1 steht den Inhalt von UDR in Deine Variable. (Das Byte ist dann in UDR komplett drin) Ungefähr so: Dim Alfred as Byte Do If UCSRA.RXC = 1 then Alfred = UDR Loop MfG Paul
hallo, ganz kurz... habs eben mal wie angegeben versucht, klappt aber nicht. statt einem byte werden gleich mehrere empfangen, die alle nicht dem gesendeten byte entsprechen. baudrate ist aber korrekt eingestellt. hm...
> statt einem byte werden gleich mehrere empfangen, die alle nicht dem > gesendeten byte entsprechen. Kann es sein, dass Dein Byte bem Senden in ASCII-Text gewandelt wird? ...
habe diesmal statt print#1, chr$(a) direkt die byte-variable a gesenden, also: print#1, a (von qbasic/PC aus) das ergebnis sind mehrere empfangene bytes statt einem (also der variablen a)
nachtrag: genau genommen mit semikolon: print#1, a ;
Dann poste doch mal den Quältext (die .FRM-Datei), vielleicht findet da jemand was... ...
> den Quältext (die .FRM-Datei),
Sorry, ich ging von VB6 aus, unter QBASIC ist das natürlich die
.BAS-Datei.
...
hier die datei, die open-zeile habe ich aus der hilfsdatei kopiert, die funktionen einiger der aufgeführten parameter ist mir zugegebenermaßen gänzlich unbekannt. benutzt man nur den linken teil bis zur 1, funktioniert die datenübertragung gar nicht, ansonsten wie weiter oben beschrieben. OPEN "COM2:9600,N,8,1,CD0,CS0,DS0,OP0,RS,TB2048,RB2048" FOR RANDOM AS #1 A = 27 PRINT #1, A ; CLOSE #1
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.