Hallo zusammen, ich arbeite mich gerade in die PWM Geschichte des Tiny85 ein. Da ich gerade nur den Digispark Klon zur Hand habe und ein sehr einfaches Setup habe. Wollte ich den Servo über USB Steuern. Die USB Verbindung mit dem Python Programm steht. Jetzt wollte bin ich dran den Servo mittels PWM Mode des Tiny zu steuern. Dabei habe ich den Timer1 mit einen Prescaler von 512 genommen ohne Interrupt, weil dieser bereits vom Digispark benutzt wird. Timer0 wird glaube ich auch bereits benutzt, also fällt dieser auch weg. Bei einen einfachen Bit schalten also 1.5ms high -> 20ms warten bewegt sich auch der Servo, bedeutet ein elektrisches Problem kann ich ausschließen. Wenn ich im angehangen Quellcode den Wert von OCR1B mit einer Schleife durchlaufe bewegt sich auch hin und wieder der Servo aber leider nicht mit den eingestellten Werten. Diese scheinen aber zu stimmen, wenn ich der Quelle glauben soll, nachgerechet habe ich es natürlich auch schon. Hat vielleicht jemand eine Idee was ich übersehen haben könnte? https://www.raspberry-pi-geek.de/ausgaben/rpg/2020/06/mikrocontroller-attiny85-programmieren/2/
Lars L. schrieb: > ich habe hier Ad hoc keines Griffbereit. Schade... Auch keinen anderen µC, den man als "Messgerät" verwenden könnte? Ohne messen: Blindes stochern im Nebel! Übrigens: Beim Digispark sind die Fuses so gesetzt, dass er mit 16MHz intern läuft. Der Bootloader dreht dann die Frequenz nochmal höher auf ca 16,5MHz Das sollte man beachten......
:
Bearbeitet durch User
Arduino F. schrieb: > Übrigens: > Beim Digispark sind die Fuses so gesetzt, dass er mit 16MHz intern > läuft. > Der Bootloader dreht dann die Frequenz nochmal höher auf ca 16,5MHz Und wenn man über USB kommunizieren möchte, sollte man daran tunlichst nichts verändern.
Lars L. schrieb: > Hat vielleicht jemand eine Idee was ich übersehen haben könnte?
1 | // ---- Timer1 Reset ---- |
2 | //Kapitel 12.3.2 Seite 90 |
3 | GTCCR |= (1 << PWM1B); //Kapitel 13.3.2 S.101 |
4 | // ---- 20 ms Periode (50 Hz) ---- |
5 | OCR1C = 255; // prescaler 512 Maximalwert 255 für 8-Bit → ca. 16,32 ms ca 61.5 hz |
Das ist falsch. Wenn du über OCR1C die PWM-Frequenz bestimmen willst, muß in GTCCR sowohl das CTC1- als auch das PWM1A-Bit gesetzt sein. Erstaunliche Leseschwäche, das richtige Kapitel hast du ja selbst angegeben und so furchtbar viel Text ist da nicht zu lesen...
Arduino F. schrieb: > Lars L. schrieb: >> ich habe hier Ad hoc keines Griffbereit. > > Schade... > Auch keinen anderen µC, den man als "Messgerät" verwenden könnte? > Ohne messen: Blindes stochern im Nebel! > > Übrigens: > Beim Digispark sind die Fuses so gesetzt, dass er mit 16MHz intern > läuft. > Der Bootloader dreht dann die Frequenz nochmal höher auf ca 16,5MHz > > Das sollte man beachten...... Hallo, ja komme erst wieder später an messgeräte dran. Hatte zwar daran kurz gedacht, aber bisher hat alles gut funktioniert. Jedenfalls habe ich dadurch den Prescaler auf 1024 hochgedrecht.
1 | TCCR1 |= (1 << CS13) | (1 << CS11) | (1 << CS10); // Prescaler 1024 |
2 | OCR1B=18; |
3 | _delay_ms(1000); |
4 | OCR1B=25; |
5 | _delay_ms(1000); |
6 | OCR1B=33; |
7 | _delay_ms(1000); |
und lustigerweise muss ich kaum die Werte verändern. Das sollte alles im Bereich zwischen 2.5ms und 0.5ms sein. Leider trotzdem keine reaktion von dem Servo. Aber bei diesem Code schwenkt er mal kurz nach Rechts aus.
1 | for(uint8_t i=1; i<100; i++) {
|
2 | OCR1B = i; |
3 | _delay_ms(500); |
4 | } |
und bei der Servo_init Funktion zuckt der mal.
:
Bearbeitet durch User
Ob S. schrieb: > Das ist falsch. Wenn du über OCR1C die PWM-Frequenz bestimmen willst, > muß in GTCCR sowohl das CTC1- als auch das PWM1A-Bit gesetzt sein. Hallo Observer, naja bin gerade bei PWM1B und nicht bei PWM1A welches im TCCR1 Register ist. Habe das einmal angepasst, aber scheinbar hat dies auch nicht zum Erfolg geführt. Ich bin an PB4 bei OC1B. Sorry falls ich es im Quellcode falsch in den Kommentaren habe.
Lars L. schrieb: > naja bin gerade bei PWM1B und nicht bei PWM1A Das ist scheißegal. Der Punkt ist: wenn du die PWM-Frequenz über OCR1C kontrollieren willst, muss das CTC1-Bit in GTCCR gesetzt werden.
Okay, also gemacht habe ich es und gebracht hat es nichts. Aber zum Thema CTC1 GTCCR Register habe zwar gerade keine Brille auf aber wie kommst du auf GTCCR? Und den Text über CTC1 habe ich auch gefunden und rangehängt.
Lars L. schrieb: > Aber zum Thema CTC1 GTCCR Register habe zwar gerade keine Brille auf > aber wie kommst du auf GTCCR? Könnte man "Übertragungsfehler" nennen. Gemeint war natürlich TCCR1. > Und den Text über CTC1 habe ich auch > gefunden und rangehängt. Wir haben den alle schon. Die Frage ist: hast du ihn gelesen (und verstanden)?
> Könnte man "Übertragungsfehler" nennen. Gemeint war natürlich TCCR1. Okay beide, probiert und leider nichts hat funktioniert. >> Und den Text über CTC1 habe ich auch >> gefunden und rangehängt. > > Wir haben den alle schon. Die Frage ist: hast du ihn gelesen (und > verstanden)? Ich weiß sehr wohl das die jeder hat. Gelesen ja, aber was soll mir der text noch sagen? Was kannst du noch daraus lesen was ich überlesen habe? Oder willst du dein geheimes Illuminaten Wissen nicht teilen.
Lars L. schrieb: > Gelesen ja, aber was soll mir der > text noch sagen? Was kannst du noch daraus lesen was ich überlesen habe? > Oder willst du dein geheimes Illuminaten Wissen nicht teilen. Nix geheim. Steht alles in der Beschreibung des Bits. > When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00 in > the CPU clock cycle after a compare match with OCR1C register value. If > the control bit is cleared, Timer/Counter1 continues counting and is > unaffected by a compare match. Insbesondere der letzte Satz dieses Zitats sei deiner geneigten Aufmerksamkeit empfohlen.
Hmmm okay das ctc1 bit muss also gesetzt werden. Das glaube ich dir jetzt komplett.😅 Aber das bit hatte ich bereits gesetzt und es funktioniert nicht. Werde dann wohl erstmal de Oszi ranlegen und dann mal schauen was da raus kommt. Abwr schade so viel Quellcode ist es ja nicht.
Lars L. schrieb: > Aber das bit hatte ich bereits gesetzt und es funktioniert nicht. Zeig' doch einfach mal den aktuellen Stand der Init-Funktion. Beim Rumprobieren ohne Sinn und Verstand schleichen sich schnell mal neue Fehler ein...
Drücke dir die Daumen das du was findest, ansonsten muss ich wohl wirklich ein oszi dran hängen. Hatte auch spass mal die manuelle setzen der Bits über PB1 getätigt und dabei die Periode von 20ms auf 16ms gedrückt. Das hat dem Servo nichts ausgemacht.
Lars L. schrieb: > ansonsten muss ich wohl > wirklich ein oszi dran hängen. Habe mal mein Billigoszi drangehangen. Original Digispark verwendet. 16,5MHz Es sagt an PB4: Frequenz: 3.97xHz Daraus folgt: Intervall: 252ms Der kurze Impuls ist: 19,2ms Der lange: 34,4ms Das sind nicht die Dinge, die ein Servo verstehen muss.
:
Bearbeitet durch User
Arduino F. schrieb: > Lars L. schrieb: >> ansonsten muss ich wohl >> wirklich ein oszi dran hängen. > > Habe mal mein Billigoszi drangehangen. > Original Digispark verwendet. > 16,5MHz > > Es sagt an PB4: > Frequenz: 3.97xHz > Daraus folgt: > Intervall: 252ms > > Der kurze Impuls ist: 19,2ms > Der lange: 34,4ms > Das sind nicht die Dinge, die ein Servo verstehen muss. Ohhh danke dir. Das stimmt. Natürlich subobjektiv. Da muss das ganze wohl nochmal in die Entwicklung.
Harald K. schrieb: > subobjektiv Ich finde das Wort fast ok. Hätte allerdings eher "suboptimal" erwartet. Muss aber sagen, dass die genannten Werte eher subjektiv als objektiv(wahr) sind. Das verwendete Oszi ist halt etwas eingeschränkt in Sachen Messmethoden und Genauigkeit. Es ist ein Owon HD5242. Für kleine Dinge in meiner Arduino Welt und auch im Feld, ausreichend. Man darf nur nicht zuviel erwarten.
Lars L. schrieb: > ich habe hier Ad hoc keines Griffbereit. Ein Logikanalysator reicht völlig aus. Arduino F. schrieb: > Daraus folgt: > Intervall: 252ms > ... > Der kurze Impuls ist: 19,2ms > Der lange: 34,4ms Arduino F. schrieb: > Das verwendete Oszi ist halt etwas eingeschränkt in > Sachen Messmethoden und Genauigkeit. Welche ausgefallene Messmethode würdest du denn verwenden wollen, um einen einfachen, sich periodisch wiederholenden Puls auszumessen? Und auch ein genaueres Oszi würde die Werte nicht so ändern, dass daraus ein sinnvolles Steuersignal für einen Modellbauservo mit 1...2ms langen Pulsen wird. Lars L. schrieb: > Hatte auch spass mal die manuelle setzen > der Bits über PB1 getätigt und dabei die Periode von 20ms auf 16ms > gedrückt. Das hat dem Servo nichts ausgemacht. Die Wiederholfrequenz ist dem Servo in relativ weiten Grenzen egal. Den interessiert nur die Dauer des positiven Pulses. An der Frequenz des Timers, d.h. an dem Wert für den Reset des Zählers willst du erstmal gar nicht drehen.
:
Bearbeitet durch User
Arduino F. schrieb: > Habe mal mein Billigoszi drangehangen. > Original Digispark verwendet. > 16,5MHz > > Es sagt an PB4: > Frequenz: 3.97xHz > Daraus folgt: > Intervall: 252ms Die wahrscheinlichste Erklärung ist dann wohl: im den CS12-Bit stand schon vorher eine 1. Dann würde sich als Prescaler 16384 ergeben, was ganz elegant zu deinen Messergebnissen führen würde. Das ist die Gefahr, wenn man Bitfelder verodert. Wenn vorher schon Bits gesetzt waren, kann ein falsches Endergebnis rauskommen. Ich würde also folgendermaßen ergänzen: // ---- Prescaler TCCR1 ---- TCCR1 &= ~((1 << CS13) | (1 << CS12) | (1 << CS11) | (1 << CS10)); TCCR1 |= (1 << CS13) | (0 << CS12) | (1 << CS11) | (1 << CS10); Selbst wenn's nicht zum Erfolg führt, ist auf jeden Fall damit eine mögliche Ursache erst mal ausgeschlossen.
Ob S. schrieb: > Ich würde also folgendermaßen ergänzen: > > // ---- Prescaler TCCR1 ---- > TCCR1 &= ~((1 << CS13) | (1 << CS12) | (1 << CS11) | (1 << CS10)); > TCCR1 |= (1 << CS13) | (0 << CS12) | (1 << CS11) | (1 << CS10); > > Selbst wenn's nicht zum Erfolg führt, ist auf jeden Fall damit eine > mögliche Ursache erst mal ausgeschlossen. Hallo observer, das war auch die Lösung, man sollte sich wirklich nicht darauf verlassen das die Bits resettet werden. Danach hat alles super funktioniert. Habe nur gemerkt das ich mir den falschen Pin ausgesucht habe :-D Denke das bekomme ich auch noch hin :D Erstmal Danke für die Hilfe und einen guten Rutsch ins neue Jahr.
Tip vom Praktiker! Wir haben in einem Museum mehrere rote Laserpointer mit jeweils zwei Servos in Betrieb, die, gesteuert von einem Touchscreen mit Informationen, einzelne Exponate optisch markieren. Wir erreichen in einem Abstand von ca. 3m und 90 Grad horizontal und vertikal eine Auflösung von ca. 1cm bei einer Wiederholgenauigkeit von ca. 1,5...2cm. Dazu verwende ich digitale(!) Minaturservos mit Metallgetriebe und Prozessoren vom Typ Wemos D1 Mini im WLAN. Zur Ansteuerung benötige ich keine Hardware-PWM, sondern gebe ganz gewöhnlich die High-Impulse mit digitalWrite(pin, HIGH); delayMicroseconds(time); digitalWrite(pin, LOW); aus. Das genügt vollkommen. Der Vorteil von digitalen Servos ist, dass diese ihre Position halten, auch wenn die Impulse mal unregelmäßig kommen oder ganz ausfallen. Nur die Länge ist maßgeblich ...
Frank E. schrieb: > Tip vom Praktiker! Wir haben in einem Museum mehrere rote Laserpointer > mit jeweils zwei Servos in Betrieb, die, gesteuert von einem Touchscreen > mit Informationen, einzelne Exponate optisch markieren. Wir erreichen in > einem Abstand von ca. 3m und 90 Grad horizontal und vertikal eine > Auflösung von ca. 1cm bei einer Wiederholgenauigkeit von ca. 1,5...2cm. > > Dazu verwende ich digitale(!) Minaturservos mit Metallgetriebe und > Prozessoren vom Typ Wemos D1 Mini im WLAN. Klingt spannend und auf jedenfall eine gute Idee für die Besucher. So müssen Ausstellungen gemacht werden! Als ich mit meiner kleinen in Brandenburg ein Schloss besucht haben. Haben die, die Geschichte mittels Animierten Figuren nachgestellt. Das ist super für die Kids! > > Zur Ansteuerung benötige ich keine Hardware-PWM, sondern gebe ganz > gewöhnlich die High-Impulse mit > > digitalWrite(pin, HIGH); delayMicroseconds(time); digitalWrite(pin, > LOW); > > aus. Das genügt vollkommen. Das hat ja bei mir auch funktioniert. Aber wenn beim Oberbau von USB gibts ein Verbindungsabbruch wenn ich es so betreibe. Deswegen musste ich das fast schon per PWM aufbauen und es funktioniert gerade gut :D Mal sehen was daraus noch wird. In ein paar Jahren will ich mir mal Schrittmotoren anschauen. > Der Vorteil von digitalen Servos ist, dass diese ihre Position halten, > auch wenn die Impulse mal unregelmäßig kommen oder ganz ausfallen. Nur > die Länge ist maßgeblich ... Eine Idee schwebt mir im Kopf mit Servo da brauche ich diese Genauigkeit aber nicht. Aber danke für die Info.
Lars L. schrieb: > man sollte sich wirklich nicht darauf verlassen > das die Bits resettet werden. Doch! Darauf kann man sich verlassen. Das Datenblatt spricht Wahr! Was bei dir passiert: Dein void setup() und loop() sagt mir, dass du in einer Arduino(ähnlichen) Umgebung tätig bist. Dort ist es üblich, dass in main() bzw. init(), die Timer für PWM vorbereitet werden. Das dürfte die Fußangel gewesen sein, in die du gestolpert bist. Der allgemeine Rat: Wenn man AVR Timer in der Arduino Umgebung für eigene Zwecke verwenden will, sollte man deren Steurerregister erstmal bewusst auf 0, Resetzustand, setzen. Außer, der Timer welcher für millis() und seine Kumpels zuständig ist. Wurde hier schon ein paar mal besprochen, in welche Fallen man da tappen kann. Sogar ein undokumentiertes Feature der AVT Timer
:
Bearbeitet durch User
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.

