Mit hilfe eines X Y Schreiber und einem Arduino Grafiken zeichnen lassen.

DrDiettrich:
Mein Einwurf hat sich auf das vorhergehende Posting bezogen, über PWM im Allgemeinen. Zum Projekt der Absatz über die Dimensionierung des RC Filters.

Oh, ach so. Ist halt blöd, dass durch ein fehlendes Zitat der Zusammenhang nicht klar ist. Ich werde das noch einmal mit dem richtigen Zusammenhang im Kopf lesen.

Gruß

Gregor

Serenifly:
Ich würde hier auch eher DA-Wandler nehmen

Um Kreise und Linien zu zeichnen gibt es wie gesagt fertige Algorithmen. Vom Bresenham gibt es auch Abwandlungen für Kreise. Dann muss man nur die Koordinaten entsprechend auf die realen Ausgangswerte umsetzen

Hasst du vielleicht Links zu diesen Algorithmen?

benni73:
Hasst du vielleicht Links zu diesen Algorithmen?

Die sind irre simpel. Wie alles, was man weiß :slight_smile:

Anders als in der Schule gelernt, beginnt das Winkelmessen nichr bei „12 Uhr“ und dann im Uhrzeigersinn sondern die 0° liegen bei 3 Uhr und der Winkel öffnet sich gegen den Uhrzeigersinn. Den Winkel beim Kreismittelpunkt verrechnet man meistens nicht in Grad sondern als Teil des Kreisumfangs eines Einheitskreises (Radius=1). Von 0 bis 360 Grad entspricht dann 0 bis 2*Pi.
Wenn man diesen Winkel für sin() und cos() verwendet bekommt man horizontale (x) und vertikale (y) Punktkoordinaten so:

x=cos(Winkel)*Radius
y=sin(Winkel)*Radius

HTH

Gregor

PS: Was den Bresenham-Algorithmus angeht: Bresenham-Algorithmus – Wikipedia

@Gregor: Das Verfahren funktioniert etwas anders als Du beschreibst, da kommt kein sin und kein cos drin vor. Zudem ist der Wikipedia Code für den Linienschreiber nicht brauchbar, weil er in jedem Schritt 4-8 Pixel in den 4 Quadranten bzw. 8 Oktanten setzt. Das funktioniert zwar auf einem Raster-Display (Bitmap), aber nicht mit einem Plotter oder XY-Schreiber.

Ich würde erst mal die Linien implementieren, und nur wenn dann noch Zeit übrig ist, den Algorithmus für die Kreise und Kreisbögen verstehen und implementieren. Wie gesagt, ein Smiley wird schwierig.

DrDiettrich:
@Gregor: Das Verfahren funktioniert etwas anders als Du beschreibst, da kommt kein sin und kein cos drin vor. Zudem ist der Wikipedia Code für den Linienschreiber nicht brauchbar, weil er in jedem Schritt 4-8 Pixel in den 4 Quadranten bzw. 8 Oktanten setzt. Das funktioniert zwar auf einem Raster-Display (Bitmap), aber nicht mit einem Plotter oder XY-Schreiber.

Diesmal habe ich etwas aus dem Posting, auf das ich mich bezog, falsch verstanden. Dass eigentlich der Bresenham-Algorithmus gefragt war, ist mir erst nach dem Schreiben aufgefallen.

Gruß

Gregor

gregorss:
Die sind irre simpel. Wie alles, was man weiß :slight_smile:

Anders als in der Schule gelernt, beginnt das Winkelmessen nichr bei „12 Uhr“ und dann im Uhrzeigersinn sondern die 0° liegen bei 3 Uhr und der Winkel öffnet sich gegen den Uhrzeigersinn. Den Winkel beim Kreismittelpunkt verrechnet man meistens nicht in Grad sondern als Teil des Kreisumfangs eines Einheitskreises (Radius=1). Von 0 bis 360 Grad entspricht dann 0 bis 2*Pi.
Wenn man diesen Winkel für sin() und cos() verwendet bekommt man horizontale (x) und vertikale (y) Punktkoordinaten so:

x=cos(Winkel)*Radius
y=sin(Winkel)*Radius

HTH

Gregor

PS: Was den Bresenham-Algorithmus angeht: Bresenham-Algorithmus – Wikipedia

Ich habe es wie beschrieben programmiert, doch der X Y Schreiber reagiert ja auf Spannungsänderung. Wie kann man die Spannung so programmieren, dass er den Kreis wie vorgegeben zeichnet?

benni73:
Ich habe es wie beschrieben programmiert, doch der X Y Schreiber reagiert ja auf Spannungsänderung. Wie kann man die Spannung so programmieren, dass er den Kreis wie vorgegeben zeichnet?

Mit den beiden von mir genannten Formeln bekommst Du jeweils einen Wert von -1 bis 1. Daraus musst Du einen Wert machen, der zwischen 0 und 255 liegt. Siehe map(). Wenn Du das hast, steuerst Du damit einen PWM-fähigen Pin an und machst aus dem PWM-Signal eine analoge Spannung. Wie diese Umformung von digital zu analog funktioniert, weiß jemand anderes. Wenn sich hier im Thread keiner dazu meldet, machst Du zu dieser Frage am besten einen neuen Thread auf.

Gruß

Gregor

Mit PWM und Tiefpass wird das zwar nette Kurven malen, aber nix was halbwegs richtig steuerbar ist. Oder man macht die Ansteuerung s o o o l a n g s a m dass der Spaßfaktor auch auf der Strecke bleibt.

Ich würde zwei externe DACs dranhängen und die die Arbeit machen lassen. Das ist nicht viel Aufwand und bringt deutlich bessere Ergebnisse.

Klaus_ww:
Ich würde zwei externe DACs dranhängen und die die Arbeit machen lassen. Das ist nicht viel Aufwand und bringt deutlich bessere Ergebnisse.

Oh ... ja ... klar. Dass es DACs gibt weiß ich zwar, aber hier fiel mir das gerade nicht ein.

Kannst Du ein bestimmtes Bauteil empfehlen? Ich habe davon echt keine Ahnung, das will ich ändern :slight_smile:

Gruß

Gregor

Formel für einen Kreis wäre

x=Radiussin(winkel3.141/180)+Xmittelpunkt
y=Radiuscos(winkel3.141/180)+Ymittelpunkt

Winkel einfach z.B. in 10er Schritten von 0 bis 360 laufen lassen. Da Sketch und Schaltplan zu eurem Aufbau fehlen, kann ich keinen Hinweis geben, wie ihr das genau in euren Sketch einbauen müsst.

benni73:
Ich habe es wie beschrieben programmiert, doch der X Y Schreiber reagiert ja auf Spannungsänderung. Wie kann man die Spannung so programmieren, dass er den Kreis wie vorgegeben zeichnet?

Du meinst, er erwartet eine Wechselspannung am Eingang? Dann suche mal die Schalter, mit denen sich die Eingänge auf Gleichspannung umschalten lassen.

Ich glaube nicht, dass hier Wechselspannung gemeint ist.

Die Schreiber die ich kenne arbeiten mit Gleichspannung. Aber vielleicht hilft die Modellangabe ja weiter (hab jetzt nicht alles nachgelesen ob die schon erwähnt wurde).

Was die DACs betrifft: mach Dir mal Gedanken über die gewünschte Genauigkeit und natürlich auch die notwendige Spannung für 100% Ausschlag. Dann kannst Du die Auflösung festlegen.

Es gibt diese 12 Bit DACs, findest Du überall unter Stichwort "arduino DAC", gleiches für 16 Bit. Ansteuerung per I2C und zweikanalig gibt's die auch.

Klaus_ww:
Was die DACs betrifft: mach Dir mal Gedanken über die gewünschte Genauigkeit und natürlich auch die notwendige Spannung für 100% Ausschlag. Dann kannst Du die Auflösung festlegen.
Es gibt diese 12 Bit DACs, findest Du überall unter Stichwort "arduino DAC", gleiches für 16 Bit. Ansteuerung per I2C und zweikanalig gibt's die auch.

Beim Überfliegen des Threads ist mir aufgefallen, dass im ersten Posting steht, dass die Aufgabe mit PWM gelöst werden soll:

benni73:
... Uns wurde gesagt, daß wir dazu ein PWM einbauen sollen mit einer konstanten Spannung von 5 V. ...

Mit DACs ist es sicherlich schneller als mit einem Tiefpass, aber die Geschwindigkeit scheint keine Rolle zu spielen. Ich denke, dass alles okay ist, bei dem ein Kreis in weniger als drei Minuten gezeichnet wird.

Kann jemand beschreiben, wie man die Werte für die Bauteile eines passenden Tiefpassfilters berechnet? Vielleicht ist das ja der Kern, auf den es bei dieser Sache ankommt.

Gruß

Gregor

Huch Gregor,

ich hatte Dich jetzt irgendwie in Verdacht das Thema angestoßen zu haben - aber das ist ja der schweigsame Benni, der sich auf den 3 Seiten kaum zu Wort meldet :o

Tiefpassfilter werden erst mal nach Tau = R*C berechnet, das ist die Zeitkonstante.
Hier müssen wir aber noch PWM-Frequenz mit berücksichtigen, die Ausgangsimpedanz des arduino und natürlich die Eingangsimpedanz des Schreibers. Und schon schauen wir wieder mit dem Ofenrohr in's Gebirge weil wir NIX wissen.

Zum anderen ist in meinen Augen die Aufgabe in Kombination "Gleichspannung durch PWM erzeugen" und "Kreis zeichnen" eher unglücklich. Ich verstehe das als minimale aber erschwerende Anforderung an die zu verwendende Hardware.

Aber ich spiele schon wieder mit meiner Kristallkugel ...

Klaus_ww:
Huch ...

Dass ich nicht der Einzige bin, der hin und wieder etwas verwechselt, ist beruhigend.

Beim etwas weniger schlampigen Querlesen der ersten Seite des Threads bin ich über den Link zu einer Webseite gestolpert, auf der einige Dinge zum Thema Tiefpassfilter erklärt sind. Dort gibt es auch einen Abschnitt „RC Low-pass Filter Design for PWM“. Ich werde mal sehen, ob ich entsprechende Teile in der Grabbelbox habe und ggf. ein bisschen spielen. Das Problem, aus einem PWM-Signal eine Gleichspannung zu machen, ist ja ziemlich allgemein und da es in vielen Fällen nicht auf die Geschwindigkeit ankommt, lohnt es sich vermutlich, ein solches Stück Analogschaltungstechnik zu kennen.

Gruß

Gregor

Also hier hilft nur das Verfahren
Versuch macht kluch ...
Teste mal folgende Routine für das Kreis-schreiben:

#define Entwackelzeit 10  // in msec
#define X_Kanal D1  // Ausgang PWM-X
#define Y_Kanal D2  // Ausgang PWM-Y

// hier fehlt die Initialisierung der I/O Pins
// und die Routinen für Aktivierung des Schreibstiftes...


void XY_Plotter_Kreis(int radius, int startwinkel, int endwinkel, int MittelpunktX, int MittelpunktY)
{
  bool PenDown=false;
  int laufenderWinkel, x, y;
  for (laufenderWinkel = startwinkel; laufenderWinkel <= endwinkel; laufenderWinkel++) { // wenn man mit 1°Auflösung zufrieden ist ...
    x = radius * sin(laufenderWinkel * 3.1415 / 180) + MittelpunktX;
    y = radius * cos(laufenderWinkel * 3.1415 / 180) + MittelpunktY;
    if (x < 0)  x = 0;
    if (x > 255) x = 255;
    if (y < 0) y = 0;
    if (y > 255) y = 255;
    analogWrite(X_Kanal, x);
    analogWrite(Y_Kanal, y);
    if (!Pendown) {
      // Schreibstift aufsetzen....
      Pendown = true;
    }
    delay(Entwackelzeit);
  }
  // Schreibstift abheben!
}

gregorss:
Mit den beiden von mir genannten Formeln bekommst Du jeweils einen Wert von -1 bis 1. Daraus musst Du einen Wert machen, der zwischen 0 und 255 liegt. Siehe map(). Wenn Du das hast, steuerst Du damit einen PWM-fähigen Pin an und machst aus dem PWM-Signal eine analoge Spannung. Wie diese Umformung von digital zu analog funktioniert, weiß jemand anderes. Wenn sich hier im Thread keiner dazu meldet, machst Du zu dieser Frage am besten einen neuen Thread auf.

Gruß

Gregor

Hier der Code:

int x_output = 12;

void setup() {

// put your setup code here, to run once:
TCCR0A = (1 << COM0A1 | 0 << COM0A0 | //clear OC0A on compare match (hi-lo PWM)

1 << COM0B1 | 0 << COM0B0 | //clear OC0B on compare match (hi-lo PWM)

1 << WGM01 | 1 << WGM00); //set PWM lines at 0xFF

TCCR0B = (0 << FOC0A | 0 << FOC0B | // no force compare match

0 << WGM02 | // set PWM lines at 0xFF

0 << CS02 | 0 << CS01 | // use system clock (no divider)

1 << CS00);

}

Int iRadius=4;

Int iX,iY;

iX=cos(360)* iRadius;
iY=sin(360)* iRadius;

void loop() {
// put your main code here, to run repeatedly:

analogWrite(x_output, 200);

}

0 << COM0A0

Das macht nicht was Leute denken die das verwenden. Es schadet zwar nichts (Ein ODER mit 0 bewirkt nichts) und kann vielleicht dazu dienen den Code zu dokumentieren, aber rein funktional ist es unsinnig. Es zeigt aber, dass nicht verstanden wurde wieso man eine 1 nach links schiebt. Und wo es völlig falsch ist, ist wenn man versucht so ein Bit zu löschen (was hier nicht der Fall ist).

Ich finde diese Schreibweise gut. So kann man jederzeit die Vorbesetzung aller Bits ändern, ohne etwas einflicken oder löschen zu müssen. Man kann sogar nach den Bits suchen, und sich deren Vorgabewerte anschauen.

Was mir garnicht gefällt, das ist die Verstellung von Timer 0. Damit kommt jegliches Timing durcheinander. Stattdessen sollte Timer 1 oder 2 verwendet werden.

Und die Ausgabe mit den Winkelfunktionen scheint auch noch viele Schwierigkeiten zu bereiten. Ich würde mit etwas einfachem anfangen, z.B. mit einem Quadrat, oder dem Haus vom Nikolaus.

gregorss:
Beim Überfliegen des Threads ist mir aufgefallen, dass im ersten Posting steht, dass die Aufgabe mit PWM gelöst werden soll:

Mit DACs ist es sicherlich schneller als mit einem Tiefpass, aber die Geschwindigkeit scheint keine Rolle zu spielen. Ich denke, dass alles okay ist, bei dem ein Kreis in weniger als drei Minuten gezeichnet wird.

Kann jemand beschreiben, wie man die Werte für die Bauteile eines passenden Tiefpassfilters berechnet? Vielleicht ist das ja der Kern, auf den es bei dieser Sache ankommt.

Gruß

Gregor

Hallo Gregor ich bin jetzt nach map() vorgegangen doch es hat nach wie vor leider nicht funktionert. Hier ist mein Code:

int x_output = 9;
int y_output = 10;
void setup() {
// put your setup code here, to run once:
TCCR0A = (1 << COM0A1 | 0 << COM0A0 | //Port OC0A wird auf 0 gesetzt und verglichen (Hoch-Tief PWM)
1 << COM0B1 | 0 << COM0B0 | //Port OC0B wird auf 0 gesetzt und verglichen (Hoch-Tief PWM)
1 << WGM01 | 1 << WGM00); // PWM linie wird auf 0xFF gesetzt
TCCR0B = (0 << FOC0A | 0 << FOC0B | // Kein erzwungener Vergleich
0 << WGM02 | // PWM Linie wird auf 0xFF gesetzt
0 << CS02 | 0 << CS01 | // Verwendung der Systemzeit(no divider)
1 << CS00);

}

void loop() {

// put your main code here, to run repeatedly:

analogWrite(x_output, 200);
analogWrite(y_output, 200);

long ix, iy;
int iradius;
iradius = 4;

ix = cos(360) * iradius;
iy = sin(360) * iradius;

y_output = map(iy, 1, 50, 50, 1); //Umformung eines PWM-Signals in eine analoge Spannung
x_output = map(ix, 1, 50, 50, 1); //Umformung eines PWM-Signals in eine analoge Spannung

}