PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Asuro - Tasterfunktion beim Selbsttest, Problem



smuller
17.05.2006, 10:38
Hallo Leute,
bei meinem neuen Asuro habe ich ein Problem mit den Tastern beim Selbsttest. Laut Anleitung sollte bei Tastendruck folgendes passieren:

K1-> Staus LED grün
K2-> Status LED rot
K3-> Front LED
K4-> Back LED Links
K5-> Back LED rechts
K6-> Motor links

bei mir passiert allerdings folgendes:

K1-> Status LED grün + Motor links
K2-> beide Back LED + Motor links
K3-> Front LED
K4-> Back LED links
K5-> Back LED rechts
K6-> Motor links + Back LED rechts (für den Bruchteil einer Sekunde)

Für Rat und Hilfe bin ich sehr dankbar.

rainer75
17.05.2006, 17:31
Hallo!

Dass die Tasten nicht immer den gewünschten Wert liefern
kommt wohl ziemlich häufig vor.
Man kann dem durch eine kleine Ändeurng in der Software
abhelfen.

Schau Dir mal diesen Thread an und probiere das
dort angegebene Testprogramm, um zu sehen, welche
Werte welcher Taster liefert:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=11797

Alternativ kann es natürlich auch noch sein, dass Du beim
einlöten versehentlich ein paar Widerstände verwechselt
hast.

Grüße,
Rainer

smuller
18.05.2006, 14:25
Ich habe mir mittlerweile die Werte ausgeben lassen. Es wird eine 15 statt 16 und eine 7 statt der 8 geliefert.

Das:
alt: return ((10240000L/(long)i-10000L)*63L+5000L)/10000;
neu: return ((10240000L/(long)i-10000L)*65L+5000L)/10000;

hat etwas verändert, allerdings auch nach mehreren Änderungen der Werte nicht zum gewünschten Erfolg geführt. Jetzt hate ich es gelöst, allerdings etwas weniger elegant:
--
ret = ((10240000L/(long)i-10000L)*63L+5000L)/10000;
if(ret == 7 { ret = 8; }
return ret;
--

Es werden jetzt die korrekten Werte geliefert, allerdings ist der Fehler beim Selbsttest, natürlich mit geänderter asuro.c, immer noch genauso vorhanden. Alleridngs soll mein Asuro ja auch nicht nur Selbsttests durchführen. Wenn es bei weiteren Programmen keine Probleme gibt, soll es mich nicht weiter stören.

fxlee
19.05.2006, 01:22
Hallo,
ich habe auch das Problem mit den Tastern gehabt. Die Lösung mit der Modifikation der Return-Zeile in Funktion PollSwitch finde ich zwar brauchbar, sie bleibt aber meiner Meinung nach eine Quick&Dirty-Lösung. Man kann den Multiplikator variieren (*62, *63, *64, was auch immer, sogar mit Nachkommastellen) um die Werte 0, 1, 2, 4, 8, 16 und 32 zu bekommen wenn EINEN Taster gedrückt wird. Ich glaube aber, dass es sehr schwer ist die 64 Werte aller möglichen Kombinationen korrekt zu bekommen! In der Praxis kommt natürlich sehr selten vor, dass mehrere Taster z.B. 1,2,3,4 bei Kollision gleichzeitig gedrückt werden. Es macht aber trotzdem Sinn: z.B. Wenn ich feststellen will ob der Asuro an der linken oder rechten Seite mit einem Obj. kollidiert (Taster 1 und 2) dann brauche ich 48 (also 110000) und nicht 47 oder 46.
Meine Lösung des Problems heißt "lineare Regression" oder "lineare Ausgleich". Im Prinzip versucht man die Messwerte durch eine Gerade zu beschreiben, wobei die Lage (Parameter) der Gerade die Lösung des Ausgleichsproblems ist. (Anm.: Die Formel in PollSwitch enthält bereits die (Daume-mal-Pi) Lösung des Ausgleichsproblems.)

Nun habe ich folgendes gemacht:
1) Als erstes versuche ich herauszufinden, welche Werte ich zurückbekomme (so genau wie möglich, ohne Info-verlust) wenn ich einen oder mehrere Taster drücke. Dazu habe ich folgendes Prg. verwendet:


#include "asuro.h"

/* function to read out switches */
unsigned int testSwitch (void)
{ unsigned int i;
DDRD |= SWITCHES; // Switches as Output
SWITCH_ON; // Output HIGH for measurement
ADMUX = (1 << REFS0) | SWITCH; // AVCC reference with external capacitor
Sleep(10);

ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF)));// wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
i = ADCL + (ADCH << 8);

SWITCH_OFF;
Sleep(5);
return (int)(1023000L/(long)i);
}

int main(void)
{
Init();
StatusLED(OFF);

SerWrite("\n\rtest switch:\n",15);
StatusLED(GREEN);

while(1) {
int j;
long sum = 0, sw=0;
SerWrite("\n\r",2);
while (!PollSwitch());
Msleep(100);
for (j = 0; j < 100; j++)
sum += testSwitch();

int sw1,sw2;
do {
sw1 = PollSwitch();
sw2 = PollSwitch();
} while (sw1 != sw2);

PrintInt((int)(sum/100.0)+0.5);
Msleep(200);
SerWrite(" ",2);
PrintInt(sw1);
}
return 0;
}


Die Messwerte (1023/y) werden sozusagen direkt aufsummiert und Durchschnitt gebildet.

2) Anhand der Werte und die Formel in PollSwitch lässt sich vermuten, dass 1/y linear ist. Die Formel ist auch nichts anders als lineare Transformation. Wegen der herstellungsbedingten Ungenauigkeit der Widerstände liegen die Messwerte 1023/y nicht auf einer Gerade.

3) Als nächste habe ich Matlab angeworfen und die Ausgleichgerade berechnet:


Z = 1./y;
X = [ones(64,1) (0:63)'];
p = X\Z; % Lsg des Glg-Systems -> Koeff. der Gerade p
Z_out = (Z-p(1))/p(2);


4) Für denjenigen, der kein Matlab hat, habe ich was vorgerechnet.
Die Werte 1/y aus 1) im folgenden Prg dem y zuweisen.


#include "asuro.h"

int main(void)
{
// y wird durch indiv. Messwerte ersetzt
int y[] = {1000, 1015, 1031, 1047, 1062, 1079, 1095, 1111, 1125, 1142,
1157, 1173, 1190, 1206, 1222, 1238, 1258, 1274, 1290, 1307,
1322, 1339, 1355, 1369, 1384, 1401, 1417, 1433, 1449, 1466,
1480, 1498, 1525, 1541, 1557, 1574, 1589, 1606, 1621, 1637,
1653, 1669, 1685, 1699, 1716, 1734, 1749, 1764, 1785, 1801,
1817, 1833, 1850, 1867, 1881, 1898, 1912, 1930, 1945, 1960,
1975, 1994, 2010, 2026},
A[2][64] = {{
6106, 5962, 5817, 5673, 5529, 5385, 5240, 5096, 4952, 4808,
4663, 4519, 4375, 4231, 4087, 3942, 3798, 3654, 3510, 3365,
3221, 3077, 2933, 2788, 2644, 2500, 2356, 2212, 2067, 1923,
1779, 1635, 1490, 1346, 1202, 1058, 913, 769, 625, 481,
337, 192, 48, -96, -240, -385, -529, -673, -817, -962,
-1106, -1250, -1394, -1538, -1683, -1827, -1971, -2115, -2260, -2404,
-2548, -2692, -2837, -2981},
{
-144, -140, -135, -130, -126, -121, -117, -112, -108, -103,
-98, -94, -89, -85, -80, -76, -71, -66, -62, -57,
-53, -48, -43, -39, -34, -30, -25, -21, -16, -11,
-7, -2, 2, 7, 11, 16, 21, 25, 30, 34,
39, 43, 48, 53, 57, 62, 66, 71, 76, 80,
85, 89, 94, 98, 103, 108, 112, 117, 121, 126,
130, 135, 140, 144}};

int i;
float p1,p2,fkt=1.e5;
p1 = p2 = 0;
Init();
SerWrite("\n\rlin.Regression:\n\r",19);
for (i = 0; i < 64; i++) {
p1 += (float)A[0][i]*(float)y[i];
p2 += (float)A[1][i]*(float)y[i];
}
p1 /= fkt;
SerWrite("bias: 0.",8);
Msleep(100);
PrintInt(p1);
SerWrite("\n\r",2);

p2 = 1000*fkt/p2;
SerWrite("slope: ",7);
Msleep(100);
PrintInt(p2);
SerWrite(".",2);
PrintInt((int)((p2-(int)p2)*10.0+0.5));
SerWrite("\n\r",2);

while (1);
return 0;
}


Das Prg spuckt zwei Werte aus: bias b (bei mir 0.995) und slope s (die Steigung der Gerade, bei mir 61.0).

5) Zum Schluß wird die Return-Zeile noch korrigiert mit:


return ((unsigned char) ((( 1023.0/(float)i - 0.995)) * 61.0 + 0.5));


Mit diesem Feintuning habe ich alle 64 Werte richtig. Probiert habe ich mit und ohne Motor eingeschalten. Hier ist noch das Testprg. Es gibt die Messwerte und die transf. Werte 1 bis 63 aus.


#include "asuro.h"

/* function to read out switches */
unsigned int testSwitch (void)
{ unsigned int i;
DDRD |= SWITCHES; // Switches as Output
SWITCH_ON; // Output HIGH for measurement
ADMUX = (1 << REFS0) | SWITCH; // AVCC reference with external capacitor
Sleep(10);

ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF)));// wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
i = ADCL + (ADCH << 8);

SWITCH_OFF;
Sleep(5);
return (int)(1023000L/(long)i);
}

int main(void)
{
Init();
StatusLED(OFF);

SerWrite("\n\rtest switch:\n",15);
StatusLED(GREEN);

while(1) {
int j;
long sum = 0;
SerWrite("\n\r",2);
MotorDir(FWD,FWD);
MotorSpeed(150,150);
while (!PollSwitch());
Msleep(100);
for (j = 0; j < 100; j++)
sum += testSwitch();

int sw1,sw2;
do {
sw1 = PollSwitch();
sw2 = PollSwitch();
} while (sw1 != sw2);

PrintInt((int)(sum/100.0)+0.5);
SerWrite(" ",2);
Msleep(200);
PrintInt(sw1);
if (sw1 & 0x7)
MotorDir(RWD,RWD);
else
MotorDir(FWD,FWD);
MotorSpeed(150,150);
Msleep(500);
}
return 0;
}


Ich hoffe, dass diese codes hilfreich sind. Falls jemand einen Fehler entdeckt, bitte melden. Wenn jemand sich interessiert, kann ich auch kurz erläutern, wie das lin. Ausgleichsproblem analytisch gelöst wird (auf die Frage, wieso sieht die 2x64-Matrix A so aus).

Felix

smuller
19.05.2006, 10:28
Die Lösung mit der Modifikation der Return-Zeile in Funktion PollSwitch finde ich zwar brauchbar, sie bleibt aber meiner Meinung nach eine Quick&Dirty-Lösung.

Ja, mehr sollte das im Moment auch nicht sein. Ich werde deine Lösung mal testen. Etwas unschön finde ich, das die Entwickler diese Fehler in Kauf genommen haben. Bauteiltoleranzen sind zwar da, aber nicht so groß, das man sie nicht von Anfang an Softwaremäßig ausgleichen könnte.