PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kurve fahren



hai1991
03.08.2008, 22:42
hallo

ich möchte ein älteres thema wieder aufgreifen:
und zwar habe ich versucht den asuro eine kurve fahern zu lassen. dabei habe ich mich an GoTurn orientiert, aber leider klappt es nicht so wie ich wollte. vl kann mir jemand helfen.

hier einmal mein code:


#define BREITE 100 //spurbreite in mm
#define PI 3.141592


void kurve(int radius, int winkel, int speed) //radius in mm, winkel in Grad
{
unsigned long count_a_soll;
int count_a=0, count_i=0;
int speed_a, speed_i;
int radius_a, radius_i;
float quot, teiler;

MotorSpeed(0,0);
MotorDir(FWD,FWD);

radius_a=radius+BREITE/2;
radius_i=radius-BREITE/2;

teiler=(float)360/winkel; //Bruchteil des Kreises
quot=((float)radius_a)/((float)radius_i);


//berechnen der notwendigen tics am außenrad
count_a_soll=2*radius_a*(PI*10000L);
count_a_soll/=MY_GO_ENC_COUNT_VALUE;

//anfangsgeschwindigkeiten berechnen
speed_a=speed;
speed_i=speed/quot;

//Motoren starten
MotorSpeed(speed_i,speed_a);

while(count_a<count_a_soll)
{
count_a+=encoder[RIGHT];
count_i+=encoder[LEFT];

if(count_a<(count_i*quot)) speed_a+=5; //zu großer radius
if(count_a>(count_i*quot)) speed_a-=5; //zu kleiner radius


//reset encoder
EncoderSet(0,0);

MotorSpeed(speed_i,speed_a);
Msleep(1);
}
MotorDir(BREAK,BREAK);
Msleep(200);
}


kurz zur erklärung:
-erstmal kann nur eine kurve gegen den uhrzeigersinn gefahren werden (andere richtung möchte ich erst einbauen wenn diese funktioniert)
- _a bedeutet immer außen(rad)
- _i bedeutet immer innen(rad)


wenn ich diese funktion in ein programm einbaue und den asuro nach erfolgreichem flashen einschlate, dann fährt er zwar im kreis und regelt nach, jedoch hält er nicht nach dem vorgegebenen winkel an, und der radius stimmt leider auch nicht ganz

ebenso ist mir beim experimentieren aufgefallen, dass es bei mir auch bei der GoTurn funktion probleme gibt (er hält nich nach vorgegebenem weg an). daher vermute ich, dass es bei mir bei der odometrie ein problem gibt und würde euch ersuchen diese funktion einmal aus zu probieren, damit ich weiß, ober es nur an meinem asuro bzw. den werten in myasuro.h liegt, oder doch am oben angeführten code.

ich bedanke mich jetzt schon mal für eure hilfe und werde selber auch noch weiter experimentieren



sorry, ich habe vergessen zu erwähnen, dass sich der radius auf die mitte der hinteren achse bezieht (daher jeweils die korrektur um BREITE / 2 )

Sternthaler
05.08.2008, 22:51
Hai hai1991,

wie ich dass sehe, wird dein speed_i immer kleiner als speed_a

Über:
-- radius_a=radius+BREITE/2;
-- radius_i=radius-BREITE/2;
bekommst du also .._a ist immer größer als .._i , und dann mit:
-- quot=((float)radius_a)/((float)radius_i);
immer einen Wert in quot > 1, und dann mit:
-- speed_i=speed/quot;
immer speed_i = speed / (größer 1) also speed_i < speed.

So weit so gut.
Auch count_a_soll ist scheinbar auf dem richtig Weg berechnet.

Nun brichst du deine While()-Loop aber nur bzw. schon dann ab, wenn count_a den count_a_soll-Wert erreicht hat.

Du macht keine Prüfung, ob ein count_i_soll-Wert erreicht wurde.

Ich würde vorschlagen, dass du auch diesen count_i_soll-Wert berechnest, und dann deine while()-Loop so umbaust, dass sie erst dann abbricht, wenn beide Soll-Werte erreicht wurden.


Ich selber nutze einen etwas anderen Ansatz.
So wie du, berechne ich auch das Verhältnis zwischen Innen und Außen.
Allerdings nutze ich die vorher ermittelten Tik’s als Verhältnis. Um sowohl Rechtskurve, als auch Linkskurve zu berücksichtigen, dividiere ich in meine quote-Variable so, dass immer ein Wert > 1 berechnet wird. (Also immer Außen-Soll-Tick's / Innen-Soll-Tik's)
Dann aber nutze ich beide gezählten Tik’s aus der Variablen encoder[] und berechne aus dem inneren encoder[]-Wert mit dem quot multipliziert einen 'getürkten' Wert. Da mein quote ja auch immer größer 1 ist, wird es als eine größere Tik-Anzahl vom Innenweg berechnet.
Dieser getürkte Wert stellt nun den Weg dar, den die Innenseite gefahren wäre, wenn sie genau so weit wie die Außenseite gefahren wäre.
Also müssen beide Werte, Außen-Soll-Tik und Innen-Türk-Tik, einfach nur gleich viele Tiks haben.
Das erledigt dann die bekannte GoTurn-Funktionalität beim Go-Teil.

Viel Erfolg
Gruß Sternthaler

P.S.: Ich habe dein Programm nicht getestet, da ich sicher bin, dass eben die Berücksichtigung/Kontrolle der Innen-Seite fehlt.

hai1991
07.08.2008, 18:58
hallo sternthaler und aller anderen

ich glaube einen fehler habe ich schon gefunden:
und zwar habe ich im main() vorm aufruf von kurve() vergessen ein EncoderInit() zu schreiben. das konntet ihr allerdings nicht wissen. jetzt bleibt er wenigstens stehen, wenn auch nicht mit dem gewünschten radius und winkel.


@ sternthaler:
sry, aber ich kann mir gerade nicht vorstellen, wie ich die abbruchbedingung umschreibe soll, damit sie deinem rat entspricht .
denn wenn ich nur abbreche wenn beide couter die richtige anzahl haben, also so:


while(count_a!=count_a_soll && (count_i*quot)!=count_a_soll))
{
//Programm siehe oben
}

werd er nie stehen bleiben.


oder wenn ich es so schreibe:


while(count_i*quot<count_a_soll)

bleibt er nur stehen wenn count_i den wert erreicht hat, also wieder das selbe wie mein erster versuch


das ist aber nicht das einzige problem! denn der radius stimmt auch nicht
hast du dazu vl. auch noch eine idee was es sein kann?

ich habe mir schon gedacht, dass man am anfang die startgeschwindigkeit vl. nich einfach so ausrechnen kann, der er doch erst ab etwa einem wert von 60 losfährt.
das komisch ist nur, dass er sich auf einen radius regelt, der überhaupt nicht stimmt. auch wenn ich ihn einen größeren winkel fahren lassen



ich weiß derzeit wirklich nicht mehr weiter, und bin daher dankbar für jeden tipp

Sternthaler
08.08.2008, 00:45
Hallo hai1991,

ich nutze eine Version zum Abbrechen, ähnlich der, die du als erstes aufgeführt hast.
Aber nicht mit dem !=, sondern auch mit einem <, wie in deinem ersten Programm. (Das != ist ja schnell vorbei, wenn das Rad noch etwas weiterdreht. Und schon arbeitet die Loop wieder weiter.)
Ich würde folgendes machen:

while (count_a < count_a_soll || count_i < count_i_soll)
{
// Innenleben
}

Ich habe nochmal meine Antwort und dein erstes Programm verglichen.
Du machst eigentlich auch 'meinen' Ansatz, dass du das Verhältnis der Tik's nutzt. Mir ist nicht klar gewesen, dass beide Verhältnisse (ich Tiks; du Radius) identisch sind. (Also kannst du auch sagen, dass ich deinen Ansatz benutze ;-))

OK, somit muss das Problem doch eher in der Loop zu suchen sein.
Dein Hinweis, dass du in deinem main() vergessen hattest, EncoderInit() aufzurufen, führt mich zu folgender Überlegung:

while(count_a<count_a_soll) // Egal, wie abgebrochen wird
{
// Interruptsystem ist aktiv.
// In encoder[] werden einzelne Tiks gesammelt.

// Nun werden die aktuell ermittelten Tiks gelesen und lokal addiert.
// ---> encoder[] kann nun z.B. [0, 1] enthalten, da RECHTS ja
// schneller gefahren wird.
count_a+=encoder[RIGHT];
count_i+=encoder[LEFT];
// count_a ist nun um eins vergrößert,
// count_i hat sich nicht geaendert.

// Das Interruptsystem erzeugt nun genau an dieser Stelle eine
// Aenderung in encoder [LEFT] auf 1.
// Dieser Tik ist NICHT in count_i abgelegt worden.

if(count_a<(count_i*quot)) speed_a+=5; //zu großer radius
if(count_a>(count_i*quot)) speed_a-=5; //zu kleiner radius

// Nun werden die encoder[]-Inhalte beide auf 0 gesetzt.
//reset encoder
EncoderSet(0,0);

MotorSpeed(speed_i,speed_a);
Msleep(1);



// Hier nun der 2.te Durchlauf der Loop

// Das Interruptsystem ist natürlich weiterhin aktiv.
// In encoder[] werden wieder einzelne Tiks gesammelt.

// Nun wieder die ermittelten Tiks lesen und lokal addieren.
// ---> encoder[] kann nun schon wieder [0, 1] enthalten
// da ja das rechte Rad immer noch schneller ist.
count_a+=encoder[RIGHT];
count_i+=encoder[LEFT];
// Jetzt ist count_a nun schon um zwei vergrößert,
// und in count_i hat sich immer noch nichts geaendert.

// Auch jetzt liefert das Interruptsystem wieder an dieser Stelle eine
// Aenderung in encoder [LEFT] auf 1.
// Auch dieser Tik ist NICHT in count_i abgelegt worden.


// Durch diese if's reduziert du nun permanent speed_a, da ja in count_a
// die Tikzahl waechst, aber count_i 'immer' bei 0 bleibt.
if(count_a<(count_i*quot)) speed_a+=5; //zu großer radius
if(count_a>(count_i*quot)) speed_a-=5; //zu kleiner radius


// Und schon wieder den einen Tik "verlieren".
//reset encoder
EncoderSet(0,0);

MotorSpeed(speed_i,speed_a);
Msleep(1);

// usw.


}

Folgende Änderung würde ich mal probieren:

//reset encoder VOR DIE SCHLEIFE
EncoderSet(0,0);
while(count_a<count_a_soll) // Egal, wie abgebrochen wird
{
// NICHT addieren, SONDERN zuweisen
count_a = encoder[RIGHT];
count_i = encoder[LEFT];

if(count_a<(count_i*quot)) speed_a+=5; //zu großer radius
if(count_a>(count_i*quot)) speed_a-=5; //zu kleiner radius

MotorSpeed(speed_i,speed_a);
Msleep(1);

// WEG MIT DEM "reset encoder"

MotorSpeed(speed_i,speed_a);
Msleep(1);
}

Mit der Konstruktion, solltest du keine Tiks mehr verlieren.
Ob es tatsächlich hilft?
Zumindest kommt es nun meiner Konstruktion ein Stückchen näher, und ich kann Kurven fahren. O:)


Zu deiner Bemerkung über die Startgeschwindigkeit noch ein Wort:

...
quot=((float)radius_a)/((float)radius_i);
...
//anfangsgeschwindigkeiten berechnen
speed_a=speed;
speed_i=speed/quot;

if (speed_i < MIN_SPEED)
{
speed_i = MIN_SPEED;
speed_a = MIN_SPEED * quot;
if (speed_a > 255)
speed_a = 255;
}
...
Ich halte den Ansatz von dir für sinnvoll, auch den Speed anhand des quot vorzubelegen.
Das Anfahren aber mit MIN_SPEED sicherstellen. Der Rest sollte von deinem 'Regler' erledigt werden. Wobei bei dir aber noch keine Grenzbetrachtungen vorhanden sind.

Frohes testen wünscht
Sternthaler

hai1991
08.08.2008, 15:16
hallo sternthaler

danke für deine ausführliche antwort!
ich werde mich sofort daran machen alles in meine funktion ein zu bauen und zu testen.

ehrlich gesagt, auf die idee mit den verlorenen ticks wäre ich selber nie gekommen. mal schauen obs daran lag und melde mich wieder so bald ich etwas weiß

edit:
ich habe bei mir noch einen fehler gefunden:
bei der berücksichtigung des teilers habe ich *teiler gerechnet, anstatt zu dividieren.
nun sieht meine funktion so aus:


#define BREITE 103 //spurbreite in mm
#define PI 3.141592



void kurve(int radius, int winkel, int speed)
{
unsigned long count_a_soll,count_i_soll;
int count_a=0, count_i=0;
int speed_a, speed_i;
int radius_a, radius_i;
float quot, teiler;

MotorSpeed(0,0);
MotorDir(FWD,FWD);

radius_a=radius+BREITE/2;
radius_i=radius-BREITE/2;

teiler=(float)360/winkel; //Bruchteil des Kreises
quot=((float)radius_a)/((float)radius_i);


//berechnen der notwendigen tics am außen- und innenrad
count_a_soll=2*radius_a*(PI*10000L/teiler);
count_a_soll/=MY_GO_ENC_COUNT_VALUE;
count_i_soll=count_a_soll/quot;

//anfangsgeschwindigkeiten berechnen
speed_a=speed;
speed_i=speed/quot;
//speed_i=speed;

//Motoren starten
MotorSpeed(speed_i,speed_a);

while(count_a<count_a_soll || count_i<count_i_soll)
{
count_a=encoder[RIGHT];
count_i=encoder[LEFT];

if(count_a<(count_i*quot)) speed_a+=10; //zu großer radius
if(count_a>(count_i*quot)) speed_a-=10; //zu kleiner radius


//reset encoder
//EncoderSet(0,0);

MotorSpeed(speed_i,speed_a);
Msleep(1);
}
MotorDir(BREAK,BREAK);
Msleep(200);
}


jetzt bleibt er zwar stehen, aber erst nach dem doppelten winkel, aber dem halben radius

ich könnte es zwar vor der berechnung der tiks korrigiern, aber trotzdem wüsste ich zu gerne woher das kommt

Sternthaler
09.08.2008, 03:10
Moin hai1991,

nur ganz kurz diesmal.

- Peinlich: In deinem ersten Beitrag ist mir nicht aufgefallen, dass teiler zwar berechnet, aber nicht benutzt wird.

- EncoderSet() finde ich nicht vor der Schleife in deinem letzten Beitrag.

- Doppelter Winkel heißt mehr Weg; halber Radius heißt weniger Weg.
Gleicht sich das mathematisch in Summe aus, so dass zumindest die Länge des Wegs in Tik’s bzw. in 'Geometrie' passt?
Wenn ja, dann würde ich auf ein Problem mit deinem Wert für MY_GO_ENC_COUNT_VALUE tippen. -> Anderer Wert soll dein Problem dann ausgleichen. (Ist im Moment meine Hoffnung. Hängt vom Ergebnis der Tik/Geometrie-Frage ab. Manchmal sollte ich ein Bild malen um zu sagen was ich sagen will ;-))
Kennst du ASURO ermittelt Werte für Lib V2.70 myasuro.h selber (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=31073)? Da wird auch MY_GO_ENC_COUNT_VALUE vom Asuro selber bestimmt. (Mit freundlicher Unterstützung von dir.)
Dann ist da natürlich jetzt auch die Frage nach der Anzahl der Schwarz-/Weißflächen auf deinen ODO-Scheiben. Die aktuell in der Asuro-LIB angegebene Zahl von 19363 für MY_GO_ENC_COUNT_VALUE ist für ODO-Scheiben mit jeweils 8 mal Schwarz- und Weiß-Flächen.
Wenn du die 4+4-Scheibe drauf hast, könnte das ja schon diesen Fehlerfaktor 2 ausmachen. Die Hoffnung stirbt zuletzt.

Schönes Wochenende, und viele Goldmetall-ien für die Sieger.
Gruß Sternthaler

hai1991
10.08.2008, 11:57
hallo sternthaler und natülich auch alle anderen, die sich dafür interessieren oder mir helfen wollen

die werte in MY_GO_ENC_COUNT_VALUE habe ich schon an meinen Asuro angepasst (ich habe extra noch mit Go() geteste, alles so wie es sein sollte)
trotzdem zur info: ich habe scheiben mit 6 schwarz- weiß-flächen montiert


bei mir hat zwar noch nicht alles gepasst, trotzdem habe ich die geschwindigkeitsanpassung ähnlich der von GoTurn umgeändert, da ich mir dachte, dass es vl an der geschwindigkeitsbegrenzung bei 255 liegen kann. leider hat es auch nichts geholfen.
zusätzlich habe ich noch die zweite richtung ein zu bauen versucht ( positives vorzeichen beim winkel sollte eine kurve im gegenuhrzeigersinn sein)

wenn ich jetzt meine fkt wie folgt aufrufe


kurve(300,180,150)

passten zwar radius und winkel nicht, aber die richtung.

wenn ich jetzt aber schreibe


kurve(300,180,200)

, also eine geschwindigkeitsänderung, dann fährt mein asuro auf einmal in die falsche richtung. ich habe aber keine ahnung woher das kommen könnte.

hier einmal meine funktion:


void kurve(int radius, int winkel, int speed)
{
unsigned long count_a_soll,count_i_soll;
int count_a=0, count_i=0;
int speed_a, speed_i;
int radius_a, radius_i;
float quot, teiler;

MotorSpeed(0,0);
MotorDir(FWD,FWD);

radius_a=radius+BREITE/2;
radius_i=radius-BREITE/2;

teiler=(float)360/abs(winkel); //Bruchteil des Kreises
quot=((float)radius_a)/((float)radius_i);


//berechnen der notwendigen tics am außen- und innenrad
count_a_soll=2*radius_a*(PI*10000L/teiler);
count_a_soll/=MY_GO_ENC_COUNT_VALUE;
count_i_soll=count_a_soll/quot;

//mindestgeschwindigkeit=70
if(speed<70) speed=70;

//anfangsgeschwindigkeiten berechnen
speed_a=speed;
speed_i=speed_a/quot;
//speed_i=speed;

//Motoren starten
if(winkel>0)
MotorSpeed(speed_i,speed_a);
else
MotorSpeed(speed_a,speed_i);

EncoderSet(0,0);

while (count_a<count_a_soll)
{
//Odometrie einlesen
if(winkel>0)
{
count_a=encoder[RIGHT];
count_i=encoder[LEFT];
}
else
{
count_a=encoder[LEFT];
count_i=encoder[RIGHT];
}


//Geschwindigkeiten anpassen
if (count_a <(count_i*quot))
{ /*außen zu langsam */
if ((speed_a > speed) || (speed_a > 244))
speed_i -= 10;
else
speed_a += 10;
}

if (count_a >(count_i*quot))
{ /* außen zu schnell */
if ((speed_a > speed))
speed_a -= 10;
else
speed_i += 10;
}

/* reset encoder */
//EncoderSet (0, 0);

if(winkel>0)
MotorSpeed(speed_i,speed_a);
else
MotorSpeed(speed_a,speed_i);

//Msleep (1);
}



ich bedanke mich jetzt schon für jeden tipp

Sternthaler
10.08.2008, 13:19
Hallo hai1991,

kannst du bitte deinen Wert für MY_GO_ENC_COUNT_VALUE angeben.
Ich bin dabei deine beiden Parameter-Aufrufe mit dem Taschenrechner nachzurechnen.
Gestolpert war ich bei
"count_a_soll = 2 * radius_a * (PI * 10000L / teiler);"
dass dort der Wertebereich mit int zu klein wäre. Aber da hast du ja schon aufgepasst und ein "unsigned long" vergeben.

Bis nachher
Gruß Sternthaler

[EDIT]
Mit einem angenommenen Wert von 15000 kann ich aber so auch nichts falsches feststellen.
Eine Stelle "while (count_a < count_a_soll)" ist natürlich noch ein Vergleich zwischen "int" und "unsigned long". Das solltes es aber keinesfalls sein, da davon ja nicht die Speed-Berechnung abhängt.

Es wird wohl Zeit, dass ich dein Programm mal bei mir laufe lassen.
Kannst du den aktuellen Stand bitte mal posten. Mit Angabe, welche LIB-Version du nutzt.

hai1991
14.08.2008, 20:00
hallo sternthaler

ich hatte jetzt nie wirklich zeit um dir zu antworten!

hier einmal mein code:


void kurve(int radius, int winkel, int speed)
{
unsigned long count_a_soll,count_i_soll;
int count_a=0, count_i=0;
int speed_a, speed_i;
int radius_a, radius_i;
float quot, teiler;

MotorSpeed(0,0);
MotorDir(FWD,FWD);

radius_a=radius+BREITE/2;
radius_i=radius-BREITE/2;

teiler=(float)360/abs(winkel); //Bruchteil des Kreises
quot=((float)radius_a)/((float)radius_i);


//berechnen der notwendigen tics am außen- und innenrad
count_a_soll=2*radius_a*(PI*10000L/teiler);
count_a_soll/=MY_GO_ENC_COUNT_VALUE;
count_i_soll=count_a_soll/quot;

//mindestgeschwindigkeit=70
if(speed<70) speed=70;

//anfangsgeschwindigkeiten berechnen
speed_a=speed;
speed_i=speed_a/quot;
//speed_i=speed;

//Motoren starten
if(winkel>0)
MotorSpeed(speed_i,speed_a);
else
MotorSpeed(speed_a,speed_i);

EncoderSet(0,0);

while (count_a<count_a_soll)
{
//Odometrie einlesen
if(winkel>0)
{
count_a=encoder[RIGHT];
count_i=encoder[LEFT];
}
else
{
count_a=encoder[LEFT];
count_i=encoder[RIGHT];
}


//Geschwindigkeiten anpassen
if (count_a <(count_i*quot))
{ /*außen zu langsam */
if ((speed_a > speed) || (speed_a > 244))
speed_i -= 10;
else
speed_a += 10;
}

if (count_a >(count_i*quot))
{ /* außen zu schnell */
if ((speed_a > speed))
speed_a -= 10;
else
speed_i += 10;
}

/* reset encoder */
//EncoderSet (0, 0);

if(winkel>0)
MotorSpeed(speed_i,speed_a);
else
MotorSpeed(speed_a,speed_i);

//Msleep (1);
}
MotorDir(BREAK,BREAK);
Msleep(200);
}


kleine Änderung am 16.8.2008, 9:36

diese infos hatte ich vorher versehentlich zu meinem code hinzu gefügt:
ich verwende die lib 2.71
mein wert von MY_GO_ENC_COUNT_VALUE beträgt 21240L
und zum prog. verwende ich "eierlegende Wollmilchsau" (Asuroflash von Osser), falls das auch noch wichtig ist

ich hoffe du kannst damit was anfange

hai1991
22.08.2008, 18:59
hallo asuroianer

kann das problem vl darin liegen, dass ich radius und winkel als int definiert habe, aber werte hineinschreibe die größer als 255 sind.

könnte es was helfen, wenn ich radis als unsigned int nehme und bei winkel ein long ( das ist doch der "größere int", oder teusche ich mich da gerade???)

Sternthaler
23.08.2008, 02:15
Hallo hai1991,

entschuldie bitte, dass ich dich vergessen habe.
Ich habe dein Programm immer noch nicht bei mir probiert.

Zu deiner Frage mit int und Werten größer 255 kann ich aber schon etwas sagen:


Typ Bitanzahl unsigned [Typ] signed [Typ]
char 8 0 bis 255 -128 bis 127
int 16 0 bis 65535 -32768 bis 32767
long 32 0 bis 4294967295 -2147483648 bis 2147483647
Um bei Vorzeichen-Variablen rauszubekommen wie weit sie nun nach minus bzw. plus gehen muss du so rechnen:
minus: 2 ^ Bitanzahl / 2 * -1
plus: 2 ^ Bitanzahl / 2 - 1

Zu dem Thema hatte ich schon mal ein kleines Programm für den Asuro geschrieben. Und auch wiedergefunden (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=340377#340377) ;-).
Es gibt die Byte-Anzahl aller Datentypen per IR am PC aus.
Auch gut, dass ich da eine Bedienungsanleitung reingeschrieben hatte:
"Nach dem Loslassen irgendeiner gedrueckten Taste wird die benutzte Byteanzahl aller Datentypen ueber IR ausgegeben."

Ich hoffe, dass ich dein Programm in nächster Zeit mal wirklich testen werde.
Gruß Sternthaler

hai1991
23.08.2008, 09:43
hallo sternthaler

danke für deine antwort.
aber ich muss zugeben dass mir in der zwischenzeit auch schon eingefallen ist, dass ich da irgend wie die werte vertauscht habe und es daher auch nicht daran liegen kann. trotzdem danke für die antwort

es ist eben so, dass ich einfach nicht mehr weiß was an meinem code falsch bzw. nicht ganz optimal ist. und ich möchte es so gerne auch einmal schaffen, dass er ein vorgegebene kurve fährt.

hat wirklich niemand mehr eine idee woran es liegen kann

mausi_mick
24.08.2008, 12:06
hi hai1991,

hab mal Deine letzte Version getestet,
mit folgenden Änderungen:
Motorstarten hinter Anfang der while ( count_a ... ) Schleife gesetzt,
anschliessnde EncoderSet(0,0);
dann mal 10 ms warten: Msleep (10);



am Ende der Schleife das Setzen von MotorSpeed eliminiert.

Bis auf die 10ms warten wohl nur formale Änderungen.

Ich denke, Du musst dem Encoderzähler mehr Zeit lassen,
das Rad braucht ein paar ms zum zählen.

Die Übergabeparameter könnte/sollte man auch irgendwo prüfen (Radius gösser halber Spurweite ?, Winkel(basolut) < 360 ? ,speed < 255 ?)
Ich hab's mit einem Rückkgabeparameter (char anstelle von void) gemacht, den ich im aufrufenden Programm auswerten kann.

Vielleicht irre ich mich ja, aber zumindest hat mein ASURO
im Test je nach Winkel und Durchmesser Links- bzw. Rechtskurven
ausgeführt.

Ich hab dabei aber Deinen Wert (MY_GO_ENC.. 21240L ) übernommen .
Ich komme aber, bei den Werten , bei meinem ASURO nicht aus der
while-Schleife raus, da count_a bzw. encoder[0] bzw. [1] auch bei 10 ms deulich unter count_a_soll liegt.
Im Asuro Original-Programm (GoTurn in encoder.c ) geht der Schleifen-Abbruch über tot_count, das pro Schleifendurchlauf um encoder[LEFT] erhöht wird.

Am besten baust Du mal ein paar PrintInt ein, um dir die Encoder, speed und count-Werte anzusehen.

Auch dei 10 ms für den Encoder müsste man mal überprüfen.

Vielleicht hast Du aber ein anders Problem

Gruss

mausi_mick

Sternthaler
25.08.2008, 00:35
Hallo mausi_mick, hallo hai1991,

ja mausi_mick, das scheint mir eine sehr gute Sicht auf die Dinge zu sein. (Jetzt wo du es sagst kommt man da "wie von selbst" drauf ;-))

Wenn man mal nachrechnet:
ca. max Speed : 450 [mm/s]
ca. min Speed : 180 [mm/s]

Bei 8 schwarz- / 8 weiß-Teilen auf der Odoscheibe:
1 Tick entsprich ca. 1,5 [mm]

Bei "max Speed" somit ca.: 450 [mm/s] / 1,5 [mm] = 300,0 [Tiks/s] = 3,3 [ms/Tik]
Bei "min Speed" somit ca.: 180 [mm/s] / 1,5 [mm] = 120,0 [Tiks/s] = 8,3 [ms/Tik]

Die 10 [ms] scheinen somit eine gute Wahl gewesen zu sein. (Hast du bestimmt genau so wie ich berechnet mausi_mick. Nur dass du bestimmt der Devise 'Erst denken, dann handeln' gefolgt bist.)


Was passiert da aber, wenn man 'zu schnell' ist?
In jedem Schleifendurchlauf wird festgestellt, dass eine Seite nicht so läuft wie erwartet.
Dann wird Speed auf der entsprechende Seite um 10 reduziert/erhöht.
Weiterschleifen ohne Bremse.
Nun wird noch kein weiterer Tik festgestellt, somit wird wieder um 10 reduziert/erhöht. usw. usw.

Wenn man jetzt Pech hat, wird das Spiel so häufig wiederholt, dass Speed > 255 wird, oder Speed geht so weit zurück, dass der Motor stehen bleibt.
Beides dürfte recht fehleranfällig sein. Denn auch wenn speed_a und speed_i int-Variablen sind, werden ja, worauf mausi_mick ja schon mit der fehlenden Prüfung hinwies, nur die hinteren 8 Bits der Variablen als Wert in MotorSpeed() benutzt. Wer weiß schon wie die dann stehen.

Abraten würde ich aber, dass die Werte in der Schleife an den PC gesendet werden da die Übertragungsgeschwindigkeit pro Zeichen bei ca. 5 [ms] liegt.
Also bei 3-stelligem Werte und beiden Seiten, 7 Zeichen (3 + Leerzeichen + 3). Damit erzeugen wir eine Verzögerung von ca. 35 [ms].
Das ist prozentual aber schon extrem gegenüber den jetzigen 10 [ms].
Lieber die Daten in der Schleife speichern, und nach der Schleife, auf Tastendruck, an den PC senden.

Aber noch mal zurück zum Msleep() mit den jetzigen 10 [ms]
Bei langsamer Fahrt können wir dann schon ca. 3 Tiks 'verpasst' haben.
Das ist ein relativ großer Fehler bei jeweils 1,5 [mm] pro Tik.

Vorschlag:
long tik_summe;

while (count_a<count_a_soll)
{
tik_summe = encoder [LEFT] + encoder [RIGHT];
while (tik_summe == encoder [LEFT] + encoder [RIGHT])
;

/*
Hier weiter mit deinem Code.
Msleep (xx); ist dann auch nicht mehr notwendig,
da ja auf alle Fälle ein Tik gewartet wurde.
*/
}Dies würde die Problematik bei einer konstanten Wartezeit eliminieren.

Gruß Sternthaler
P.S.: Der Code war immer noch nicht in meinem Asuro. :oops:

mausi_mick
25.08.2008, 07:50
Hallo Sternthaler,
hallo hai1991,

Danke für den Tip mit der Ausgabe der Messwerte.

Hab nochmal ein wenig getestet und das Progamm modifiziert,
auch Richtung Sicherheit (z.B. winkel 0 nicht zulassen) Auch hab ich einen
Wert für die Tiks vorgegeben, ab dem erst die Geschwindigkeit verändert werden soll (z.B. 10 oder 20 Tiks.
Scheint bei mir zu laufen, nur etwas ruckhaft. Vielleicht muss man die Geschwindigkeitsänderung (+-10) auch in Abhängigkeit der Tik-Differenz modifizieren.
Ich versuch mal , den Code einzubinden, weiss aber (noch) nicht, wie das geht

Gruss mausi_mick

hai1991
25.08.2008, 20:23
hallo ihr beiden

schön, dass sich noch jemand zu uns gesellt (ich glaube zu dritt hat man mehr ideen und hoffe, dass es bei mir auch bald klapt)

nur kurz als info:

winkel 0 nicht zulassen
das habe ist meiner meinung nach nicht nötig, da 0° immer ein count_a_soll=0 ergebt, und er somit nicht in die schleife eintritt, aber man kann es natürlich als sicherheit noch hinzufügen


Winkel(basolut) < 360 ? ,speed < 255 ?
winkel>360° kann vl. auch gewollt sein, darum kontrolliere ich das nicht
und speed>255 vermeide ich hier:


if (count_a <(count_i*quot))
{ /*außen zu langsam */
if ((speed_a > speed) || (speed_a > 244))
speed_i -= 10;
else
speed_a += 10;
}

da ich außen nur erhöhe falls speed_a<244 (244+10=254, also <255)


so, genug geschrieben. jetzt bin ich wieder zum ausprobieren dran
sobald ich was neues weiß lasse ich es euch sofort wissen

mausi_mick
26.08.2008, 06:00
hallo hai1991,
mit dem Winkel und der Speed sind nur formale Sachen,
aber Du solltest entweder in der Funktion oder vom Hauptprogramm solche Werte verhidern, da Du z.B. durch den Winkel teilst, und das ist bei Winkel = 0 nicht so doll.
Mit der speed meine ich nicht speed_a bzw. speed_i, sondern den Übergabewert speed.

Die Winkelbegrenzung nach oben hab ich auch nicht realisiert, so kann ich auch z.B. mal 2 oder 1,5 Kreise fahren.

Wäre eigentlich nicht schlecht, wenn man das Programm auch zum
exakten Geradeausfahren verwenden könnte (Radius = 0), aber dann hat man Probleme mit dem Fahrtende über den Winkel, oder man müsste dann den Winkel als Fahrzeit (Msleep) interpretieren.
z.B: kurve(0,-450,170) bedeutet:
fahre geradeaus, rückwärts 450 sec lang, mit speed 170.

Und übrigens: mein Programm läuft auch nicht mehr, oder ähnlich wie Deins:
Die erste Kurve macht er noch richtig, bei der zweiten macht er irgendwas und das fast Geradeausfahren (mit dem grossen Radius) fuktioniert auch nicht.
Ich glaube, ich hab mir die Parameter MY_ODOMTERIE_DARK ... Parameter (in My_ASURO.H) zerschossen (ich hab einen Original-Asuro und einen umgebauten Asuro, der andere Radsätze/Übersetzungen und andere (bessere?) Sensoren (CNY70), die nicht so Umgebungslicht empfindlich sind, verwendet).

Ich muss mal sehen, dass ich da bessere Werte bekomme, damit die ADC's der Encoder wieder vernünftige Werte liefern.

Gruss
mausi_mick

Sternthaler
26.08.2008, 09:26
Guten Morgen.

Hallo mausi_mick,
kannst du mir den Sinn bez. die Idee erklären, die du mit dem Code bewirken möchtest:
Msleep (dauer);
count_a = encoder [RIGHT];
if (count_a == enc_ad)
dauer = dauer + 1;
enc_ad = count_a - enc_ad;
if (enc_ad >= min_tik) // ab z.B 10 tiks prüfen
{Du erhöhst ja ab und zu die Variable dauer. Passt sich der Wert im Laufe der Zeit von alleine an einen sinnvollen, zur Geschwindigkeit passenden, Wert an?

Ich habe mal Excel etwas bemüht, um rauszubekommen, wie sich der Wert in dauer verändert könnte.
Auch der Wert in enc_ad ist mir bei meinen Excel-Versuchen noch nicht so richtig sinnvoll vorgekommen. Meistens bleibt er bei mir unter den 10 aus min_tik.
Hilfe, mir gehen die Ideen aus, wie sich die Dinger verhalten sollten.

Gruß Sternthaler

mausi_mick
26.08.2008, 11:58
Hi Sternthaler,

hab das nur mal mit dem Erhöhen der dauer probiert, falls der Encoderwert zwischen zwei Aufrufen nicht hochgezählt wird.
Hab das aber wohl nicht sauber ausgetestet.

Anders als bei hai1991 wollte ich auch nicht mehr zur Geschwindigkeitsberechnung die Encoderwerte von Anfang an (EncoderSet(0,0) ist wohl nur vor der Schleife gesetzt) berücksichtigen,
sondern nur die seit dem letzten Aufruf (-dauer).
Wenn in dem Zeitraum aber nur wenige Tiks anfallen, wird wohl die Ungenauigkeit recht gross.
Auch müsste man sich überlegen, ob nicht bei kleinen Differenzen links/rechts die Speed-Änderung kleiner als 10 ausfallen müsste.


Gruss
mausi_mick

hai1991
26.08.2008, 18:20
hallo

gleich vorweg:
jetzt funktioniert es bei mir auch schon recht gut (vl. noch die werte in myasuro.h etwas umändern/anpassen, dann müsste er hoffentlich schöne kurven fahren)

@mausi_mick
die idee mit der kombination aus kurve und gerade faheren hatte ich auch schon, nur habe ich mir das etwas anders vorgestellt:
was wäre wenn an einfach die GoTurn() hernimmt und etwas abändet?
wenn winkel=0: eine gerade streche fahren
distance=0: drehen
winkel und distance haben einen anderen wert als 0: dann könnte man distance als radius interpretieren und eine kurve fahren

somit hätte man alles in was man so zum fahren braucht in einer funktion und könnte sie natürlich dementsprechend auch umbenennen auf Drive()

dann müsste man aber natürlich auch die von dir angesprochenen sicherheitsabfragen bezüglich zu hoher geschwindigkeit einbauen

Sternthaler
26.08.2008, 20:44
Hallo ihr Beiden,

wenn ihr schon auf dem Wege seid eine Funktion zu schreiben, die 'alles' kann, dann wäre es nicht schlecht, wenn ihr euch ein bisschen an die bestehende Lib anlehnen würdet bei den Parametern.

Aktuell heißt deine Funktion hai1991:
void kurve(
int radius,
int winkel,
int speed)
{
..
}

Die Funktion in der Lib heißt aktuell:
void GoTurn (
int distance,
int degree,
int speed)
{
..
}
Ich benenne mal deine Funktionsparameter um, und nehme noch den Parameter distance aus der Lib dazu:
void kurve(
int distance, /* aus der Lib */
int radius, /* dein int radius, */
int degree, /* dein int winkel, */
int speed) /* dein int speed) */
{
..
}Nun sind immer noch deine Parameter vorhanden, und aus der Lib ist nur distance hinzugekommen.

Und jetzt der 'Trick', damit deine Funktion komplett in der Lib eingesetzt werden könnte und die GoTurn()-Funktion ersetzt.
Mit dem Trick könnten dann nämlich alle geschriebenen Programm, die die 'Funktionen' Go() und Turn() nutzen, weiterhin funktionieren, und es braucht dann nur noch ein weiterer #define für Arc hinzukommen, der dann eben für deine Bogenfahrt benutzt wird.

--> Diese beiden Defines sind schon in der Lib und würden ersetzt.
#define Go(distance,speed) GoTurn(distance,0,speed)
#define Turn(degree,speed) GoTurn(0,degree,speed)

--> durch diese hier:
#define Go(distance,speed) kurve(distance,0,0,speed)
#define Turn(degree,speed) kurve(0,0,degree,speed)

--> und neu hinzu kommt:
#define Arc(radius,degree,speed) kurve(0,radius,degree,speed)


Wenn die hier gebaute Funktion also so gut wird, dass sie als Ersatz für die Lib taugt, dann solltest es den Lib-Benutzern leicht gemacht werden einfach umzusteigen.
Mit den #defines laufen jedenfalls alle alten Programme weiter und sie bekämen dann halt noch die Bogenfahrt über Arc() hinzu dazu.

Und als letztes I-Tüpfelchen wäre eine Änderung von kurve() in GoTurnArc() ein heißer Kandidat für die Lib.



Und dann wäre da noch meine Anfrage an mausi_mick.
So richtig folgen kann ich deiner Erklärung nicht.
Hmm, eine Bearbeitung von Tiks zum richtigen Zeitpunkt hatte ich ja schon oben bei https://www.roboternetz.de/phpBB2/viewtopic.php?p=393258#393258 als Vorschlag gegeben.
Dort wird unabhängig von einer Zeit für Msleep(), ja immer dann geregelt, wenn ein Tik aufgetreten ist.
Klar, zu Anfang ist der Unterschied zwischen beiden Seiten ja auf alle Fälle mit: 1 Tik hier und 0 Tik dort, ziemlich falsch. Aber genau deshalb hatte ich schon zu Anfang im Thread vorgeschlagen, dass die encoder-Werte eben nicht mit jeder Reglerbearbeitung wieder auf (0,0) gesetzt werden. Nach ein paar Tiks Fahrt wird das Verhältnis rechts/links ja auch bei einer Abweichung von nur einem Tik auf einer Seite ja nicht mehr so gravierend falsch.

Gruß Sternthaler

mausi_mick
29.08.2008, 07:14
hi Sternthaler,

ja ich glaub, wenn das mal soweit ist oder sein sollte, müsste man das so anpassen, dass es möglichst aufwärtskompatibel ist.
Aber - ich hab Probleme mit dem MY_ODO_... Werten -
Dein Windows-Programm krieg ich nicht zum Laufen (Der Rechner unter XP hängt sich auf) und ich hab dann mal die Werte über das Programm von Gruber /Hoffmann (Mehr Spass mit Asuro Band II S.23 -24) ermittelt.
Die Mittelwerte der Kurve liegen dann bei 600 bzw. 500.
Damit scheinen meine Programme besser zu gehen.
Hab aber Probleme mit den Encoder-Werten. Meiner Ansicht nach
sollte man die encoder[2] auf volatile unsigned long setzen.
(z.Zt. wohl in ASURO.h und Globals.c (müssen die eigentlich in beiden angegeben werden ?) als volatile definiert, da bekommt man bei 32xxx bereits einen Überlauf ( bei max speed und 8-Segmentscheibe bei ca 110 sec ) .
Sonst muss man wohl - in Abhängigkeit von der Fahrzeit und von der Drehzahl des Encoderrades und der Anzahl der s/w Segmente - öfters mal EncoderSet(0,0) aufrufen.

Gruss mausi_mick

Sternthaler
29.08.2008, 18:48
Hallo mausi_mick,

das ist aber sehr merkwürdig mit dem XP-Hänger. Ich hatte deshalb mal meinem Asuro mit in die Firma genommen und den dortigen PC auch mal mit dem Proggi 'versorgt'. Keine Probleme. Schade, dass es bei dir erst mal nicht läuft.
Kommt noch irgendeine Reaktion nach dem Start vom Programm? Oberfläche sichtbar? Schnittstelle noch wählbar? ...?

Ja, das mit der 2.fachen Angabe von Variablen ist sehr lästig. Und birgt auch das Risiko von unterschiedlichen Angaben.
In der Firma hatte ich vor ca. 100 Jahren mal folgendes eingeführt:
------
In asuro.h:
#ifdef MAIN
#define EXTERN
#else
#define EXTERN extern
#endif

EXTERN typ variable;
------

------
In dem Source mit der main()-Funktion: (bei uns i.d.R. test.c)
#define MAIN
#include "asuro.h"
------

------
In allen anderen Sourcen:
#include "asuro.h"
------

Da es nur einen Source mit MAIN gibt, wird dann in asuro.h bei
EXTERN typ variable;
ein
typ variable;

und alle anderen Sourcen machen dann in dem asuro.h bei
EXTERN typ variable;
ein
extern typ variable;

Alle sind glücklich, haben entweder die Variable definiert, oder als extern declariert, und ich als Programmierer muss die Variable nur genau einmal schreiben, an genau nur einer Stelle.


Ob man die Variable aber nun von signed auf unsigned, und dann noch long machen sollte, weiss ich nicht so recht. Das signed würde ich eher drin lassen, da man ja eventuell auch mal eine Rückwärtzfahrt berücksichtigen sollte/möchte.
Und bei 110 Sekunden mit 50 cm/s dann also 5500 cm = 55 m. Da passen sowiso keine Tiks mehr zu dem tatsächlich gefahrenen Weg. Sind ja viel zu viele Fehler unterwegs zusammengekommen. ?????

Schönes Wochenende
Gruß Sternthaler

mausi_mick
31.08.2008, 15:15
Hallo Sternthaler,

die long Werte hat ich mir eigentlich für so Spiralfahrten überlegt, wo mein
Sauroboter Robertina den Boden z.B. in Spiralen abfährt.

Habe mich etwas ernsthafter mit den Encoderwerten beschäftigt.
Da das Programm aus Asuro Band II recht hohe Maximal-Werte (600-850) ausgab, bin ich dann irgendwie/wann daraufgekommen, dass im Gegensatz zu Odometry/ie(data) die neuen Encoderfunktionen (EncoderInit(),IsrEnc, ...) mit eiem 8-bit ADC arbeiten. (in irgendwelchen Doku's hab ich nichts dazu gefunden, hab's dann an dem ADLAR beim ADMUX erkannt und daran, dass nur ADCH dem Encoder/tmp - Wert zugewiesen wird (in IsrEnc().
Hab dann ein eigenes Programm geschrieben, um an die 8-bittigen Werte meiner Encoder zu kommen. (Dein Win-Programm machte bei der Installation gar-nichts, nur hängte sich der Rechner auf. (Vielleicht liegt das aber daran, dass meine Systempartition nicht die C: , sondern seit einer dubiosen (fast Neu) Installation die E: Partition ist.) Auch verwende ich die Asuro-Bib 2,80 , da ich auch mit dem ATmega168 experimentiere.

Parallel dazu hab ich, da die Kurven doch sehr lichtempfindlich und auch geschwindigkeitsabhängig waren, die Hardware vom Asuro leicht modifiziert: Den R22 Widerstand (470 Ohm) - er befindet sich in der Nähe Pin 1-3 vom Atmega8 - hab ich entfernt bzw. den Draht durchgekniffen, auf der Rückkseite von der +5V Versorgung eine Schottky-Diode gelötet und an deren Kathode (Strich) einen Elko/Tantal gelötet. Von dem Pukt aus hab ich die Anoden der Encoder Leds D13/D14 mit je einem 349 Ohm Widerstand verbunden. Die Kathoden der Leds hab ich direkt an Masse angeschlossen (Verbindungsleiterbahn Kathode D12 nach Anode D13 hab ich unterbrochen (etwa da, wo auf dem Foto der Widerstand den schwarzen Kabelbinder "untertunnelt").
Mit der separaten Versorgung hab ich mehrere Vorteile:
- Betrieb der Backleds parallel zum Encoder möglich
- stabilere / störungsfreiere Versorgung der EncoderLeds (entkoppelt über Diode und Elko)
- freie Wahl der Ströme durch die Encoderdioden unabhängig von der Belastbarkeit des ATmega-Ports (bei hohen Diodenströmen schalten die FotoTransistoren T11/T12 besser durch (gegen 0V).
- Anpassungsmöglichkeit der Encoderkennlinie durch unterschiedliche Ströme durch entsprechende Widerstandswahl. (Hab ich (noch?) nicht gemacht, könnte aber vielleicht in sehr heller Umgebung was bringen).
Ich denke aber - einfacher und vielleicht auch besser wäre es, die Dioden in Reihe geschaltet zu lassen und nur den Widerstand nach + VCC (je nach Batteriezustand 5V-6V) so zu dimensionieren, dass ein höherer Strom fliesst ( bei mir z.Z. ca 2 x 12 mA : (5V - 2*1,1V) = 3,8V.
Ein Betrieb mit 20mA ist wohl sinnvoll (bei IRL80 max. 60mA möglich),
dann würde ich die Dioden aber in Reihe geschaltet lassen mit einem 154 Ohm Widerstand, besser noch mit einer Fet-Konstantstromquelle (z.B. FET BF245 oder besser BBS129 (Depletion Mode-Mosfet)), die ich auf 20 mA einstelle.

Mit diesen Hardwareänderungen und den neu ermittelten 8-Bit Parametern My_ODO... hab ich jetzt saubere Encoderwerte auch bei wechselnden Lichtverhältnissen (wenn gar nichts mehr geht, kann man auch die Encoder-Transistoren/Dioden gegen Fremdlicht kapseln oder gleich bessere Reflexlichtschranken (z.B. CNY70) einbauen).

Vielleicht komm ich auch nochmal dazu, das Programm von hai1991 zu testen/ändern, aber zumindest gehen bei mir jetzt die Go/Turn Funktionen.

Gruss mausi_mick

Sternthaler
01.09.2008, 00:49
Hallo Mausi_mick,

willkommen im Club der Odo-Geschädigten.
Ich gehöre da mehr oder weniger seit meinem ersten Kontakt mit dem Asuro dazu. Begonnen hatte es bei dem Thread von stochri Asuro ... ein kleiner Wettbewerb (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=10291), den er schon im Juni 2005 eingetragen hatte. Meine Antwort auf die Odometrieprobleme konnte ich dann immerhin schon 9 Monate später hinzufügen ;-). (Ist schon/erst auf Seite 3 vom Thread zu finden.)

Du solltest mal die Rechschreibüberprüfung einschalten bevor du auf absenden drückst:
... mein
Sauroboter Robertina ... Hier kann es sich doch bestimmt nur um einen Saug-Roboter handeln. Ich würde den eher im Quadrat, als in Spiralen saugen oder springen lassen. Ansonsten bring die Sau zum Metzger und schmeiß den Grill an. ;-)

Ja, ja, die 8- und 10-Bit-Ergebnisse in den einzelnen ADC-Messungen. Ist immer wieder ein irreführendes Thema.

Windoof-Installation auf E: ist ja seeeehhhhr ungewöhnlich.
Falls du Zeit, und noch Interesse an meinem Programm hast, gebe ich dir mal alle Teile aus dem Installer hier zum download an:
- cmctlde.dll (http://www.asuro-sternthaler.de/asuro/sensoren/cmctlde.dll) 112 kByte
- comctl32.ocx (http://www.asuro-sternthaler.de/asuro/sensoren/comctl32.ocx) 608 kByte
- dbgrdde.dll (http://www.asuro-sternthaler.de/asuro/sensoren/dbgrdde.dll) 35 kByte
- dbgrid32.ocx (http://www.asuro-sternthaler.de/asuro/sensoren/dbgrid32.ocx) 519 kByte
- mscomde.dll (http://www.asuro-sternthaler.de/asuro/sensoren/mscomde.dll) 13 kByte
- mscom32.ocx (http://www.asuro-sternthaler.de/asuro/sensoren/mscom32.ocx) 97 kByte
- MSVBVM50.dll (http://www.asuro-sternthaler.de/asuro/sensoren/MSVBVM50.dll) 1355 kByte
- VB5StKit.dll (http://www.asuro-sternthaler.de/asuro/sensoren/VB5StKit.dll) 29 kByte
- VB5DE.dll (http://www.asuro-sternthaler.de/asuro/sensoren/VB5DE.dll) 100 kByte
- StdOle2.tlb (http://www.asuro-sternthaler.de/asuro/sensoren/StdOle2.tlb) 18 kByte
- OleAut32.dll (http://www.asuro-sternthaler.de/asuro/sensoren/OleAut32.dll) 553 kByte
- OlePro32.dll (http://www.asuro-sternthaler.de/asuro/sensoren/OlePro32.dll) 83 kByte
- AsycFilt.dll (http://www.asuro-sternthaler.de/asuro/sensoren/AsycFilt.dll) 65 kByte
- Ctl3d32.dll (http://www.asuro-sternthaler.de/asuro/sensoren/Ctl3d32.dll) 27 kByte
- ComCat.dll (http://www.asuro-sternthaler.de/asuro/sensoren/ComCat.dll) 3 kByte
- Sensoren.exe (http://www.asuro-sternthaler.de/asuro/sensoren/Sensoren.exe) 100 kByte

Alles bis auf Sensoren.exe liegen bei mir unter C:\WINDOWS\SYSTEM32.
Ob das alles tatsächlich benötigt wird kann ich leider nicht sagen.
Falls du dir die Dateien holst, solltest du neuere Dateien auf deiner E:-Platte NICHT überschreiben. Sicher deine Original-Dateien auf alle Fälle bevor du dir dein System plättest. Wäre aber eine schöne Gelegenheit noch mal zu üben ein Windoof zu installieren ;-).
Sensoren.exe in ein beliebiges Verzeichnis und einfach starten. Daumen drück.


Deinen Umbau an der Odo-Beleuchtung habe ich mal im Schaltplan nachvollzogen. Die Idee ist nicht schlecht.
Deine Änderung ermöglicht ja nun tatsächlich die Benutzung beider Hardware-Teile (Brems-LED und Odo-Sensoren).
Natürlich habe ich da sofort etwas dran auszusetzen. (Ist bei mir so üblich, da ich das in der Firma unter anderem als Aufgabe habe. Also bitte keinesfalls übel nehmen. Meine Frau hat sich da auch nach vielen Jahren noch nicht so richtig dran gewöhnt ;-))
- Durch Software kann man Beides ohne Umbau erreichen. Allerdings leuchten die Brems-LEDs dann aber nie zu 100%.
- Du hast nun keine Möglichkeit mehr, auch an den ODO-Scheiben eine Messung ohne Beleuchtung zu machen und somit eine Differenzmessung zu erhalten (Beleuchtet - Unbeleuchtet). Ja, auch wenn es eigentlich unmöglich scheint, geht es doch auch ohne Umbau.
- Du bist ein Energieverschwender. Bau bitte zum Ausgleich sofort eine Solarzelle auf den Asuro. Und natürlich: Gehe nicht über Los und ziehe nicht 4000 Mark ein.

Ansonsten halte ich vor allem aber deine Idee eine Konstantstromquelle einzubauen für sehr erfolgversprechend. Genau hier vermute ich auch eine gute Möglichkeit das Umgebungslicht eventuell doch auszutricksen. Obwohl ich mir da nicht so sicher bin ob es funktionieren könnte. Je heller es wird, um so schlechter werden die Differenzen zwischen schwarzer und weißer Odofläche. Und wenn nun auch eine gute, konstante LED-Beleuchtung vorhanden ist, so scheint die Sonne immer noch dazu. Eine Abdeckung halte ich hier für sehr sinnvoll. (Ist bei mir 'natürlich' auch schon vorhanden. Pappe (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=169199#169199))

So, genug zum Umbau und zu Windoofprogrammen.

@hai1991
Kannst du dein jetziges Programm mal posten. Mal sehen, ob ich dann meine Trägheit überwinden kann und es auf meinem Asuro laufen lasse.

Eine schöne, fleißige Woche wünsche ich euch.
Gruß Sternthaler

mausi_mick
02.09.2008, 13:59
hallo hai1991,
hallo Sternthaler,

1. Win-Programm von Sternthaler für My_asuro.h

- Ich hab zwar die Oberfläche des Programm's mit den DLL's zum Laufen ?
gebracht, zumindest kann ich die schöne Oberfläche bewundern, aber auf die Tasten reagiert es nicht. Ist vielleicht doch ein Problem mit der Installation auf E:

2. Kurvenprogramm von hai1991

- das modifiz. Programm Kurven-Programm läuft bei mir jetzt stabil und relativ genau, man sollte aber mit der speed möglichst oberhalb von 170 bleiben, da sonnst das innere Rad zu langsam wird und das eher ein Rucken auf der Stelle wird.

Den (Winkel == 0) hab ich noch nicht realisiert (für geradeaus) ebenso fehlt noch der Teil mit (speed < 0).

Es verträgt jetzt auch recht hohe Winkel ( durch (int) begrenzt: 32... < w < 32... ) , ich habe bei mir encoder [] als unsigned long definiert, wobei das unsigned vielleicht doch etwas überflüssig ist, sodass man dortso leicht keinen Überlauf bekommt.

als Anhang noch mein Programmbeispiel (weder optimiert noch Schnittstelle an andere ASURO-Programme (Turn/Go/GoTurn...) angepasst)

Gruss
mausi_mick

mausi_mick
03.09.2008, 08:08
Hallo Sternthaler,

hab jetzt mal die Kurvenfunktion (links,rechts,vorwärts,rückwärts)
realisiert und den Aufruf in der Form
char GoTurnArc(int distance,int radius, int degree, int speed)
gebracht. Scheint zu funzen. (Bisher nur mit distance 0)

Hardwaremässig hab ich die beiden Encoder gegen Fremdlicht (von hinten und oben ) mit einem Plastikgehäuse ( PVC-Rechteckkrohr für Aufputz Kabelmontage) gekapselt. Von vorne werde ich noch testen, ob die Schwarzfärbung der Encoderscheibe/rades (natürlich von der Rückseite)
was bringt (werd sie wohl vorsichtshalber erstmal mit schwarzer Folie / Tesa bekleben).

Im Anhang der Code des GoTurnArc-Programms.

PS: Sorry betreff SauRoboter, er verhält sich aber zur Zeit so, hat auf den Encoderkurven jede Menge Peaks (von Motor/H-Brücke), die von 0 bis 255 gehen. Entstörung in Arbeit.
Gruss

mausi_mick

Sternthaler
04.09.2008, 02:51
Grüß dich mausi_mick,

da warst du ja echt fleißig.
Aufgefallen sind mir folgende Stellen:

- Keine Prüfung, ob Parameter "radius" negativ ist. Soll das gehen?
Zumindest wird ja nur mit "if (radius > 0)" wirklich weiter gemacht.

- Dann hier:
while (weg_s < weg_as) // Ist-Tiks < Soll-Tiks
{
zist = (int)(Gettime () - zista);

//Msleep (5); // 2 ??? 4 und 6 Problem kleiner Durchmesser
//Odometrie einlesen
if (degree > 0) // Rechtskurve: im Uhzeigersinn
{
MotorSpeed (speed_ac, speed_ic); // links = aussen , rechts = innen
count_an = encoder [0]; // links schneller als rechts
count_in = encoder [1];
count_ai = count_ai + count_an;
}
else
{
count_an = encoder [1]; // rechts schneller als links
count_in = encoder [0];
count_ai = count_ai + count_an;
}Hier müsste doch eigentlich auch ein MotorSpeed() in den else-Zweig, oder?

- Was bedeutet der Kommentar hinter dem auskommentierten Msleep (5)?
" //Msleep (5); // 2 ??? 4 und 6 Problem kleiner Durchmesser"

- Merkwürdig: Wenn "60Tik/U" bedeutet, dass pro Radumdrehung 60 ODO-Tiks erzeugt werden (Ich bin sicher, dass es dies bedeutet). Bei meinem Asuro sind es 80 Tiks pro Radumdrehung.

- Last and least
Warum unterscheidest du beim Sammeln der Daten in Variable dax[][] über "if (degree > 0)" in Rechts- bzw. Linkskurve?


Ansonsten macht mir das Ganze einen soliden Eindruck.
Die von mir aufgeführten Punkte sind ja ohne Auswirkung zum gewünschten Programmablauf.
Dass es aktuell 'etwas' lang und mit sehr vielen float-Berechnungen versehen ist, stört im Moment nicht so dolle. Optimierungspotential habe ich jedenfalls an einigen Stellen entdeckt. Aber wer weiß schon, ob es danach noch gehen würde ;-)?

Auch hier wieder: Es war noch nicht in meinem Asuro. Ich schaue nähhhhmlich gerade auf die Uhr.

Gruß Sternthaler
P.S.: Die Parameter, so wie ich vorgeschlagen hatte sind jedenfalls gut geeignet, um die Lib-Macros Go und Turn weiterhin erhalten zu können. Klasse!
Sauroboter haben immer die Angewohnheit zu quicken. Nicht peaken ;-)
Wermutstropfen: Deine Formatierung ist echt grottig.

mausi_mick
04.09.2008, 06:00
Hi Sternthaler,

Dank für Deine frühe Mühe,

Mit dem Radius hab ich mir das so vorgestellt:
- radius ==0 : erlaubt für Geradeausfahrt (noch nicht realisiert)
sonst:
- radius < halbe Spurweite: Abbruch mit Fehler 1 (err_fl).

Mit der Motorspeed hast Du wohl recht, wobei ich denke, dass ich die Zeile oben deaktivieren werde, da ich am Ende der Schleife MotorSpeed für beide Winkel anpasse. Hab wohl anfangs die MotorSpeed am Anfang der while Schleife für +-Winkel anpassen wollen , hat aber irgendwie (ich weiss echt nicht warum) nicht geklappt und hab dann die Zeilen nach unten kopiert und wohl oben nur eine gelöscht. Muss das aber testen, ob's dann auch noch funktioniert.
Mit den auskommentierten Msleep - Werten : waren alles Tests ,
fährt aber z.Z. ohne Msleep.
Auch noch unsauber ist die Abbruchbedingung, da die letzten counts wohl noch gemacht werden, auch wenn die Ist-Wegstrecke über der Sollstrecke ist. (Fährt dann immer etwas zu weit.)
Mit den 60 Tiks : Ich hab eine Encoderscheibe mit 6 schwarzen und 6 weissen Segmenten, also 12 s-w-Wechseln , macht 12 Tiks pro Encoderrad. Die Über/Untersetzung zum Laufrad beträgt 5 . Ergibt 5* 12 = 60 Tiks pro Laufradumdrehung. Du hast vermutlich eine Encoderscheibe mit 2 * 8 Segmenten .
Das Sammeln der DAX-Werte (hat vermutlich nicht direkt was mit dem Index zu tun) für links und rechts separat ist eigentlich nicht nötig, ich wollte nur in dax[0] die Daten des linken Motors und in [1] die des rechten.
Der Code ist wohl echt etwas kotig, zuviele Casts und zum Teil zu genau (float/double), auch wenig ++. Da sollte man (nicht umbedingt ich ) was tun, wenn die Sache sauber läuft.

Muss mir mal gleich Deine Formatierung ansehen.

Ok, hab mal Deine anders formatierte Version genommen und obige MotorSpeed-Zeile entfernt und die DAX-Tab-Füllung etwas modifiziert.

Erste Tests ok, meist fährt ASURO etwas zu weit / lang,
auch Probleme mit kleiner Speed (z.B. 170) und engen Kurven, da dann das Innenrad je nach Schmierung etc. eventuell steht.

Im Anhang noch der neuste Code

Gruß

mausi_mick

mausi_mick
04.09.2008, 15:06
Hi Sternthaler,

hab nochmal ein paar Sachen geändert und auch für Geradeausfahrt
(distance > 0, radius =0) getestet, wobei mein Asuro vorwärts recht gut die Richtung hält, rückwärts zieht er nach rechts (ein Kreis mit ca 2 m Durchmesser).

Gruss
mausi_mick

hai1991
04.09.2008, 18:18
hallo ihr beiden

wie ich sehe seid ihr fleißig am experimentieren, optimieren, programmieren,...

ich hatte leider in den letzten tagen nicht so viel zeit (z.T. auch wegen dem schönen wetter)

vl. kann ich mich aber trotzdem wieder einmal dazu überwinden auch etwas herum zu tüftlen

@sternthaler
du hattest doch mal nach meinem aktuellen code gefragt: ich glaube es müsst der letzte sein den ich gepostet habe (falls du ihn auch mal probieren willst)


am 4.9.08 um 18:46
kleine frage am rande:
müssen bei GoTurnArc() oder wie auch immer man sie nennt unbedingt 4 parameter übergeben werden?
würden nicht 3 genügen?
- length (wird als radius oder distance verwendet. je nach dem ob degree=0 oder nicht)
- degree
- speed

auswahl des jeweileigen typs:
-length=0: auf dem stand drehen (entspricht dem früheren Turn())
-degree=0: gerade strecke fahren (entspricht dem früheren Go())
-keins der beiden =0: bogen fahren (entspricht Kurve())


oder wäre es eurer meinung nach besser alle 4 zu verwenden, um die doppelte verwendung von length als radius und distance zu umgehen?

ich werde auf jeden fall in nächster zeit einmal versuchen meine idee als programm zu verwirklichen. dann kann man noch immer entscheiden was besser ist

trotzdem bedanke ich mich bei euch schon mal für die (hoffentlich) kommenden rückmeldungen


[edit] am 5.9.08 um 10:05
wie angekündigt habe ich jetzt meine version fertig gestellt
ich hoffe ihr könnt etwas damit anfangen

hier einmal mein code:
um für mich das zusammensetzten leichter zu machen habe ich erstmal viel gleichbedeutende alte und neue variablen nur mit defines ersetzt. später kann man das natürlich im code ersetzten, um das lesen zu erleichtern


#include <asuro.h>
#include <myasuro.h>


//defines zur kurvenfahrt
#define BREITE 103 //spurbreite in mm
#define PI 3.141592

//defines, um alte variablennamern weiterverwenden zu können
#define distance length
#define radius length
#define winkel degree

#define enc_count count_a_soll
#define tot_count count_a
#define l_speed speed_a
#define r_speed speed_i

#define GO 1
#define TURN 2
#define ARC 3

void GoTurnArc (
int length,
int degree,
int speed)
{
StatusLED(RED);
unsigned long enc_count;
int count_a=0,count_i=0;
int diff = 0;
int speed_a=speed, speed_i=speed;
int radius_a, radius_i;
float quot, teiler;
long tik_summe;

int typ; //speichert den typ der gefahrenen strecke

/* stop the motors until the direction is set */
MotorSpeed (0, 0);

/* Go */
if (distance != 0 && degree == 0)
{
typ=GO;
/* calculate tics from mm */
enc_count = abs (distance) * 10000L;
enc_count /= MY_GO_ENC_COUNT_VALUE;

if (distance < 0)
MotorDir (RWD, RWD);
else
MotorDir (FWD, FWD);
}
/* Turn */
else if (distance == 0 && degree != 0)
{
typ=TURN;
/* calculate tics from degree */
enc_count = abs (degree) * MY_TURN_ENC_COUNT_VALUE;
enc_count /= 360L;

if (degree < 0)
MotorDir (RWD, FWD);
else
MotorDir (FWD, RWD);
}
/* Arc */
else if (distance != 0 && degree != 0)
{
typ=ARC;
/* calculate tics from distance and degree */
radius_a=radius+BREITE/2;
radius_i=radius-BREITE/2;

teiler=(float)360/abs(winkel); //Bruchteil des Kreises
quot=((float)radius_a)/((float)radius_i);


//berechnen der notwendigen tics am außen- und innenrad
count_a_soll=2*radius_a*(PI*10000L/teiler);
count_a_soll/=MY_GO_ENC_COUNT_VALUE;
}


/* reset encoder */
EncoderSet (0, 0);

/* now start the machine */
if(typ!=ARC)
MotorSpeed (l_speed, r_speed);
else
{
//mindestgeschwindigkeit=70
if(speed<70) speed=70;

//anfangsgeschwindigkeiten berechnen
speed_a=speed;
speed_i=speed_a/quot;
//speed_i=speed;

//Motoren starten
if(winkel>0)
MotorSpeed(speed_i,speed_a); //im Gegenuhrzeigersinn
else
MotorSpeed(speed_a,speed_i); //im Uhrzeigersinn
}

while (tot_count < enc_count)
{
if(typ!=ARC)
{
tot_count += encoder [LEFT];
diff = encoder [LEFT] - encoder [RIGHT];
/* reset encoder */
EncoderSet (0, 0);
}
else
{
//einen Tik abwarten
tik_summe = encoder [LEFT] + encoder [RIGHT];
while (tik_summe == encoder [LEFT] + encoder [RIGHT]);

//Odometrie einlesen
if(winkel>0)
{
count_a=encoder[RIGHT];
count_i=encoder[LEFT];
}
else
{
count_a=encoder[LEFT];
count_i=encoder[RIGHT];
}

diff=count_a-(count_i*quot);
if(winkel > 0) diff*=-1;
}

if (diff > 0)
{ /* Left faster than right */
if ((l_speed > speed) || (r_speed > 244))
l_speed -= 10;
else
r_speed += 10;
}

if (diff < 0)
{ /* Right faster than left */
if ((r_speed > speed) || (l_speed > 244))
r_speed -= 10;
else
l_speed += 10;
}


if(typ!=ARC) MotorSpeed (l_speed, r_speed);
else
{
if(winkel>0)
MotorSpeed(speed_i,speed_a);
else
MotorSpeed(speed_a,speed_i);
}
Msleep (1);
}
MotorDir (BREAK, BREAK);
Msleep (200);
}


zur zeit funktionierten leider nur Go und Turn (also entweder distance oder degree =0). Kurve hat bei meinen probefahrten noch nicht funktioniet.
vl findet ihr einen fehler
[edit]

mausi_mick
06.09.2008, 08:40
Hallo Sternthaler,
Halllo hai1991

mit den Übergabeparametern hab ich auch so meine Probleme,
ist ein wenig überbestimmt und man sollte daher einige Kombinationen
im Programm abfangen.

Hab dann noch ein wenig getestet, hatte aber immer Probleme mit der Sollvorgabe für die Geschwindigkeit und den unterschiedlichen Motor-Daten (mein rechter Motor ist deutlich langsamer.)
Hab dann einen zulässigen Korridor für die Geschwindigkeit um die Geschwindigkeitsvorgabe definiert (maxi,mini für innres Rad, maxa, mina für äusseres Rad) und zusätzlich einen Korrekturwert für den rechten Motor definiert für vorwärts + 5 und für rückwärts + 25 (speed_korr)
.
Die Werte hab ich vorher für Geschwindigkeit ab 210 ermittelt.

Hab auch anstelle der encoder[] eine eigene 8-Bit Odometr-Funktion verwandt (vermutlich nicht notwendig), hat den Vorteil, dass ich die
MY-ODO-Daten nicht ständig ändern un die Bib neue "maken" muss, sondern verwende im Programm die Schwellwerte tlp,tlm,trp,trm .

Damit kommt das neue Programm ganz gut zurecht, zumindest, wenn die Räder vernünftig drehen ( geölt, keine Haare / Staub an den Achsen, möglichst frische Akku's / Batterien, speed > 170).

Im Anhang noch der Code


mausi_mick


PS: Bin ab heute/morgen im Urlaub

Sternthaler
06.09.2008, 11:49
Guten Morgen hai1991 und mausi_mick.

Hier nur mal kurz auf die schnelle.

@hai1991
ARC dürfte nicht funktionieren, da du die beiden Variablen für " while (tot_count < enc_count)" nicht berechnest bzw. bei neuen Tiks neu ermittelst. Hab ich was übersehen?
Ansonsten finde ich deinen Code gut getrennt durch die 3 Fahrt-Varianten.

@mausi_mick
Hey, die Formatierung ist besser ;-). Wie steht in deinem Editor die TAB-weite? Bei 4 bekommt der Code ein fast homogenes aussehen. Ich stelle in meinem Editor immer ein, dass die geschriebenen TAB's in Leerzeichen gewandelt werden. Dann ist der Code grundsätzlich auch für andere identisch.
Inhaltlich habe ich jetzt noch nicht intensiv geschaut.
Faulpelz. Die Lib nicht übersetzen zu wollen, wo gibt es denn so was?
Du kannst die 4 Variablen tlp,tlm,trp,trm komplett sparen. Du kannst sie auch als #define anlegen, da die Inhalte sich nie ändern, und der Wert selber auch nur durch Defines bestimmt werden.
#define TLP TRIGLEV_L + HYST_L
Nun aber erst einmal einen schönen Urlaub.

Gruß Sternthaler

mare_crisium
06.09.2008, 14:09
Hi, Jungs (SternThaler, mausi_mick und hai1991)

Ihr kommt ja gut voran! Im Anhang habe ich den Vorschlag, die Motoren zu regeln, um mausi_micks faulem rechten Motor die Flausen auszutreiben ;-) . Ich hoffe, mein Vorschlag trägt dazu bei, besser die Kurve zu kratzen.

Ciao,

mare_crisium

hai1991
06.09.2008, 17:35
hallo allerseits

@sternthaler
wenn ich deine vermutung richtig verstehe muss ich dich leider entteuschen. ganz oben habe ich die variablen mit defines gleichgesetzt


#define enc_count count_a_soll
#define tot_count count_a

dadurch musste ich erstmal nicht alles umändern, sondern konnte es so übernehmen wie es ist.
falls du etwas anderes gemeint hast, bitte ich dich, es etwas genauer zu beschreiben

@mare_crisium
ich habe deine datei schnell überflogen und muss sagen, dass es nicht schlecht aussieht. jedoch bin ich mir nicht sicher, ob es für den asuro schon eine fertige funktion für die berechnung der drehzahl gibt. das muss ich erst mit hilfer der suchfunktion heraus finden.

mausi_mick
06.09.2008, 18:01
hallo ihr Kurver,

vermutlich liegt mare_crisium gar nicht so daneben, werd mir vielleicht im
Urlaub Gedanken dazu machen ... wenn der Krimi zu öde ist.


Gruss
mausi_mick

Sternthaler
06.09.2008, 18:46
Hallo hai1991
Oh Mist, da gebe ich mausi_mick den Tipp seine Variablen durch Defines zu ersetzen, und die von dir gemachten Defines habe ich übersehen.
Ja, dein Hinweis löst genau das was ich übersehen hatte.

Grüß dich mare_crisium,
was machst du bei den Asurianern ;-)? Hast du nun auch einen?
Und wie immer ein guter Vorschlag von dir. (Ist ja ein echter Regler)
Ähm, in deinem Text schreibst du, dass hier aktuell nicht geregelt würde.
- while((difl < 10) && (difr < 10))
- {
--- OdometrData(dalr);
--- Auswerten der beiden ODO-Werte aus dalr[2] und ermitteln einer
--- Geschwindigkeitsänderung
--- ...
Das ist doch auch ein Regler? (Vorgabe / Messwerte / Abweichung -> Ergibt neue Stellwerte)
Und ein schuldbewustes: Ja, Ja, ich sollte eigentlich X, Y und Omega berechnen ;-).

Und noch mal etwas zu hai1991.
Deine Suche nach einem Regler für den Asuro wird dich unweigerlich zu wastes linienverfolgendem PID-Regler führen.
Genau den habe ich schon seit vielen, vielen Äonen zum Kurven-/Geradefahren genutzt.
Ein paar experimentelle Anpassungen an den Reglerparametern (wie mare_crisium es Dummys wie mir, bei solchen Dingen empfiehlt). Ein weiterer kleiner Umbau darin erlaubt es auch noch, dass man nicht auf das Ende der Fahrt warten muss solange das Hauptprogramm das Ding regelmäßig alle 2ms aufruft.
Dazu aber nur den Codeausschnitt vom Regler. Schließlich geht es hier um deinen Ansatz.

/************************************************** ***************************
FUNKTION: MotorPID
Aufgabe: Funktion zur Reglung der Motoren.
Diese Funktion bzw. die eigentliche Berechnung fuer die
Reglung wurde im Forum unter www.roboternetz.de von waste
entwickelt.
Von Sternthaler ist die Moeglichkeit hinzugefuegt, die
Reglerberechnung fuer unterschiedliche Regelaufgaben zu
nutzen.
Die Parameter steuern, welche Sensoren zur Reglung benutzt
werden sollen. Zum einen koennen es die Liniensensoren sein
um eine Linienverfolgung zu realisieren, zum anderen kann
der Regler zur Ueberwachung der Raddecoder genutzt werden.
Parameter:
************************************************** ***************************/
unsigned char MotorPID (
unsigned char regler,
char speed,
int links,
int rechts)
{
int LWert = 0, RWert = 0;
int absLinks = 0, absRechts = 0;
float faktor;
static int x, x1, x2, x3, x4;
static int xalt, drest, isum;
int kp = 0, kd = 0, ki = 0;
int yp, yd, yi, y, y2;
int LSpeed, RSpeed;
unsigned char LDir, RDir;
unsigned char use_regler = TRUE;

switch (regler)
{
case PID_LINIE:
links = rechts = 1; // erzwingt vorwaertsfahrt
LineData (); // Liniensensoren
LWert = sens.linie [LINKS_DUNKEL] - sens.linie [RECHTS_DUNKEL];
RWert = sens.linie [LINKS_HELL] - sens.linie [RECHTS_HELL];
/* DIESE PARAMETER WURDEN VON waste IM FORUM UNTER
https://www.roboternetz.de
ENTWICKELT.
*/
kp = 5; // Parameter kd enthält bereits Division durch dt
ki = 5;
kd = 70;
break;
case PID_ODOMETRIE:
if (links == 0 || rechts == 0)
use_regler = FALSE;
else
{
absLinks = abs (links);
absRechts = abs (rechts);
/* Odometrie-Zaehler so justieren, dass fuer eine Kurvenfahrt
die Tic-Anzahl auf beiden Seiten identisch aussehen.
Die Seite auf der weniger Tic's zu fahren sind wird auf die
hoehere Anzahl 'hochgerechnet'.
*/
if (absLinks < absRechts)
{
faktor = (float)absRechts / (float)absLinks;
LWert = sens.rad_tik [LINKS] * faktor;
RWert = sens.rad_tik [RECHTS];
}
else
{
faktor = (float)absLinks / (float)absRechts;
LWert = sens.rad_tik [LINKS];
RWert = sens.rad_tik [RECHTS] * faktor;
}
kp = 65;
ki = 5;
kd = 90;
}
break;
}

LSpeed = (int)(speed - HW_MOTOR_DIFF / 2); //Wunschgeschwindigkeit vorgeben
RSpeed = (int)(speed + HW_MOTOR_DIFF / 2); //Hardware beruecksichtigen

if (use_regler == TRUE)
{
/* AB HIER IST DIE BERECHNUNG VON waste IM FORUM UNTER
https://www.roboternetz.de
ENTWICKELT WORDEN.
*/
x1 = RWert - LWert; // Regelabweichung

x = (x1 + x2 + x3 + x4) / 4; // Filtert die 4 letzten Werte
x4 = x3; x3 = x2; x2 = x1; // Pipe ueber die letzten 4 Werte

isum += x; // I-Anteil berechnen
if (isum > 16000) isum = 16000; // Begrenzung: Überlauf vermeiden
if (isum < -16000) isum = -16000;
yi = isum / 625 * ki;

yd = (x - xalt) * kd; // D-Anteil berechnen und mit nicht
yd += drest; // berücksichtigtem Rest addieren
if (yd > 255) drest = yd - 255; // Eventuellen D-Rest merken
else if (yd < -255) drest = yd + 255;
else drest = 0;

yp = x * kp; // P-Anteil berechnen

y = yp + yi + yd; // Gesamtkorrektur
y2 = y / 2; // Aufteilung auf beide Motoren
xalt = x; // x merken

if (y > 0) // Abweichung nach rechts
{
LSpeed += y2; // links beschleunigen
if (LSpeed > 255) // wenn Wertebereich ueberschritten
{
y2 += (LSpeed - 255); // dann Rest rechts berücksichtigen
LSpeed = 255; // und Begrenzen
}
RSpeed -= y2; // rechts abbremsen
if (RSpeed < 0) // Auch hier Wertebereich
{
RSpeed = 0; // beruecksichtigen
}
}
if (y < 0) // Abweichung nach links
{
RSpeed -= y2; // rechts beschleunigen
if (RSpeed > 255) // wenn Wertebereich ueberschritten
{
y2 -= (RSpeed - 255); // dann Rest links berücksichtigen
RSpeed = 255; // und Begrenzen
}
LSpeed += y2; // links abbremsen
if (LSpeed < 0) // Auch hier Wertebereich
{
LSpeed = 0; // beruecksichtigen
}
}
}

if (links >0) LDir = FWD; else if (links <0) LDir = RWD; else LDir = BREAK;
if (rechts>0) RDir = FWD; else if (rechts<0) RDir = RWD; else RDir = BREAK;

if (LSpeed < 20) LDir = BREAK; // richtig bremsen
if (RSpeed < 20) RDir = BREAK;
MotorDir ( LDir, RDir);
MotorSpeed (abs (LSpeed), abs (RSpeed));

return 0;
}
Diese Funktion muss alle 2ms vom Hauptprogramm aus aufgerufen werden, da waste damals diesen Zeitfaktor in seinen Berechnungen zur Reglerdimensionierung angesetzt hatte.
Oder innerhalb der Funktion wird ein while() mit Msleep(2) eingebaut.
Die struct-Variable sens enthält die Messwerte der Sensoren, die per Interrupt immer aktuelle Werte enthalten. Sie 'verbrauchen' innerhalb der Funktion keine Rechenzeit.

Ein Aufruf erfolgt mit Tik-Angaben bei den Parametern links und rechts. Eine Umrechnung von Strecke bzw. Winkel und Radius und Vorwärts/Rückwärts muss vorher erfolgen.

Tut mir leid, wenn ich euch das bis jetzt verschwiegen habe. Aber dein Ansatz hai1991 soll ja nicht durch 'Fertigfutter' beeinflusst werden fand ich.

@mausi_mick
Dann lass den Krimi doch zu Hause ;-)

Gruß Sternthaler

mare_crisium
07.09.2008, 09:23
Guten Morgen, alle zusammen,

gut, wenn der Asuro die Regelfunktion schon eingebaut hat. Auf meine Idee bin ich auch nur deshalb gekommen, weil das Rad an mausi_micks Asuro ohne Sonderbehandlung die Sollgeschwindigkeit nicht erreicht. Er könnte das Problem also beheben, indem er den Regler „schärfer“ einstellt. Ich versuche gerade mich durch den Abschnitt des c-Codes durchzubeissen, um zu verstehen, wie das gehen könnte.

@SternTahler
nee, einen Asuro habe ich nicht. An meinem Asuro-ähnlichen Eigenbau bin ich noch am Basteln. Ich will Euch auch kein x für ein y oder Omega vormachen. - Es führen viele Wege nach Roma, ganz besonder für Asuros :-) .

Ciao,

mare_crisium

Sternthaler
08.09.2008, 00:43
Auch einen guten Morgen an alle. (Ja meine Zeiten sind etwas ver-rückt)

Speziell an mare_crisium
Ich glaube, ich muss mein letztes unverständliches Gebrabbel erst einmal sortieren. Nicht dass wir aneinander vorbei reden.
- Der Asuro und auch die Lib haben keinen Regler implementiert.
- Der von waste entwickelte Regler ist 'standalone' zur Linienverfolgung entwickelt worden. (wastes Regler (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=11818) 38970 Ansichten!!!)
- Das Codeschnipsel oben von mir nutzt die Mathematik von waste. Ich habe ihn nur für meine Belange so umgebaut, dass er auch für beliebige Fahrstrecken als Regler genutzt werden kann.
Und weil der Begriff Regler hier nun auftauchte, habe ich ihn hier als Muster ins Rennen geworfen.

Auf alle Fälle sollten mausi_mick und hai1991 sich deinen Pseudo-Code ansehen. Der von dir vorgeschlagene Zweipunkt-Regler ist ja auch ohne Studium, im Gegensatz zu einem ausgewachsenen PID-Regler, auch noch verständlich.

Somit bleibt erst einmal nur noch eine Navigationsplanung nach Rom zu machen ;-). Ist bestimmt ein gutes Ziel. Und das sollte man immer haben.

Gruß Sternthaler

P.S.: @mare_crisium
Hast du zu deinem Roboter hier im Forum(-Romanum) einen Thread bei den vorgestellten Eigenbauten?

hai1991
10.09.2008, 22:23
hallo zusammen

gleich vorweg:
noch mal ein thx an mare_crisium für die bescheibung eines brauchbaren reglers, aber sollte es nicht auch funktionieren, wenn ich das verhältnis der gefahenen wege bilde und dann dementsprechend die geschwindigkeiten änder? vorausgesetzt man wählt seine mindestgeschwindigkeit dementspechend
somit brauche ich nicht erst die drehzahl ermittel und auf diese reagieren (das spart vl etwas speicherplatz und zeit, wobei ich nicht weiß wie relevant das in diesem fall ist)

warum ich aber eigentlich schreibe:
wie oben schon berichtet hatte ich ein problem mit der integrierung der Arc-funktion in GoTurn.
durch experimentieren und mehrmaligem durchschauen des codes ist mir aufgefallen, dass ich "nur" ein MotorDir im Arc-Teil vergessen hatte, dadurch war er noch immer auf BREAK.

hier also der funktionierende code:


#include <asuro.h>
#include <myasuro.h>


//defines zur kurvenfahrt
#define BREITE 103 //spurbreite in mm
#define PI 3.141592

//defines, um alte variablennamern weiterverwenden zu können
#define distance length
#define radius length
#define winkel degree

#define enc_count count_a_soll
#define tot_count count_a
#define l_speed speed_a
#define r_speed speed_i

#define GO 1
#define TURN 2
#define ARC 3

void GoTurnArc (
int length,
int degree,
int speed)
{
StatusLED(RED);
unsigned long enc_count;
int count_a=0,count_i=0;
int diff = 0;
int speed_a=speed, speed_i=speed;
int radius_a, radius_i;
float quot, teiler;
long tik_summe;

int typ; //speichert den typ der gefahrenen strecke

/* stop the motors until the direction is set */
MotorSpeed (0, 0);

/* Go */
if (distance != 0 && degree == 0)
{
typ=GO;
/* calculate tics from mm */
enc_count = abs (distance) * 10000L;
enc_count /= MY_GO_ENC_COUNT_VALUE;

if (distance < 0)
MotorDir (RWD, RWD);
else
MotorDir (FWD, FWD);
}
/* Turn */
else if (distance == 0 && degree != 0)
{
typ=TURN;
/* calculate tics from degree */
enc_count = abs (degree) * MY_TURN_ENC_COUNT_VALUE;
enc_count /= 360L;

if (degree < 0)
MotorDir (RWD, FWD);
else
MotorDir (FWD, RWD);
}
/* Arc */
else if (distance != 0 && degree != 0)
{
typ=ARC;
/* calculate tics from distance and degree */
radius_a=radius+BREITE/2;
radius_i=radius-BREITE/2;

teiler=(float)360/abs(winkel); //Bruchteil des Kreises
quot=((float)radius_a)/((float)radius_i);


//berechnen der notwendigen tics am außen- und innenrad
count_a_soll=2*radius_a*(PI*10000L/teiler);
count_a_soll/=MY_GO_ENC_COUNT_VALUE;

MotorDir(FWD,FWD);
}




/* now start the machine */
if(typ!=ARC)
MotorSpeed (l_speed, r_speed);
else
{
//mindestgeschwindigkeit=70
if(speed<70) speed=70;

//anfangsgeschwindigkeiten berechnen
speed_a=speed;
speed_i=speed_a/quot;
//speed_i=speed;

//Motoren starten
if(winkel>0)
MotorSpeed(speed_i,speed_a); //im Gegenuhrzeigersinn
else
MotorSpeed(speed_a,speed_i); //im Uhrzeigersinn
}

/* reset encoder */
EncoderSet (0,0);

while (tot_count < enc_count)
{
if(typ!=ARC)
{
tot_count += encoder [LEFT];
diff = encoder [LEFT] - encoder [RIGHT];
/* reset encoder */
EncoderSet (0, 0);
}
else
{
//einen Tik abwarten
tik_summe = encoder [LEFT] + encoder [RIGHT];
while (tik_summe == encoder [LEFT] + encoder [RIGHT]);


//Odometrie einlesen
if(winkel>0)
{
count_a=encoder[RIGHT];
count_i=encoder[LEFT];
}
else
{
count_a=encoder[LEFT];
count_i=encoder[RIGHT];
}

diff=count_a-(count_i*quot);
if(winkel > 0) diff*=-1;
}

if (diff > 0)
{ /* Left faster than right */
if ((l_speed > speed) || (r_speed > 244))
l_speed -= 10;
else
r_speed += 10;
}

if (diff < 0)
{ /* Right faster than left */
if ((r_speed > speed) || (l_speed > 244))
r_speed -= 10;
else
l_speed += 10;
}


if(typ!=ARC) MotorSpeed (l_speed, r_speed);
else
{
if(winkel>0)
MotorSpeed(speed_i,speed_a);
else
MotorSpeed(speed_a,speed_i);
}
Msleep (1);
}
MotorDir (BREAK, BREAK);
Msleep (200);
}




der code ist zwar noch etwas verbesserungsfähig, aber es funktioniert endlich


was mir beim ausprobieren noch aufgefallen ist:
die gemessene strecke ist derziet noch recht stark von der beleuchtung abhängig. so fährt er zb im schatten relativ genau seinen vorgegebenen winkel, jedoch bei zimmerbeleuchtung (energiesparlampe) fehlen immer einige grade. da muss ich wohl noch eine abschirmung der odometriesensoren basteln


wenn noch jemand irgendwelche verbesserungsvorschläge hat bitte bescheidsagen

mare_crisium
13.09.2008, 00:01
Guten Abend, zusammen!

@SternThaler,
tscha, mein Eigenbau geht sehr langsam voran. Ausserdem wird's nicht mehr als das, was die Amerikaner ein "vanilla three wheeled robot vehicle" nennen würden. Deswegen einen eigenen Thread vom Zaun zu brechen, lohnt sich IMHO nicht.

@hai1991,
gut, dass Du den wesentlichen Fehler beseitigen konntest. - Ob Du auf Dauer ohne Regler auskommen wirst, bezweifle ich: Steuerungen sind nun einmal starr und wenn das Wollknäuel an der Asuroachse erstmal dick genug ist (oder sich was anderes ändert), wird Dein Asuro nicht mit dem gewünschten Radius um die Kurve fahren. - Estmal ist es aber wichtiger, dass er's jetzt besser tut als vorher, und Du Dein hart verdientes Erfolgserlebnis geniesst :-) !

Ciao,

mare_crisium

mausi_mick
05.10.2008, 14:45
Hallo,

hab's im Urlaub - bezüglich Kurven - nicht so geregelt bekommen, wie ich es mir vorgestellt hatte, hab aber gestern mit dem Vorschlag von mare_crisium - in leicht modifizierter Form - experimentiert.

Hatte mir im Urlaub ? wohl überlegt, dass das mit dem speed=PWM-Wert zur Regelung eigentlich nicht so doll ist.
Eigentlich will ich dem ASURO doch sagen : Fahr mit 30 mm/s geradeaus
oder mit 150mm/s rechts und 40mm/s links in eine Kurve.
Als Eingabewerte hab ich daher erst mal nur zwei Parameter zugelassen: die Distanz und dann die Geschwindigkeiten links/rechts in mm / s.
(Man kann das wohl auch wieder umsetzen in eine mittlere Kurvengeschwindigkeit in mm/s und einem Kurvenradius, ich hab es aber z.Zt. so nicht realisiert.)
Der wesentliche Unterschied ist also, dass ich die Geschwindigkeit in mm/s
vorgebe und nicht einen PWM-Wert zwischen 0? und 255 für die ? Geschwindigkeit.
Als Obergrenze hab ich 600 mm/s festgelegt (Geschwindigkeit meines ASURO für MotorSpeed(255,255)), als Untergrenze 10 mm / s.

Funktioniert relativ gut für hohe und mittlere Geschwindigkeiten,
oder Kurvenfahrten, wo ich z.B. mit v_links = 10mm/s und v_rechts = 300 mm/s reingehe, funktioniert schlecht bei kleiner Geschwindigkeit von z.B. 10 mm/s auf beiden Rädern. Hab dazu zwar den Anfangsstellwert und auch die Messzeit angepasst, ist aber wohl zu langsam.
Ich werde versuchen, hardwaremässig die Encoderscheibe direkt auf die
Ritzel zu kleben (und die ReflexLS entsprechend umzubauen), da ich dort 5 x mehr TIKs bekomme. Melde mich dann mal wieder, falls ich damit Erfolg habe.

Das Programm ist noch in der Testphase und vermutlich noch recht fehlerhaft, ich kann es bei Bedarf aber posten


Gruss
mausi_mick

mausi_mick
06.10.2008, 11:49
Hallo Asuro-Kurver,

hab die Übergabeparameter geändert:

GoTurn(Circle)(long distance, int speed_mms,int radius)
mit
distance in mm

speed_mms für mittlere (links/rechts) Geschwindigkeit in mm/s

speed < 0: rückwärts, speed > 0 vorwärts
Absolutwert zwischen 10 und 600 zulässig, funktioniert ab etwa 80

radius in mm

radius < 0 : Linkskurve, radius > 0 Rechtskurve, radius == 0 geradeaus
ist radius ungleich 0, sollte er groesser halbe Spurweite 52mm sein

Bin noch beim Hardware-Umbau (Encoderscheibe an Ritzel und CNY70 als
Reflexsensor)

Gruss

mausi_mick

mausi_mick
10.10.2008, 08:45
Hallo Asuro-Kurver,

hab die Encoder direkt am Motorritzel angebracht,
als Reflexsensor verwende ich CNY70. Aus Platzgründen hab ich die CNY70
"oberflächen" montiert auf einem dünnen (ca 0,5mm ) Pertinaxplättchen.
Die MY_ASURO_ .. Werte liegen bei etwa 220 +-10. Um Beeinträchtigung von den Originalsensoren zu verhindern, hab ich die ursprünglichen LED's von der Versorgung abgetrennt.

Die Regelung scheint wohl besser zu funktionieren ( ich bekomme jetzt ca 3,33 x soviele TIKs ( 5 fache Zahnradübersetzung , aber nur 2x4 Segmente auf Encoderscheibe anstelle 2x6) pro Zeiteinheit)).

Nur klappt bei mir die Entfernungssteuerung (noch ?) nicht, obwohl ich die
Fahrwegberechnung auch angepasst habe ( 0,58 mm/Tik gegenüber ca 1,9 mm/Tik bisher), Asuro fährt ca 2 x soweit wie berechnet/vorgegeben.

Gruss

mausi_mick

oberallgeier
10.10.2008, 09:59
Hei, mausi_mick, wie gut! Aber wie hast Du dieses Scheibchen aufs Ritzel bekommen? Ich wollte schon immer mal meine Gabellichtschranke an den Motor/die Motorwelle bauen - aber dann müsste ich das Ritzel ganz reinschieben. Dabei fürchte ich, dass der Zahneingriff nicht mehr ok ist. Hast Du die Scheibe ans Ritzel geklebt? Womit? Ich dachte, das sei HDPE - und das lässt sich nach meinem Wissen garnicht wirklich kleben, nur schweißen.

mausi_mick
10.10.2008, 10:34
hi oberallgeier,

war natürlich gelogen oder vereinfacht dargestellt - ich hatte zufällig , ich glaube von OPITEK - ein
Doppelzahnrad mit 10 / 50 Zähnen, hab dann von dem grossen die 50 Zähne abgesägt / feilt und das kleine Zahnrad (mit den 10 Zähnen ) anstelle des Ritzels verwandt. Das grosse Zahrad (jetzt ohne Zähne) dient dann nur noch als Träger für die Encoderscheibe. Die 50 Zähne musste ich entfernen, da sie sonst in die Zähne des 2 Zahnrads griffen und dieses blockierten.
Das grösste Problem (neben der Wegermittlung) war, dass das anstelle des Ritzels verwandte Zahrad ein grösseres Loch für die Welle aufwies. Da hatte ich aber so einen Adapter (wohl auch von OPITEK) zur Anpassung unterschiedlicher Wellendurchmesser.

Bei der Wegermittlung hab ich ein Problem : Die Berechnung der Weglänge (0,58 mm / TIK) scheint in Ordnung, vermutlich gehen mir aber irgenwelche(3 von 4?) TIKs verloren, da der 8-Bit-Wandler eventuell zu langsam ist oder aus anderen Gründen die schwarz/weiss Wechsel nur jedes 3. oder vierte Mal erkannt werden. Die Messdaten zur Ermittlung der MY-ODO-WERTE - bis auf den relativ geringen Abstand zwischen etwa 170 und 245 für hell/dunkel - sahen aber - im Leerlauf - eigentlich recht gut (sinusähnlich ) aus.

oberallgeier
10.10.2008, 10:44
Danke mausi_mick.
... war natürlich gelogen ...Na ja, nicht wirklich. Ich glaube, ich muss nun wirklich mal meine Version der Geschwindigkeitsmessung mit der Gabellichtschranke am asuro ausprobieren, die ja auf meinem Dottie mit INT0 und INT1 ganz hervorragend funktioniert. Da büsse ich allerdings die Tasterfunktion und die Linienfolger ein - aber für eine erste Bestätigung würde das dafürstehen. Bisher fehlte mir halt eine Idee, wie ich die Unterbrecherscheibe am Motor befestige.

Sternthaler
16.10.2008, 00:12
Hallo mal wieder.

Ihr habt mich ein bisschen abgehängt ;-).
Zum Thema Odometrie am Asuro mit Gabellichtschranken hat inka unter: Probleme mit 22er-Lochscheiben (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=35109) einen sehr guten Beitrag begonnen.

Gruß Sternthaler

mausi_mick
16.10.2008, 06:27
Hallo Sternthaler,

Dank für Deine Info,
Super-Thread von Inka und den anderen,
ich hatte nur gedacht, da die Gabellichtschranken im Vergleich zu den ReflexLS sauber durchschalten , dass man auf die Mimik mit den vergleichsweise langsamen ADCs verzichten kann und die Timer / Counter des Atmega8 benutzt.
Habe aber beim ASURO zu Verwendung der Timer als Impulszähler nichts gefunden.
Kenne mich mit den ISR nicht aus und weiss nicht, wenn ich z.B. Timer0 und Timer1 mit zusätzlichen oder modifizierten ISR/Prescaler etc. für GabelLS links/rechts benutze, ob dann noch die IR-Schnittstelle und - in dem Zusammenhang wichtiger - die PWM (OCR0/1) für die Motoren gehen.

Gruß
mausi_mick

Richard
16.10.2008, 10:25
Hallo Mausi_mick,


Windoof-Installation auf E: ist ja seeeehhhhr ungewöhnlich.

Gruß Sternthaler

Moin moin,

Geht ganz einfach. USB Stick bei der Installation im Rechner
stecken lassen und schon installiert sich Win sostwo hin, bei
mir war es auch E:\. Ich habe dann aber neu installiert und
C:\ manuell ausgesucht, besser isses. :-)

Gruß Richard

Richard
16.10.2008, 10:28
Hallo Mausi_mick,


Windoof-Installation auf E: ist ja seeeehhhhr ungewöhnlich.

Gruß Sternthaler

Moin moin,

Geht ganz einfach. USB Stick bei der Installation im Rechner
stecken lassen und schon installiert sich Win sostwo hin, bei
mir war es auch E:\. Ich habe dann aber neu installiert und
C:\ manuell ausgesucht, besser isses. :-)

Gruß Richard

Sternthaler
16.10.2008, 23:27
Hallo zusammen.

@Richard
Guter Tip für hääääßßßßliches Windoof-Verhalten!


Hi mausi_mick,

ja, inka hat da schon Panik bekommen, als wir ihm die 3680 (oder so ähnlich) vielen Bohrlöcher vorgerechnet hatten.

Ich bin mir recht sicher, dass du erst einmal keine Timer zum Registrieren der Löcher bei einer Gabel benötigen würdest.
Schwieriger ist es, wenn die beiden Seiten irgendwie per ISR bearbeitet werden sollen, beide in den Asuro zu bekommen.
Die beiden Eingänge zum ADC (0 und 1) für die ODO-Sensoren können leider nicht per Interrupt überwacht werden.

Der INT1-Eingang wird durch die Tasten belegt, und sollte meiner Meinung nach nicht abmontiert werden.
Somit bleibt nur der eine INT0-Eingang übrig.

Meine Idee zur Schaltplanschmiererei ist folgende:

Unter der Annahme, dass die Differenz zwischen Hell-/Dunkelsignal so gut ist, wie inka es gezeigt hat, kann man versuchen ein logisches OR-Glied aus den beiden Dioden (oberhalb vom AVR gezeichnet) zu bilden um beide Rad-Seiten zusammenzufassen. Der Widerstand dazu sollte recht groß gegenüber den im Asuro eingebauten R18 und R20 sein, um möglichts wenig Einfluß zu nehmen.

Somit kann am INT0-Eingang ein Interupt ausgelößt werden, wenn einer der beiden Räder meint ein Loch zu sehen.
Die ISR-Funktion dazu liest dann einfach die ADC0/1-Ports als BIT-Wert ein und schon kann dort gezählt werden.
Auch hier sollte man natürlich darauf achten, dass nur dann hochgezählt wird, wenn ein Bitwechsel erfolgt ist.

Das einziege (Määäh), was dann nicht mehr funktionieren würde ist dann die rote Seite der Status-LED, da die AVR-Leitung ja nun als Interrupt-Eingang zu konfigurieren ist.

Ob die beiden Dioden mit dem Widerstand zusammen, bzw. der Spannungseinbruch bei beleuchtetem T11/T12, tatsächlich ausreichen um ein LOW-Signal am INT0-Eingang zu erzeugen, kann ich allerdings nicht sagen.

Gruß Sternthaler

Und da die Schaltplankritzelei:

oberallgeier
17.10.2008, 00:10
Hallo Ihr Bohrungsgucker,


... Unter der Annahme, dass die Differenz zwischen Hell-/Dunkelsignal so gut ist, wie inka es gezeigt hat ...Da die Bohrlochgabellichtschrankengeschwindigkeitsmessung von Inka ähnlich ist wie die Messung in meinen Minimotoren, wird es schon möglich sein, einen ähnlichen Signalabstand zu bekommen, wie ich ihn hier gemessen und gezeigt hatte. (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=344795#344795) Man kann hier recht gut mit dem Vorschaltwiderstand (Helligkeit) der LED und dem Vorschaltwiderstand (load resistor) des Fototransistors spielen und die Signalpegel deutlich verschieben. Ich hatte mir nach der Dimensionierung laut Datenblatt immer einen kleinen Messstand aufgebaut und auch die Widerstände angepasst . . . .

Sternthaler
17.10.2008, 00:47
Hossa Schnellantwortschreibermitgutemtipdabei.

Kleine Betrachtung, warum ich 'Angst' vor meiner Minimal-Schaltung habe:
Selbst wenn der Fotowiderstand in T11/T12 auf 0 Ohm abfallen würde, bleibt immer noch auf der anderen Seite der Diode eine Restspannung von ca. 0,7 Volt übrig. Und da der Widerstand keinesfalls auf 0 runter geht, ist diese Spannung auf alle Fälle größer.
Ich weiß aktuell nicht auf welchen Pegel der INT-Eingang reagiert um ein LOW zu erkennen. Müsste man in der Doku mal nachschlagen. Genau das ist der Punkt, vor dem ich 'warnen' will.

Als Alternative bei den Dioden kämen aber auch noch Germanium-Dioden in Frage. Dort beträgt die 'Restspannung' nur ca. 0,3 Volt.

Und Tschüß
Sternthaler

mausi_mick
17.10.2008, 04:39
Hallo Sternthaler,
Hallo Oberallgeier,

Danke für den Vorschlag, werde das mal mit den Dioden probieren,
werd aber wohl anstelle Germanium eher Schottkys verwenden.
Schön ist, dass mann dabei die Pollswitch-Funktionen weiter verwenden kann.

Bei den ISR werd ich mich dann wohl spätestens wieder melden.


Gruß

mausi_mick

oberallgeier
17.10.2008, 10:25
Hallo mausi_mick,

ich hatte für meine Motoren eine fertige Gabellichtschranke genommen, die GP1S093HCZ von Sharp (kostet bei CSD (http://www.csd-electronics.de/de/index.htm) 0,45 EU(lekt)ROnen). Da ich Platz sparen musste, kam mir diese Subminiaturversion gerade recht. Die bringt am Standard-Asuro-Zahnrad (weisser kunststoff, eingeschwärzt mit Stabilo-OHPen-Filzstift) einen Spannungshub von 0,29 V unbedämpft = Zahnlücke auf 2,7 V am Zahnkopf --- Messtrecke vom Fremdlicht weitgehend abgeschirmt. Durch besseres Einschwärzen der Zahnscheibe wäre da sicher noch etwas zu machen. Ich hatte mich kurz mal mit diesem Thema beschäftigt (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=322040#322040), aber hatte es nicht weiter verfolgt.

Im "Maximalfall" - bedämpft mit einem Metallunterbrecher - bringt der Signalausgang 5,03 V bei Versorgungsspannung 5,04 V. Die Abweichung kann vom Messrauschen kommen (MetraHit 12S). Als Vorschaltwiderstand für die LED habe ich 330R und als load resistance 10k - auf der benutzten Testplatine beide in SMD.

Bei Sharp gibts zum genannten Bauteil ein Datenblatt (http://document.sharpsma.com/files/GP1S093HCZ0F_DS.pdf) und natürlich auch technische Daten. (http://www.sharpsme.com/Page.aspx/europe/en/part/GP1S093HCZ0F/) Meine Schaltung ist aus dem Datenblatt, Seite 5, entnommen.

mausi_mick, schaust Du nie nach Deinen PN?

mausi_mick
18.10.2008, 07:09
Hi oberallgeier,
Hi Richard

musste mich erst mal bezüglich "PN" informieren, kannte es bisher wohl nur als Übergang und ist - bei Schottky - wohl irrelevant.

PN : meinst wahrscheinlich Persönliche / Private Nachricht und nicht Picairninseln.
Bin mir aber nicht sicher, auf welche PN Du Dich beziehst.

Bei den Gabellichtschranken werde ich erstmal andere nehmen, da sie wohl besser zu den bereits vorhandenen Bohrungen im Zahnrad passen.
Sie scheinen ähnliches Schaltverhalten wie die Sharps zu haben.
Die Schwärzung des Zahnrades hatte ich auch beabsichtigt, hab aber noch zwei schwarze Zahnräder gefunden, bei denen sich die Einschwärzung wohl erübrigt.

Werde dann - dauert vermutlich noch etwas wegen anderen Terminen - mit der Gabel-LS direkt mit Zahnrad an der Motorwelle testen. An /in ihm sind bereits 4 Bohrungen, die ich für die Gabel-LS nutzen will.

Mit der Neuinstallation Windows bin ich etwas vorsichtig, da
- mein SYSTEM auf E: sehr stabil läuft, wenn ich den Rechner hochfahren kann
- auf der C (noch rudimentäre) Daten sind, die ich nicht löschen kann, ich kann die Partition auch nicht formatieren, vermutlich Plattenfehler
- ich beim Booten seit 6 Monaten Probleme habe:
Rechner lässt sich nur einschalten, wenn Super-IO-Chip warm (>23,4 °).
Ist wohl der interne Temperatursensor, den man/ich nicht austricksen kann.
An warmen Sommertagen startet der PC direkt, an kälteren Tagen (z.B. heute) muss ich ihn per Föhn starten: es reichen ca 10-15s bei schwacher
Hitze (hört sich wie ein Kochrezept an).
Ist aber relativ unkritisch, da ich ihn (Föhn) für meine dreieinhalb Haare nicht wirklich benötige.

Besser als Neuinstallation ist vermutlich neuer Rchner bzw. Motherboard/Festplatte

Gruß und Dank für die Info

mausi_mick

Richard
18.10.2008, 09:59
Hi oberallgeier,
Hi Richard

Besser als Neuinstallation ist vermutlich neuer Rchner bzw. Motherboard/Festplatte

Gruß und Dank für die Info

mausi_mick

Moin moin, dann hast Du aber das Problem das die meisten
Installprogramme nach C:\ installieren wollen und es möglicherweise
auch machen wenn auf C:\ noch ein altes Win Verzeichniss
vorhanden ist. :-((( Irgendwann geht das dann daneben und es
werden b.B. falsche DLL dateien geladen/geschrieben!

Sicher die wichtigsten Dateien, nimm ne Linux Live CD, starte
Fdisk dev/hda und Partioniere neu, danach ist die Platte blank
wie ein Kinderpopo. :-) Formatieren kannst Du dann wieder mit
der Install CD von Win, aber bitte von Hand C:\ auswählen. Wenn
ein Bootfähiges Wechelmedium im PC steckt und C:\ noch nicht
Bootfähig Formatiert ist, wird das Wechselmedium als erste Platte
= "C:\" erkannt und Win landet wieder auf der falschen Platte...

Das Du C:\ nicht löschen kannst bedeutet ziemlich sicher das
Win auf Systemdateien von C:\ zugreift......

Gruß Richard

oberallgeier
18.10.2008, 10:11
... nimm ne Linux Live CD, starte Fdisk dev/hda und Partioniere neu, danach ist die Platte blank wie ein Kinderpopo ...Meine traditionelle Vorgehensweise ist wesentlich arbeitssparender: Knoppix, mit dd die ersten paar Sektoren löschen. Danach erkennt Windoof diese Platte als fabrikneu . . . . und fährt das volle Neue-Platte-Programm.

@mausi_mick:
... erst mal bezüglich "PN" informieren ... :-({|= .... in Deinem Postfach (Private Nachrichten, Posteingang) liegt eine Nachricht für Dich .... :-({|=

mausi_mick
18.10.2008, 12:46
hi oberallgeier,

Danke für den Tipp mit dem Postfach - das Naheliegende ist manchmal doch etwas fern.

Hab mir mal den Source ausgedruckt zum Studieren ...

Gruß

mausi_mick

Richard
18.10.2008, 15:04
Moin moin allerseits.

Mir ist aufgefallen das ihr Lichtschranken mit analogen Ausgang verwendet.
Da ist eine gute Auswertung doch recht schwierig und verbraucht auch noch
Zeit weil über AD Wandler eingelesen wird?

Ich habe hier mal ein Datenblatt von Lichtschranken welche OC Ausgänge
haben und das gleich 2, hell durchgesteuert, dunkel durchgesteuert.
Möglich das die besser zu gebrauchen b.z.w. auszuwerten sind.

"https://www.distrelec.com/distrelec/datasheets.nsf/WebAttachmen/758D0FC46C711EABC125730200312F56/$File/PM-Serie_Data-D.pdf"

Da der Link zu lang ist und vom Editor abgeschnitten wird, habe ich das in ""
gesetzt. Die müssen beim Copieren entfallen!

Die Firma selber....

https://www.distrelec.de/ishopWebFront/home.do?language=de&shop=DE

Grüße Richard

oberallgeier
18.10.2008, 18:09
... Lichtschranken mit analogen Ausgang ... gute Auswertung ... schwierig und verbraucht ... Zeit ....Wieso soll eine gute Auswertung schwierig sein? Das verstehe ich jetzt nicht. Der ADC wird angestossen und meldet sich (gibt einen Interrupt), wenn er mit der Messung fertig ist. Und das Ergebnis hat bei mir üblicherweise einen Fehler von weniger als 1 % vom Messwert. Ist das schlecht? Oder ist Dir die 25 Hz-Messfrequenz des Sharp zu langsam? Wo liegt denn Dein Problem? Ich sehe für mich keines.


... Möglich das die besser zu gebrauchen b.z.w. auszuwerten sind ...Ist das eine Möglichkeit oder eine Tatsache? Hast Du Erfahrungen mit dem Teil? Ich kenne Messverfahren mit 0/1-Aussagen. Also wenns blos ne Möglichkeit ist . . . . ich würde meine getesteten Erfahrungen nicht mit einer möglichen Verbesserung im untersten %-Bereich tauschen.

Richard
19.10.2008, 06:57
... Möglich das die besser zu gebrauchen b.z.w. auszuwerten sind ...Ist das eine Möglichkeit oder eine Tatsache? Hast Du Erfahrungen mit dem Teil? Ich kenne Messverfahren mit 0/1-Aussagen. Also wenns blos ne Möglichkeit ist . . . . ich würde meine getesteten Erfahrungen nicht mit einer möglichen Verbesserung im untersten %-Bereich tauschen.

Moin moin, eine Möglichkeit. Mir kam es in diesem Thread so vor als das
es mit der Lichtschranke Probleme gab? Deshalb hatte ich das Datenblatt
hier gepostet, schuldigung wenns nicht recht war.

Gruß Richard

mausi_mick
19.10.2008, 08:00
Hallo Richard,
aus meiner Sicht mal eine kleine Zusammenfassung:

Beim ursprünglichen Thema "Kurve fahren" gab es bei mir bei der Motorregelung neben Software-Problemen auch diverse Probleme
mit der HW, den Sensoren.
Die ursprünglich montierten Reflexsensoren weisen folgende Nachteile auf:
- starke Umgebungslichtabhängigkeit , reduzierbar durch Kapselung der Sensoren oder Verwendung bereits gekapselter Sensoren (z.B. CNY70)
- keine schnelle Regelung möglich , da Messwertaufnahme zu langsam
Behebung durch: Erhöhung der Anzahl der schwarz/weiss-Segmente
auf Odometriescheiben und/oder Verlegung der Odometriescheibe auf Motorzahnrad/Ritzel, schnellerer ADC (10-Bit auf 8Bit -> 4Bit?)
- Reflexsensor liefert kein TTL-Signal , da Transistoren bei Reflexion (weiss) nicht sauber durchschalten und Flanken nicht steil sind ("sinusförmig"), behebbar durch Schmitttrigger mit justierbarer Schaltschwelle (softwaremässig gelöst).

Gabellichtschranken dagegen schalten - wie oberallgeier bereits ermittelt hat und auch ich durch eigene Tests bei kleinen Drehzahlen bestätigen kann - bei den verwandten Diodenströmen deutlich besser durch und liefern ein TTL-ähnliches Signal. Daher kann man sich den (zeit)-aufwändigen ADC sparen und die Impulse zählen und bekommt dann wohl nicht - wie bei Inka diskutiert - Probleme mit der Wandlungszeit bei hohen Drehzahlen/TIKs.

Ich habe nach der Ermittlung des Schaltverhaltens die Gabel-LS genommen, die von den Abmessungen (Schlitzbreite-/höhe, Lage des Sensors) am besten zu meinen Odometrielochscheiben passten.

Damit lässt sich wohl - wie oberallgeier bei seinem dooty realisiert - eine
sehr gute und schnelle Motorregelung erreichen.

Wenn ich das richtig sehe, macht oberallgeier die Regelung wohl über Timer2 und INT1/INT0 beim ATMega168,
STERNTHALER schlägt für den ASURO (ATMega8) INT0 vor, da INT1 durch durch die Taster belegt ist.

Gruß

mausi_mick

Richard
19.10.2008, 09:48
Hallo Richard,


Gabellichtschranken dagegen schalten - wie oberallgeier bereits ermittelt hat und auch ich durch eigene Tests bei kleinen Drehzahlen bestätigen kann - bei den verwandten Diodenströmen deutlich besser durch und liefern ein TTL-ähnliches Signal. Daher kann man sich den (zeit)-aufwändigen ADC sparen und die Impulse zählen und bekommt dann wohl nicht - wie bei Inka diskutiert - Probleme mit der Wandlungszeit bei hohen Drehzahlen/TIKs.

Gruß

mausi_mick

Hallo mausi_nick,

Genau deshalb hatte ich auf das Datenblatt hingewiesen, diese
Gabellichtschranken haben intern eine Auswertung und als Ausgang
2 ( hell/dunkel schaltend) open Collecktor Ausgänge. Da sollte es
nie (?) Probleme mit den Signalen geben. Mit den Asuro selber kenne
ich mich nicht aus, vom Prinip her sind mir aber OC Ausgäne lieb weil
damit auch gleich ( wenn benötigt ) eine Pegelanpassung gemacht
werden kann.

Gruß Richard

mausi_mick
21.10.2008, 07:30
Hi Richard,
hab mir mal die Datenblätter von distrelec/Schuricht angesehen,
würde wohl - wegen der Abmessungen (Gabelweite/Tiefe etc), den Anschlüssen und den Preisen - eher die Vishay bzw. Fairchild - Typen verwenden. Die sind aber so ähnlich wie meine von Optek.
Open-Collector haben die alle, es ist ja nur neben der IR-Diode der "nackte" Opto-Transistor eingebaut. Wichtig ist eigentlich nur das CTR (CurrentTransferRatio), d.h. wieviel Diodenstrom ich zum Durchschalten
des Transsistors brauche und die Qualität des Opto-Schalttransistors (Kollektorrestspannung etc).
Das CTR ist stark von der Gabelweite abhängig. Ich werde eine mit 2,5-3mm verwenden, da meine Lochscheibe ca 2mm Stärke hat.
Zur Signalaufbereitung (Flankensteilheit) werde ich mal testweise einen Schmitttriger (74HC132) verwenden, wird aber vermutlich nicht notwendig sein.


Gruß
mausi_mick

PS:
Ich hab zwar bei distrelec die Doku zu den PM-K LS gefunden,
aber kein Angebot bzw. Preise dazu. Bei anderen Anbietern kostet z.B. PM-K24 mehr als 15 €, gegenüber weniger als 1 € bei "normalen" LS.
Der Strom (max. 15mA) ist im Datenblatt nicht genauer spezifiziert, da aber vermutlich intern eine Konstantstromquelle verwandt wird, kann man bei 5V wohl auch mit mehr als 10mA rechnen. Ausserdem kann ich nicht - wie beim ASURO - die beiden IR-Dioden in Reihe schalten, da die Anschlüsse nicht separat herausgeführt werden.
Die zwei Ausgänge werden bei der vorgesehenen Anwendung wohl auch nicht benötigt.

mausi_mick
21.10.2008, 17:52
hi Curver,

hab heute mal die HW aufgebaut inclusive Schmitttrigger (74HC132).
Erste Messungen erfolgsversprechend. Bei dem verwandten Rad mit den 4 Bohrungen bekommt man halt relativ schmale Impulse. Die Flankensteilheit ist bei den hohen Drehzahlen an der Motornabe noch relativ gut, sodass man wohl auf den Schmitttrigger verzichten kann.
Ich muss die Positionierung der Gabel-LS noch verbessern und stabilisiern. Taucht die Gabel nicht tief genug ein, schalten die Transistoren nicht mehr voll durch und es gehen dann eventuell TIKs verloren.
Ich betreibe die IR-LEDs mit ca 10mA (in Reihe), dafür sieht das Signal auf dem Oskar bei exakter Positionierung der LS sehr gut aus.

Die Software arbeitet z.Zt. noch mit den 8-Bit-Wandleren.

Im Anhang noch ein paar Foto's von Platine und Aufbau.

Gruß

mausi_mick

mausi_mick
22.10.2008, 07:01
Hi curver,
wegen des ungünstigen Tastverhältnisses bei der 4-Lochscheibe werde ich -
zumindest wenn ich die ADC-Wandlung beibehalte - mit einem Teiler durch 2 (74HC74) - ein symmetrisches Signal erzeugen. Der 74HC74 hat auch Schmitttrigger-Eingänge, sodass dann der 74HC132 entfällt.

Besser wäre es wohl , eine Lochscheibe mit z.B 8 Löchern zu verwenden, bezweifle aber, dass ich das sauber hinbekomme.

Gruss mausi_mick

mausi_mick
23.10.2008, 12:30
Hi Curver,

hab die Halterung für die Gabel-LS etwas verbessert, sodass Abstand Lochscheibe zu Gabel-LS fixiert ist und Löcher auf Höhe der Sensoren.
Anbei noch ein paar Fotos zum Aufbau und Messergebnis bei MotorSpeed (255,255) und 4-Loschscheibe an Motorwelle/Ritzel.
Die Einstellung am Oskar waren 1V / 1ms.
Das Signal sieht gut aus, den Schmitttrigger (74HC132) brauch ich wohl nicht.

Gruss mausi_mick

mausi_mick
23.10.2008, 14:27
Hi curver,

bei der Messung der Spannung an ADC0 / ADC1 mit 8-Bit-Wandler
ergaben sich für das Minimum ( Light) 8 und für das Maximum ( Dark) 252 in einem Speed-Bereich von 100 - 255 (Räder freilaufend). Unterschiede zwischen rechts und links waren nicht messbar. Bei der 4-Lochscheibe ist das Tastverhältnis Low/High etwa 1/3. Der 8 Bit ADC scheint das Signal auch bei Speed 255 locker auswerten zu können.

Gruß

mausi_mick

mare_crisium
23.10.2008, 18:28
Buona sera, mausi_mick,

nur damit Du nicht meinst, Deine Arbeit würde nicht beachtet: Du machst das ganz ausgezeichnet - sehr systematisch und immer der Logik folgend.
Grosse Anerkennung :-) !!!

Nur weiter so!

mare_crisium

mausi_mick
24.10.2008, 06:14
Buon giorno, mare_crisium,

Dank für die Blumen,

ich persönlich seh das etwas anders - bezüglich Systematik und Logik .

Ich eiere eigentlich ziemlich herum. Seitdem ich die Messung der Ticks von dem ursprünglich 2. Rad auf das erste (Motorwelle/Ritzel) verlegt habe,
stimmt die Strecken/Wegermittlung überhaupt nicht mehr:

Legte ASURO ursprünglich etwa 1,94 mm / Tick zurueck (60 Impulse auf 116,2 mm (=1 Radumdrehung), sollte er jetzt eigentlich nur ca 0,581 mm/Tick zuruecklegen (200 Impulse pro Radumdrehung).

Obwohl ich das im Programm berücksichtigt habe oder zu haben glaube, fährt ASURO aber z.Zt. ca 3-4 mal so weit . Irgendwie hab ich wohl im Programm noch was übersehen, da der 8-Bitwandler auch bei den schnelleren Light/Dark-Wechseln zu funktionieren scheint und somit ein Wechsel auf einen (schnelleren) 4-Bitwandler oder ein reines Zählen der Impulse (INT0) nicht notwendig zu sein scheint.


Gruß

mausi_mick

mausi_mick
24.10.2008, 08:33
hi curver,
ja , man muss wohl esrt mal jammern, bevor man sich um die Probleme
kümmert. Hab mir das Programm nochmal angesehen:

Abbruchbedingung für gefahrene Wegstrecke war fehlerhaft.
Dann hab ich die Startgeschwindigkeit mal auf 255 gesetzt, um ASURO in den ersten ms mal etwas "auf Speed" zu bringen.
Ausserdem am Stereckenende (letzte 10% bzw. 10cm) Speed auf 100 gesetzt, damit er nicht soviel weiter rollt. Das ist aber noch verbesserungswürdig (siehe PID-Regler von waste etc.)

Gruß

mausi_mick

oberallgeier
24.10.2008, 08:55
Grüß Dich, mausi_mick,


... Startgeschwindigkeit mal auf 255 gesetzt, um ASURO in den ersten ms mal etwas "auf Speed" zu bringen ...In verschiedenen Postings wird über Probleme mit kleinsten Motoren, speziell mit total "ausgeweideten" Servos berichtet, deren Lebenserwartung sich mitunter im Minutenbereich bewegen würde. Das kann ich nicht bestätigen und ich glaube zu wissen warum: Ich hatte ziemlich früh die Sprungfunktion meines Dottie gemessen (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=388755#388755) und daraus die Zeitkonstanten der beiden Motoren bestimmt. Als sehr simple Näherung hatte ich anschließend die Motoren entsprechend dieser ersten Anstiegszeit hochgefahren. Die dankten es mir mit einer mittlerweile viele Stunden währenden Lebensdauer.

Nun ist mir klar, dass die Motoren des asuro wesentlich robuster sind. Beim asuro hatte ich festgestellt, dass die Motoren eine bestimmte Anfahrleistung benötigen - also einen bestimmten, minimalen PWM-Wert benötigen um sich zu bewegen. Wenn der überschritten ist, dann legen die los. Dieser Wert ist bei den Motoren meines asuro unterschiedlich. Anm.: auch Dottie hat an einem Motor eine Zeitkonstante von 12 ms und am anderen nur 8 ms. Dies nur als Anmerkung zur "Vollgas-Startphase".

mausi_mick
25.10.2008, 09:35
Hi curver,

hab heute mal die Ticks gemessen bei verschiedenen Geschwindigkeiten.
Vorher hab ich den Motor 150ms lang auf die gewünschte speed gebracht
(müsste eigentlich reichen).
Bei 2 s Messdauer gab's folgende Werte:

im Leerlauf:

speed 255 : links 2017 Ticks, rechts 2099 Ticks
speed 200 : links 1450 Ticks, rechts 1527 Ticks
speed 150 : links 1019 Ticks, rechts 1056 Ticks
speed 110 : links 660 Ticks, rechts 628 Ticks

und bei Fahrt auf Parkett:

speed 255: links 1860 Ticks, rechts 1973 Ticks Strecke: 120cm (inclusive 150ms für Beschleunigung auf 255 ).

1860 * 0,5808 = 1080 mm links
1973 * 0,5809 = 1146 mm rechts

Anmerkung: bei einer Radumdrehung (116,2 mm) und Untersetzung 25 : 1 und 8 Ticks pro Motorumdrehung legt ASURO pro Tick 116,2mm / 200 = 0,581mm zurueck.

Das scheint zu passen.

Gruss mausi_mick

mausi_mick
25.10.2008, 14:27
hi curver,

hab noch ein wenig getestet (Haus vom Nikolaus Aussenkontur abgefahren mit 500mm Basilänge). Dabei den gravierensten Fehler eliminiert: man sollte am Ende einer Fahrstrecke (bevor man z.B. die Messwerte auf den PC ausgibt) die Motorrichtung MotorDir( , ) auf BREAK,BREAK setzen !

Jetzt klappt das relativ gut : er kommt bis auf 50mm-100mm an den Startpunkt heran.
Der Aufruf erfolgt
über
unsigned char GoTurnCircle ( long distance, int speed_mms, int radius);

mit distance in mm (> 0 , 0 nur erlaubt bei radius ^= 0 (Drehen auf Stelle))
speed_mms in mm/s (+ vorwärts,-rückwärts, Absolutwert zwischen 5 min und 600 max),
radius in mm (+=Rechtskurve, - = Linkskurve) für Kurve, 0 = geradeaus

bei distance = 0 wird der Radius-Angabe als Winkel interpretiert:
z.B.
errc = GoTurnCircle ( 0,200,-90) Linksdrehung um 90° auf der Stelle mit Geschwindigkeit 200mm/s


Gruß

mausi_mick

mausi_mick
30.10.2008, 16:18
hi curver,

Ich habe , da es mit der Geschwindigkeit der 8-Bit AD-Wandler keine Probleme gab, durch vier zusätzliche Bohrungen an dem Encoderrad die Anzahl der Ticks pro mm Wegstrecke verdoppelt: 5 x 5 x 16 = 400 Ticks pro Radumdrehung (d.h. auf ca 116-120mm) , macht dann etwa 0,2975 mm / Tick (hab intern mit 0,3 gerechnet ).
Erziele bei Geradeausfahrt eine Genauigkeit von ca +-/ 1cm bei 100cm Fahrweg.
Die Winkelgenauigkeit (Drehung auf der Stelle) liegt bei etwa 1% (bei 90° gemessen) .
Die Geschwindigkeit hab ich - gerade bei den "normalen Kurven" - etwas beiseite gelassen, ist auch bei meinen Anwendungen eher nebensächlich. Ich bremse ASURO auf den letzten 4cm in zwei Stufen etwas ab, um nicht aufgrund der Trägheit über das Ziel hinauszufahren( geht halt nur , wenn die Fahrstrecke > 4 cm ist.)
Beim Drehen auf der Stelle und kleinen Winkeln (z.Zt 30°) spendiere ich ASURO noch eine Ehrenrunde von 360°. Den Wert 30° kann man wohl noch senken, aber unter 5 ° ist die Zusatzrunde zum Erzielen einer hohen Genauigkeit bestimmt sinnvoll.

Gruss

mausi_mick

mausi_mick
31.10.2008, 07:32
hi curver,

hab den Code noch etwas verbessert und beim Drehen auf der Stelle
die Extrarunde erst bei Winkeln unter 20° spendiert.

Der Absolutwert von speed wird nicht als Sollvorgabe verwendet, intern wird mit einer mittleren Geschwindigkeit von 170 gearbeitet.
Wenn man unterschiedliche Geschwindigkeiten vorgeben will, muss man auch die Bremswege entsprechend anpassen, da sonst ASURO aufgrund seiner Trägheit z.B. bei höheren Geschwindigkeiten über sein Fahrziel hinausfährt.

im Anhang noch ein Beispiel Code (GoTurn2)

mausi_mick
04.11.2008, 07:56
hi curver,
hab doch mal eine Geschwindigkeitsvorgabe zugelassen für Gescwindigkeiten
von kleiner ca 250mm /s (entspricht bei mir etwa MotorSpeed(170,170)) für Geradeausfahrt und Drehen um Achse.

Wegeinhaltung - auch bei kleinen Geschwindigkeits (50 mms/s ) (entspricht bei mir ca MotorSpeed(88,88) - sehr gut, wobei die Geschwindigkeit allerdings nur grob eingehalten wird:

Im Anfahrbereich (für die ersten Ticks ) beschleunige ich ASURO mit MotorSpeed(170,170), daher ist dann aufgrund der Trägheit die Geschwindigkeit auf den ersten ca 5cm Fahrweg bei kleinen Geschwindigkeitsvorgaben zu hoch.

mausi_mick
09.11.2008, 09:16
hi,

noch ein Vergleich mit der Original-GoTurn()-Funktion:

beim Abfahren einer vorgegebenen Strecke (Aussenkontur vom Haus vom Nikolaus mit 1000mm Basislänge) komme ich bei relativ niedriger Geschwindigkeit bei meiner Programmversion (GoTurn2()) etwa auf 100 mm an den Startpunkt heran, während bei der original GoTurn( ) Funktion der Abstand meist grösser als 300mm ist mit recht grosser Streuung.

Da die Streuung bei meinem Programm sehr klein ist, könnte man
durch Anpassung der Werte Tick / mm Fahrweg bzw. Tick / Grad
zumindest bei kleinen Geschwindigkeiten die Genauigkeit noch erhöhen.

Der verbleibende Rest kommt vermutlich durch Rutscheffekte und dynamische / träge Verhalten des Motors zustande.

Als Anhang noch das Vergleichsprogramm


Gruss

mausi_mick

PS: Ich habe in den H-Brücken die die BC3.. Transistoren durch ZETEX-Transistoren ersetzt, die deutlich niedrigere Collector-Emitter-Sättigungsspannungen haben und so ein sicheres Anfahren mit MotorSpeed(80,80) (bei vollem Akku ) ermöglichen.

Sternthaler
19.11.2008, 23:17
Hi mausi_mick,

tut mir leid, dass ich mich jetzt erst wieder einmal melde. (Arbeit, Arbeit, Jammer, Jammer)

Ich habe mir gerade mal deine letzte Version runtergeladen und ein bisschen begutachtet.

Du treibst ja mittlerweile einen enormen Aufwand für eine möglichst präzise Fahrt. Alleine die Geschwindigkeitsreduzierung kurz vor dem Erreichen des Ziels ist schon nicht schlecht.
Wie ich gefunden habe, hast du ja weiterhin auch noch die Situation abgefangen, dass in der Loop zum Abfahren der Wunschstrecke die Warteschleife für mindestens einen gefahrenene Tick benutzt wird.
Das scheint sich ja wohl doch zu einem zentralen Teil der ganzen Funktion ge(mausi_mick)ert zu haben.

Eine Stelle, eigentlich ja 2, ist/sind mir aufgefallen.
Wenn du in der Fahrt-Loop mit "if (tick_zi >= tick_end)" prüfst, ob die Summe der zu fahrenden Tiks am Ziel angekommen ist, verläßt du die GoTurn2()-Funktion mit einem "return (0)".
Dann aber ist nicht geprüft, ob jede Seite ihre Sollstrecke gefahren ist. Fehlt also einer Seite ein Tick, muss er auf der anderen Seite gefahren worden sein. Somit ist die Differenz immer 'doppel'schlecht.
Hier ist noch 'ein ganz kleines bisschen' Potenzial die Genauigkeit zu steigern. Eventuell dadurch, dass die noch fehlenden Tiks der einen Seite doch noch gefahren werden.
Sollte aber bestimmt nicht beim 'Drehen auf der Stelle' passieren, da hier ja die Summe der Tiks den Drehwinkel bestimmt, und somit genauer ist, als wenn die 'Fehlseite' noch weiter bewegt wird.
Beim Geradeausfahren allerdings steht der Asuro dann besser in der gewünschten/erwarteten Richtung.

Andererseits zeigen deine Angaben im Vergleich zur Originalfunktion ja schon sehr schön, dass sich dein Aufwand enorm gelohnt hat. Allerdings ist die Größe der Software ja auch enorm geworden.

Ich werde das ganze mal meinem Asuro verpassen und dann mal berichten. (wann, wann, jammer, jammer ;-))

Viele Grüße Sternthaler

Ach ja: Klasse Arbeit und viele informative Beiträge von dir.
Auch wenn aktuell nicht allzuviel geantwortet wurde. Ich werde versuchen mich zu bessern.

Sternthaler
12.12.2008, 00:39
Upps, besser spät als nie.

Hallo zusammen. Hallo mausi_mick,

leider muss ich von einem völligen Versagen auf meinem Asuro berichten.

Die Maschinen laufen beide gut an, und dann geht es nur noch in einer recht engen Linkskurve immer im Kreis.
Auch ein paar Versuche mit angepassten Werten für die Tik-Zählerei im Encoder-Teil haben keine Besserung gebracht.
Da mir mein Asuro im Moment etwas suspekt vorkommt (scheint ein wenig Staub angesetzt zu haben), habe ich mir den vom Nachbarn gekrallt, dort aber auch keinen Erfolg gehabt. Gleiches Resultat.

Ich stehe aktuell vor einem Rätsel, habe aber immer noch absolut keine Zeit das Problem auf meinem Asuro zu suchen.

Gruß Sternthaler

mausi_mick
12.12.2008, 17:35
Hallo Sternthaler,

bin erst heute aus Mexiko zurück, hatte Deinen Kommentar dort schon gelesen, aber keine Zeit ? zu antworten. Lag wohl doch eher an den Antwortszeiten, der Tastatur, den Temperaturen ...

Ich hab auch den Eindruck, dass das Programm zu gross ist. Auch ist das
Anfahrverhalten und das Abbremsen am Ende noch nicht optimal. Beim Anfahren merkt man auch die "Totzeit", bis die Regelung greift. Die Werte fürs Anfahren und Abbremsen sind eigentlich auch geschwindigkeitsabhängig, sodass das Programm noch aufwändiger würde.
Besser wäre es wohl - wie bei Waste und Dir schon realisiert - mit einem PID-Regler zu arbeiten.
Ein anderes Problem ist - gerade beim Kurve fahren - vielleicht auch darin zum sehen , dass ASURO ein Dreirad ist, wobei das 3. Rad (Tennisball) eigentlich schlechte (Reib-)Werte aufweist.
Um diesen Einfluss zu minimieren, müsste man es entlasten (bei mir z.T. realisiert durch Verlageren des Schwerpunkts durch Akku mit 4 Mignon (AA)-Zellen).

Mit der Messung der Ticks mit dem Gabel-LS bin ich sehr zufrieden, bringt im unteren Geschwindigkeitsbereich einiges . Den Aufbau könnte man wohl noch eleganter und weniger aufwändig gestalten, zumal der Schmitttrigger nicht notwendig ist.

Gruß

mausi_mick

oberallgeier
12.12.2008, 18:09
Hallo mausi_mick,


... Anfahrverhalten und das Abbremsen am Ende noch nicht optimal ...Ich habe ja leider seit Monaten den asuro beiseite gelegt und viel an meinem Dottie (https://www.roboternetz.de/phpBB2/viewtopic.php?p=390196#390196) gebaut. Dabei hatte ich aber (auch) sehr viel Wert auf die Regelung gelegt und hatte damit einigen Aufwand. Mittlerweile läuft die Regelung mit 405 Hz (https://www.roboternetz.de/phpBB2/download.php?id=15412) (hat sich so ergeben) recht ordentlich - alles integer, weil mit FP der Zeitaufwand viel zu hoch ist.

Ich hatte mir die Zeitkonstanten der einzelnen Motore bestimmt aus der Sprungantwort und dann ein bisschen an den Faktoren rumgepopelt. Die Motore fahre ich "entlang" der Sprungantwort hoch und stelle fest, dass das ihrer Lebensdauer bekommt (sind ja diese 5ervos ohne irgendeine eigene Elektronik, nur mein 2-Blatt-Encoder) - aber in rund 20 ms ist die Drehzahl (und die Regelung) da - wenn etwa 50 .. 70 % volle Drehzahl angesteuert wird. Ok, ich habe im Dottie einen mega168 mit 20 MHz.

/* === Regelungsroutine für Motor 12 ========================================== */
/* Die gemessene Zeitdifferenz Iz_diff0 wird zur Regelung verwendet
*/
void rgl_mo_12(void) // (Wird) Regelung für Motor 12
{
// PORTC |= (1<<PC4); // LED auf PC4/I2C/SCA einschalten = Start ISR
// PORTC &= ~(1<<PC4); // LED auf Port PC4/I2C/SCA ausschalten
// PORTC ^= (1<<PC4); // Zeitmessung: LED auf Port PC4/I2C/SCA toggeln

// Anmerkung für mausi_mick:
// tupsi = T imer U nits P er S ensor I nterrupts, Sensor = Encoder
// stupsi = Soll-tupsi
// stupsi12 = Soll-tupsi für Motor 12 (12 = Ausgänge des L293D)
// idrz = Ist-Drehzahl
//
if (stupsi12 <= 5) // Soll überhaupt gefahren werden?
{
OCR0A = 0;
return;
}
tupsi12 = Iz_diff0; // Übernahme Iz-Wert in Regelung
ndrz12 = stupsi12;
if ( tupsi12 > 100 ) { tupsi12 = 100; } // Eingrenzen
idrz12 = 1000 / tupsi12;
ie_mot12 = ndrz12 - idrz12; // Vergleich => Regelabweichung
iesum12 = iesum12 + ie_mot12;
if (iesum12 < -10) { iesum12 = -10;}
if (iesum12 > 500) { iesum12 = 500;}
iy12 = iesum12/2;
iy12 = iy12 + ie_mot12 + ie_mot12 + ie_mot12 + ie_mot12 + ie_mot12;
// Diese Rechenoperation benötigt in float 0,20 bis 0,25 ms!

if ( iy12 < 0 ) { iy12 = 0;}
if ( iy12 > 255 ) { iy12 = 255;}

OCR0A = iy12; // Ansteuerung der PWM direkt statt "setPWMlinks"
// PORTC ^= (1<<PC4); // "war-hier-Signal": LED auf PC4 toggeln

return;
}
/* ================================================== ============================ */
Meine Fähigkeiten in C (heisst bei mir immer noch Cäh) sind zwar recht gering und mein Code ist schauderhaft (nach interner Mitteilung eines Forummitglieds *ggggg*), aber vielleicht hilft Dir das etwas?

mausi_mick
19.12.2008, 07:30
hi oberallgeier,

danke für Deine Regelungsroutine.

Bin/war aber leider z.Zt. mit häuslichen Problemen (Toplader Waschmaschine stand "kopf" (Ladeöffung offen und unten, Trommel gefüllt, Wäsche nass, Trommel nicht drehbar, da Ladeklappen an Trommelwand verklemmt) und mit (Basic-)MonoWheel beschäftigt (hatte mir im Urlaub Gedanken gemacht, ob und wie man MW vielleicht doch noch zum Kurve fahren bringt).
Dazu will ich erst mal den am Baby-MW eingesetzten Winkelsensor SCA61T anstelle der beiden Sharp-Abstandssensoren verwenden.
Vorteil:
Geringerer Stromverbrauch (< 5mA) , weniger Entstöraufwand
Einbauposition/-ort beliebig (IC muss nur horizontal eingebaut werden),
einfachere,kürzere Verdrahtung,
geringeres Gewicht/Volumen
höhere Genauigkeit (10 Bit Wandler ?)
Senkrechte auch in geneigtem Gelände (Hang) erfassbar, wo Differnzabstandssensor versagt
weniger Programmieraufwand, geringere MC-Belastung (nur ein AD-Wandler)
Nachteil : Preis (kostet mehr al 50 € gegeüber ca 25€)

Werd mich daher in der nächsten Zeit nicht mit dem ASURO-Kurven-Thema beschäftigen können.

Gruß

mausi_mick