Digispark Klon und PWM Servosteuerung

#7985964
Lesenswert?

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/

Angehängte Dateien:
(Firma: Gast) #7986008
Lesenswert?

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
(Firma: 1984now) #7986053
Lesenswert?

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...

#7986060
Lesenswert?

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
#7986075
Lesenswert?

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.

(Firma: 1984now) #7986083
Lesenswert?

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)?

#7986105
Lesenswert?

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.

(Firma: 1984now) #7986118
Lesenswert?

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.

#7986137
Lesenswert?

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.

(Firma: Gast) #7986184
Lesenswert?

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
#7986202
Lesenswert?

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.

(Firma: Gast) #7986471
Lesenswert?

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.

#7986528
Lesenswert?

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
(Firma: 1984now) #7986547
Lesenswert?

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.

#7986875
Lesenswert?

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.

(Firma: Q3) #7986890
Lesenswert?

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 ...

#7986899
Lesenswert?

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.

(Firma: Gast) #7986919
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren