Digitale Welle

Hi,

ich habe mir für ein Projekt eine Digitale Welle gebaut. D.h. es wird ein Drehsignal von einem Servomotor mittels Drehgeber abgegriffen und über einen Arduino Uno an einen Schrittmotor weitergeleitet und dort mit einem 2. Drehgeber überprüft. Es besteht keine mechanische Verbindung zwischen den beiden Motoren. Die Drehgeber arbeiten mit dem SSI Protokoll und sind Absolutdrehgeber. Das klappt auch alles soweit sehr gut.

Nun zur Frage:

Wenn das Geber-Signal zu schnell den Nulldurchgang passiert kann es sein das der Nehmer-Motor nicht dem Geber folgt, sondern eine knappe 360° Drehung zurück macht um diese Position anzufahren.

Hat einer ne Idee wie ich das verhindern kann? Also ich möchte dem Nehmer auch durch den Nulldurchgang “zwingen” ^^

Schonmal vielen Dank für die Hilfe

VG

Henne

Nunja...
In dem du die Überlauf/Unterlauf Bedingungen beabeitest.

Könntest du das etwas genauer ausführen? Die Drehgeber arbeiten im Bereich von 0-4096 Impulsen. Wenn sie die 4096 passieren springen sie wieder auf Null und andersrum von 0 auf 4096.

Und, brauchst du beide Drehrichtungen?

0 auf 4096

Du meinst sicherlich 0 bis 4095, oder?

PS:
Unsere "Nachtwächter Erklärung" zeigt, wie man den millies() Überlauf kompensiert.
Das gleiche Verfahren könntest du auch hier anwenden.

Ja beide Drehrichtungen sind wichtig.

Ne 4096 ^^ zumindest sagt das die Produktbeschreibung:

https://www.rls.si/en/products/re36-rotary-magnetic-shaft-encoder

"Nachtwächter Erklärung" schau ich mir an.

Nein, das steht da nicht!

Da steht:

... 4,096, ... counts per revolution)

Und 0 bis 4095, sind genau 4096 Impulse/Counts

Das hört sich vielleicht etwas pingelig an, aber Schlampigkeiten kann man sich da nicht leisten.
Schon gar nicht, genau auf der Überlaufschwelle.

Oh verdammt - du hast natürlich Recht. Asche auf mein Haupt :frowning:

Gut, dann ist schon mal eine Kuh vom Eis runter.

Ja beide Drehrichtungen sind wichtig.

Und?
Geht das Endlos, oder eine begrenzte Zahl von Umdrehungen?

:smiley:

Im Grunde dreht sich der Gebermotor immer nur max. 180° plus/minus. (wenn überhaupt)

Meine rein praktische Lösung sah bis jetzt aus den Nulldurchgang einfach dort hinzudrehen wo der Motor selten oder nie hinkommt.

Das heißt ein abgeschlossener Bewegungszyklus besteht aus ca 2048 Counts
Plus minus irgendeinen kleinen Betrag.

Ja, dann ist sollte das doch recht trivial sein.....
Auch wenn die Nullschwelle dabei überschritten wird.

Meine rein praktische Lösung sah bis jetzt aus den Nulldurchgang einfach dort hinzudrehen wo der Motor selten oder nie hinkommt.

Klar, um den Fehler drum rum eiern.....
(nur um dann doch ab und zu auf die Nase fallen)

Du hast mich eiskalt durchschaut :smiley: aber da es eben so ist wie du sagst bin ja jetzt an einer besseren Lösung interessiert.

Leider sind Microcontroller und die Programmierung derer so überhaupt nicht mein Fachgebiet, wenn du mir also noch etwas weiter auf die Sprünge helfen könntest wäre ich dir zu Dank verpflichtet. Vll kannst du es mir an einem Beispiel erkären?

Ja, nee…
Schöner Versuch, aber den Trick kenne ich schon…

  • Dein Kram muss geheim bleiben
  • Ich mache deine Arbeit
  • Und du sagst mir dann: Ähm, das passt so nicht in meine Anwendung rein.

Und was kann ich tun um deine Bedenken zu beseitigen? Geheim ist daran eigentlich nichts^^

Das klappt auch alles soweit sehr gut.

Nun zur Frage:

Wenn das Geber-Signal zu schnell den Nulldurchgang passiert kann es sein das der Nehmer-Motor nicht dem Geber folgt, sondern eine knappe 360° Drehung zurück macht um diese Position anzufahren.

Hat einer ne Idee wie ich das verhindern kann?

Meine Idee:
Erstmal genauer hinschauen - was ist "zu schnell" , wann geht es noch richtig ?
Beim genauer hinschauen helfen oft auch Serial.print Testausgaben.

Wie schaffst du es, dass du --langsam genug-- von 4095 nach 1 mit +2 kommst (statt durch -4094) ?

Ich schaue mir deinen Sketch übrigens nur lieber an, wenn du erstmal alles überflüssige entfernt hast, und eigentlich den Fehler auch selber sehen könntest. Aber komplett, also kompilierbar sein und das Problem zeigen, sollte er schon.

Ich will keine zerstreuten Bedenken!
Die kannst du nicht zerstreuen!
Bedenke, du bist nicht der erste mit dem Trick.
Und sicher nicht der letzte.

Und auch nein, an der Salamitaktik bin ich auch nicht interessiert.
Du wirst mich nicht dahin bekommen, dass ich nach jeder Scheibe bettle, und dann in 3 von 5 Fällen hängen gelassen werde.
Kenne ich auch schon!
Ist auch keine neue Taktik.

Tipp:
Ich bin hier im Forum weil ich lernen möchte.
z.B. Spannende Probleme bearbeiten, auf die ich nie von alleine gekommen wäre.
(dein Problem könnte ein solcher Fall sein)
Ich bin nicht hier um die Arbeit anderer (deine Arbeit) zu erledigen.

Leider sind Microcontroller und die Programmierung derer so überhaupt nicht mein Fachgebiet,

Und da kann ich auch nichts dran ändern.
Wenn du das lernen möchtest, gut und gerne, dann helfe ich dir auf die Sprünge.
Aber egal, was ich lerne, dir hilfts nicht weiter, denn davon lernst du nichts.
Das ist deine Baustelle!

Hi Leute hatte leider paar Tage keine Zeit das Thema weiter zu bearbeiten.

@michael_x mit dem zu schnell war quatsch habe ich festgestellt, es passiert immer.

@combie was dein Problem ist versteh ich ne aber ok ist deine Ding :slight_smile:

Hier mal das Sketch was soweit funktioniert, ich nutze seit heute das TOS-100 Motortreiber Board:

#include <SPI.h>
#include <TMC26XStepper.h>
#include <SSI.h>

SSI RM08(3, 4, 12); //Pins für den Drehgeber und die Genauigkeit (12 Bit)
SSI RM08_m(6, 7, 12); //Pins für den Drehgeber und die Genauigkeit (12 Bit)

//we have a stepper motor with 200 steps per rotation, CS pin 2, dir pin 6, step pin 7 and a current of 300mA
TMC26XStepper tmc26XStepper = TMC26XStepper(200,2,6,7,1000);

float Angle1 = 0;
float Angle2 = 0;
int schritte = 0;
int motorschritte = 0;
int encoderWert = 0;
int pause = 300;

void setup()
{

Serial.begin(9600);
Serial.println("==============================");
Serial.println(“TMC26X Stepper Driver Demo App”);
Serial.println("==============================");
//set this according to you stepper
Serial.println(“Configuring stepper driver”);
//char constant_off_time, char blank_time, char hysteresis_start, char hysteresis_end, char hysteresis_decrement
//tmc26XStepper.setSpreadCycleChopper(2,24,8,6,0);
tmc26XStepper.setSpreadCycleChopper(1,1,1,3,0);
tmc26XStepper.setRandomOffTime(0);

tmc26XStepper.setMicrosteps(4);
tmc26XStepper.setStallGuardThreshold(10,0);
Serial.println(“config finished, starting”);
tmc26XStepper.start();
Serial.println(“started”);

encoderWert = ((RM08.SSIread() - Angle1)*800/4096); //den Wert einlesen

}
void loop()
{

schritte = (((RM08.SSIread()) - Angle1)*800/4096); //den Wert einlesen
motorschritte = ((RM08_m.SSIread() - Angle2)*800/4096); //den Wert einlesen

if(schritte - encoderWert > 1) //grösser 0
{

digitalWrite(6,HIGH);

}

if(schritte - encoderWert < 1) //kleiner 0
{

digitalWrite(6,LOW);

}

if(abs(schritte - encoderWert) > 1)
{

for(int i=0; i <= abs(schritte - encoderWert); i=i+1)
{

Step();

}

motorschritte = ((RM08_m.SSIread() - Angle2)*800/4096) * -1; //den Wert einlesen

while(abs(schritte - motorschritte) > 5)
{

Step();

motorschritte = ((RM08_m.SSIread() - Angle2)*800/4096); //den Wert einlesen

}

encoderWert = schritte; //Wert des Encoders wieder auf 0 stellen

}

Serial.print(schritte);
Serial.print(", ");
Serial.println(motorschritte);

}

void Step() {

digitalWrite(7, HIGH);
delayMicroseconds(pause);
digitalWrite(7, LOW);
delayMicroseconds(pause);

}

Ich hab da mal was gebastelt:

// Finde den kürzeren Weg von a nach b
// a und b sind n-bit breite Zahlen
// n = 2 .. 15
// ---------------------------------------------
// Beispiel: n = 8 ( a,b = 0..255 )
// a = 255,  b = 1: diff = +2 oder -254, also +2
// a = 10, b = 255: diff = -11 oder +245, also -11
//
int diff(unsigned int a, unsigned int b, byte n) {
   unsigned int mask = (1 << n) - 1;
   unsigned int d = (a - b) & mask;
   if (d < (mask >> 1)) return -(int)d;
   d = -1 ^ (int)mask | d; // sign extend
   return - (int)d;
}

diff (4095,1,12) sollte 2 ergeben
diff (1,4095,12) sollte -2 ergeben

Ohne Überlauf gehts natürlich auch:

diff (10,22,12) sollte 12 ergeben
diff (22,10,12) sollte -12 ergeben

Viel Spass

Hallo!

Ich weiß nicht, wie weit Dein Vorhaben inzwischen ist - ich habe den Thread nicht verfolgt.

Aber vielleicht ist das noch hilfreich: Als ich meine el. Achse gebaut hatte, zeigten sich Fehler, die ich mir nicht erklären konnte. Ein Freund, der offensichtlich genauer beobachtet als ich, brachte mich darauf, dass die Ursache das Nachlaufen der Getriebemotore war.

Ich habe jetzt deutlich grobere Kodierscheiben, mit denen mein Roboter schnurgerade fährt:

Gruß

Gregor

OMG michael_x du bist der Beste :)))

Es funktioniert!

Nun habe ich noch eine Bitte. Ist es möglich den Zahlenraum für a und b selbst zu definieren, also das es keine n-breite Zahl ist, sondern eine beliebig breite Zahl? In meinem Fall wäre 800 gut, da mein Motor mit soviel Schritten läuft :smiley:

Edit:

Ich habs hinbekommen :slight_smile:

Ich hab einfach unten bei:

if(abs(Differenz) > 2)
{

for(int i=0; i <= abs(Differenz) - 0; i=i+5.12) //5.12 ist die Übersetzung 800 zu 4096
{

Step();

}

die Übersetzung rein gepackt und was soll ich sagen - es funktioniert!

danke nochmal an michael_x

Hallo,

dabei solltest du eine immer größer werdende Abweichung feststellen. i ist int, also Ganzahlenbereich. statt 5.12 wird immer nur 5 addiert. i müßte float sein damit es klappt. Oder du rechnest in float und castest das Ergebnis gerundet auf int.