Forum: Mikrocontroller und Digitale Elektronik Digispark Klon und PWM Servosteuerung


von Lars L. (vertigo)


Angehängte Dateien:

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/

von Sebastian R. (sebastian_r569)


Lesenswert?

Was sagt das Oszilloskop am entsprechenden Pin?

von Lars L. (vertigo)


Lesenswert?

Hallo,

ich habe hier Ad hoc keines Griffbereit.

von Arduino F. (Firma: Gast) (arduinof)


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
von Loco M. (loco)


Lesenswert?

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.

von Ob S. (Firma: 1984now) (observer)


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

von Lars L. (vertigo)


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
von Lars L. (vertigo)


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.

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

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.

von Lars L. (vertigo)


Angehängte Dateien:

Lesenswert?

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.

von Ob S. (Firma: 1984now) (observer)


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

von Lars L. (vertigo)


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.

von Ob S. (Firma: 1984now) (observer)


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.

von Lars L. (vertigo)


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.

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

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

von Lars L. (vertigo)


Angehängte Dateien:

Lesenswert?

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.

von Arduino F. (Firma: Gast) (arduinof)


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
von Lars L. (vertigo)


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.

von Harald K. (kirnbichler)


Lesenswert?

Lars L. schrieb:
> subobjektiv

?

von Arduino F. (Firma: Gast) (arduinof)


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.

von Rainer W. (rawi)


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
von Ob S. (Firma: 1984now) (observer)


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.

von Lars L. (vertigo)


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.

von Frank E. (Firma: Q3) (qualidat)


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

von Lars L. (vertigo)


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.

von Arduino F. (Firma: Gast) (arduinof)


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
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
Noch kein Account? Hier anmelden.