PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Frage zu den Tastern bzw. die Position in einer Schleife



Peacecamper
27.05.2007, 12:30
Hallo,

ich habe hier folgendes Linienprogramm, das den Asuro über zwei schwarze Linien außen und eine weiße in der Mitte leiten soll. Das funktioniert soweit auch. Nun möchte ich, dass der Asuro bei einer Kollision mit einem Hindernis anhält. Leider weiß ich genau, wo diese Abfrage in das Programm rein muss, vielleicht ist sie auch falsch formuliert, jedenfalls funktioniert es nicht.

Hier das Programm:
#include "asuro.h"

#define dunkel 50
#define rechts 1
#define links 0

void warte (int s)
{
int x = 0;
for (x = 0; x <s; x++) Sleep(72);
}

int main(void)
{

Init();
unsigned int Licht[2];
int white;
FrontLED(ON);
warte(1000);
LineData(Licht);
white = (Licht[links]+Licht[rechts])/2-60;
MotorDir(FWD,FWD);
MotorSpeed(180,180);
int i = 0;

while (1)
{

LineData(Licht);
MotorSpeed(180,180);
if(PollSwitch()>0)
{
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
}
while (Licht[links] > white && Licht[rechts] > white)
{
MotorDir(FWD,FWD);
LineData(Licht);
}
MotorSpeed(180,180);
while (Licht[links] < white)
{
MotorDir(FWD,BREAK);
LineData(Licht);
while (Licht[rechts] < white)
{
MotorSpeed(255,180);
LineData(Licht);
while (Licht[links] > white)
{
MotorSpeed(255,180);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
MotorSpeed(180,180);
while (Licht[rechts] < white)
{
MotorDir(BREAK,FWD);
LineData(Licht);
while (Licht[links] < white)
{
MotorSpeed(180,255);
LineData(Licht);
while (Licht[rechts] > white)
{
MotorSpeed(180,255);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
}
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);


return 0;

}


Schon mal Danke im Voraus. O:)

damaltor
27.05.2007, 16:30
BITTE NICHT PUSHEN. schon gar nicht nach 3 stunden.

dien programm sieht ok aus, bis darauf dass die funktion Init(); UNTER die variablendeklaration muss.

was funktioniert nicht? das kompilieren? der ablauf? was macht der asuro? "geht nicht" ist nichtgenau genug.

ehenkes
27.05.2007, 17:01
Bau zu Diagnosezwecken noch LEDs ein, damit Du weißt, ob alle Zweige erreicht werden, z.B.:



if (PollSwitch()>0)
{
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
BackLED(ON,ON); // nur zu Diagnosezwecken
}

Peacecamper
27.05.2007, 17:22
BITTE NICHT PUSHEN. schon gar nicht nach 3 stunden.

dien programm sieht ok aus, bis darauf dass die funktion Init(); UNTER die variablendeklaration muss.

was funktioniert nicht? das kompilieren? der ablauf? was macht der asuro? "geht nicht" ist nichtgenau genug.

Die Kollisionsabfrage, sprich er reagiert nicht, wenn die Taster gedrückt werden.

radbruch
27.05.2007, 17:33
So in der Art funktioniert PollSwitch():


#include "asuro.h"

char sw0, sw1;

void warte (int s)
{
int x = 0;
for (x = 0; x <s; x++) Sleep(72);
}

int main(void)
{
Init();
sw0=PollSwitch();

while (1)
{
sw1=sw0;
sw0=PollSwitch();
//PrintInt(sw0);
if ((sw0 == 0) && (sw1 == 0))
{
StatusLED(GREEN);
MotorDir(FWD,FWD);
MotorSpeed(180,180);
//FolgeDerLinie();
} else {
StatusLED(RED);
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
warte(100);
MotorDir(RWD,RWD);
MotorSpeed(150,180);
warte(500);
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
warte(100);
sw0=PollSwitch();
}

}
return 0;

}


Du solltest deine while-Anweisungen teilweise gegen if-Abfragen ersetzen, weil das Programm sonst gelegentlich festhängt.

Gruß

mic

Peacecamper
27.05.2007, 17:44
Mh, jetzt sieht das ganze so aus und nach dem Anmachen leuten nur noch die beiden hinteren LEDS und die vordere neben dem Powerswitch:


#include "asuro.h"

#define dunkel 50
#define rechts 1
#define links 0

void warte (int s)
{
int x = 0;
for (x = 0; x <s; x++) Sleep(72);
}

int main(void)
{

unsigned int Licht[2];
int white;
FrontLED(ON);
warte(1000);
LineData(Licht);
white = (Licht[links]+Licht[rechts])/2-60;
MotorDir(FWD,FWD);
MotorSpeed(180,180);
int i = 0;
Init();

while (1)
{

LineData(Licht);
MotorSpeed(180,180);
if(PollSwitch()>0)
{
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
BackLED(ON,ON);
}
while (Licht[links] > white && Licht[rechts] > white)
{
MotorDir(FWD,FWD);
LineData(Licht);
}
MotorSpeed(180,180);
while (Licht[links] < white)
{
MotorDir(FWD,BREAK);
LineData(Licht);
while (Licht[rechts] < white)
{
MotorSpeed(255,180);
LineData(Licht);
while (Licht[links] > white)
{
MotorSpeed(255,180);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
MotorSpeed(180,180);
while (Licht[rechts] < white)
{
MotorDir(BREAK,FWD);
LineData(Licht);
while (Licht[links] < white)
{
MotorSpeed(180,255);
LineData(Licht);
while (Licht[rechts] > white)
{
MotorSpeed(180,255);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
}
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);


return 0;

}

damaltor
27.05.2007, 19:52
Das Problem mit pollswitch ist, dass die werte manchmal falsch sind - allerdings sind sie zu hoch.
dei originales programm war zwar absolut korrekt, aber irgendwie hat pollswitch nichts ergeben. der ansatz von radbruch schliesst zwr die fehler durch zu hohe werte (fast) immer aus, aber bei dir scheint der wert immer null zu sein, sonst würde er ja anhalten. das wird dir nich helfen.

flashe mal folgendes programm



#include "asuro.h"

int main(void){
int radix=10;
int poll=0;
char wert[3];

Init();

while(1){

poll=PollSwitch();
itoa(poll,wert,radix);
SerWrite(wert,3);
SerWrite("\n\r",2);

}
}


hoffe das das so funktioniert, kanns grade nicht testen. wer weiss was falsch ist bitte schreiben!

dieses programm sollte dir in hyperterminal den aktuellen pollswitch wert ausgeben. die werte der taster müssten der reihe nach 1,2,4,8,16 und 32 sein. wenn mehrere taster gedrückt werden, müsste die summe der werte ankommen. wird kein taster gedrückt müsste 0 ausgegeben werden. was kommt bei dir?

ehenkes
27.05.2007, 21:49
Das Programm funktioniert gut.

Meine Werte an einem ASURO sind z.B.:
keine Taste: 4
von links nach rechts (von vorne gesehen):
5, 6, 4 (???), 12, 20, 32

Was ist da falsch? (die dritte Taste scheint "tot" zu sein, es ist aber ein 16K Widerstand eingelötet, seltsam)

ehenkes
27.05.2007, 21:55
Kleine Schönheitsergänzung zum Programm:


#include "asuro.h"

int main(void)
{
int radix = 10;
int poll = 0;
char wert[3];

Init();

while(1)
{

poll = PollSwitch();
int i;
for(i=0;i<3;++i)
wert[i]=' ';
itoa (poll, wert, radix);
SerWrite (wert, 3);
SerWrite ("\n\r", 2);

}
}

damaltor
28.05.2007, 09:32
oh oh... das ist grütze. probiere es noch ein bisschen und schau obs immer die gleichen werte werden.

radbruch
28.05.2007, 11:27
Hallo

Wir sollten mal einen allumfassenden Tastenbeitrag im Wiki verfassen. Vieles wurde hier dazu schon geschrieben, aber finden kann man's leider nicht mehr so einfach. [Beispiel (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=268667)]

Hier eine alternative Tastenabfrage (gepostet von asuro-henk im arexx-Forum (http://www.arexx.com/forum/viewtopic.php?p=1323#1319)):

if(!(PINC & (1<<PC4)))

Es wird nur geprüft, ob überhaupt eine Taste gedrückt wurde.

Gruß

mic

Peacecamper
28.05.2007, 13:40
dien programm sieht ok aus, bis darauf dass die funktion Init(); UNTER die variablendeklaration muss.



Negativ, dann geht gar nichts mehr, das war das eine Problem mit den nur noch leuchtenden LEDs. Dein Programm zu den Tastern funktioniert, es werden auch die richtigen Werte ausgegeben.

Aber auch die zuletzt gepostete Funktion funktioniert in meinem Programm nicht, irgendwie habe ich den Verdacht, dass ich die an die falsche Stelle setze, kann das nochmal jemand überprüfen?

Ich habe das jetzt aus Gag nochmal umpositioniert, half aber auch nicht.
Also jetzt sieht das Ganze so aus:


#include "asuro.h"

#define dunkel 50
#define rechts 1
#define links 0

void warte (int s)
{
int x = 0;
for (x = 0; x <s; x++) Sleep(72);
}

int main(void)
{

Init();
unsigned int Licht[2];
int white;
FrontLED(ON);
warte(1000);
LineData(Licht);
white = (Licht[links]+Licht[rechts])/2-60;
MotorDir(FWD,FWD);
MotorSpeed(180,180);
int i = 0;


while (1)
{

LineData(Licht);
MotorSpeed(180,180);
while (Licht[links] > white && Licht[rechts] > white)
{
MotorDir(FWD,FWD);
LineData(Licht);
}
MotorSpeed(180,180);
while (Licht[links] < white)
{
MotorDir(FWD,BREAK);
LineData(Licht);
while (Licht[rechts] < white)
{
MotorSpeed(255,180);
LineData(Licht);
while (Licht[links] > white)
{
MotorSpeed(255,180);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
MotorSpeed(180,180);
while (Licht[rechts] < white)
{
MotorDir(BREAK,FWD);
LineData(Licht);
while (Licht[links] < white)
{
MotorSpeed(180,255);
LineData(Licht);
while (Licht[rechts] > white)
{
MotorSpeed(180,255);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
}
if(!(PINC & (1<<PC4)))
{
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
BackLED(ON,ON);
}


return 0;

}

radbruch
28.05.2007, 14:50
Das wird so nichts werden. Um zu erkennen, ob während der Fahrt eine Taste gedückt wird, muss man den Tastenstatus im Programm auch einlesen. Wenn dein Programm also in einer while-Schleife ala

while (Licht[links] < white)

hängt und Licht[links] nie kleiner als white wird, wird auch nie etwas anderes gemacht, also auch kein PollSwitch(). Kein Einlesen der Tasten bedeutet eben auch, keine Reaktion auf Tasten.

Du könntest nun alle while-Schliefen um ein zusätzliches Ende per Tastendruck ergänzen, oder du überdenkst deinen Code nochmals komplett und trennst dich von deinen vielen Whiles.

Der Einbau der Tastenabfrage (keine Taste: Linienfolgen; Taste: Stopp) in deinen Code würde etwa so aussehen:


#include "asuro.h"

#define dunkel 50
#define rechts 1
#define links 0

void warte (int s)
{
int x = 0;
for (x = 0; x <s; x++) Sleep(72);
}

int main(void)
{

Init();
unsigned int Licht[2];
int white;
FrontLED(ON);
warte(1000);
LineData(Licht);
white = (Licht[links]+Licht[rechts])/2-60;
MotorDir(FWD,FWD);
MotorSpeed(180,180);
//int i = 0;


while (1)

/* Abfrage der Tasten 1
Wenn (PINC & (1<<PC4)) == true dann keine Taste gedrückt
Es wird dann die grüne StatusLED eingeschaltet und der Linie gefolgt

Durch die verschachtelten while-Anweisungen kommt das Programm aber
aus manche Stellen der Liniensuche nicht mehr raus, so dass weitere
Tastenabfragen nur in Abhängigkeit der Liniesitiation erfolgen.
*/

if (PINC & (1<<PC4))

{
StatusLED(GREEN);

LineData(Licht);
MotorSpeed(180,180);
while (Licht[links] > white && Licht[rechts] > white)
{
MotorDir(FWD,FWD);
LineData(Licht);
}
MotorSpeed(180,180);
while (Licht[links] < white)
{
MotorDir(FWD,BREAK);
LineData(Licht);
while (Licht[rechts] < white)
{
MotorSpeed(255,180);
LineData(Licht);
while (Licht[links] > white)
{
MotorSpeed(255,180);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
MotorSpeed(180,180);
while (Licht[rechts] < white)
{
MotorDir(BREAK,FWD);
LineData(Licht);
while (Licht[links] < white)
{
MotorSpeed(180,255);
LineData(Licht);
while (Licht[rechts] > white)
{
MotorSpeed(180,255);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
}

/* Abfrage der Tasten 2
Bei gedrückter Taste wird dann der folgende Code ausgeführt, vorrausgesetzt,
beim Linienfolgen wurde die Kette der while-Anweisungen durchlaufend und der
neue Status der Tasten wird eingelesen.
*/

else

{
StatusLED(RED);
}

return 0;

}

Gruß

mic

Peacecamper
28.05.2007, 15:15
So, das klappt jetzt, vielen Dank.

Hier der endgültige Quellcode:


#include "asuro.h"

#define dunkel 50
#define rechts 1
#define links 0

void warte (int s)
{
int x = 0;
for (x = 0; x <s; x++) Sleep(72);
}

int main(void)
{

Init();
unsigned int Licht[2];
int white;
FrontLED(ON);
warte(1000);
LineData(Licht);
white = (Licht[links]+Licht[rechts])/2-60;
MotorDir(FWD,FWD);
MotorSpeed(180,180);



while (1)


if (PINC & (1<<PC4))
{
StatusLED(GREEN);

LineData(Licht);
MotorSpeed(180,180);
while (Licht[links] > white && Licht[rechts] > white)
{
MotorDir(FWD,FWD);
LineData(Licht);
}
MotorSpeed(180,180);
while (Licht[links] < white)
{
MotorDir(FWD,BREAK);
LineData(Licht);
while (Licht[rechts] < white)
{
MotorSpeed(255,180);
LineData(Licht);
while (Licht[links] > white)
{
MotorSpeed(255,180);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
MotorSpeed(180,180);
while (Licht[rechts] < white)
{
MotorDir(BREAK,FWD);
LineData(Licht);
while (Licht[links] < white)
{
MotorSpeed(180,255);
LineData(Licht);
while (Licht[rechts] > white)
{
MotorSpeed(180,255);
LineData(Licht);
}
}
MotorSpeed(180,180);
}
}

else

{
StatusLED(RED);
MotorDir(BREAK,BREAK);
MotorSpeed(0,0);
}

return 0;

}

radbruch
28.05.2007, 15:18
Na wunderbar. O:)

Peacecamper
29.05.2007, 16:02
Mh, aus irgendeinem Grund reagiert er nur manchmal auf die Taster... :-k

radbruch
29.05.2007, 16:38
...weil dein Programm in einer while-Schleife festhängt.

Peacecamper
29.05.2007, 16:59
...weil dein Programm in einer while-Schleife festhängt.

Also einfach die whiles durch ifs ersetzen?

radbruch
29.05.2007, 17:30
Naja, so einfach ist das nicht. Du must dazu dein Program ziemlich komplett umbauen. Dann allerdings würden z.B. auch deine vielen LineData()-Aufrufe verschwinden.

Als Anregung mal meine Anfänge aus einem älteren Thread (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=28103):


#include "../inc/asuro.h"
#include "../inc/asuro.c"

#define schwelle 15
#define power 175

unsigned char pow_l, pow_r, dir_l, dir_r;
unsigned int data[2], suchen;
unsigned int h_l, h_r, d_l, d_r;

int main(void) {

Init();
FrontLED(ON);
dir_l=dir_r=FWD;
pow_l=pow_r=power;
d_l=d_r=0;
h_l=h_r=1023;
MotorDir(dir_l,dir_r);
MotorSpeed(pow_l,pow_r);
suchen=0;

do{
LineData(data);
BackLED(OFF,OFF);
if ((data[0]-schwelle < d_l) && (data[1]-schwelle < d_r)) {
dir_l=dir_r=FWD;
pow_l=255-data[0];
pow_r=255-data[1];
suchen=0;
StatusLED(GREEN);
BackLED(ON,ON);
} else {
if (data[1]-schwelle > data[0]) {
pow_l=0;
pow_r=power;
d_l=(d_l+data[0])/2;
h_r=(h_r+data[1])/2;
suchen=1;
StatusLED(YELLOW);
BackLED(OFF,ON);
}
if (data[0]-schwelle > data[1]) {
pow_l=power;
pow_r=0;
h_l=(h_l+data[0])/2;
d_r=(d_r+data[1])/2;
suchen=1;
StatusLED(YELLOW);
BackLED(ON,OFF);
}
if (suchen==1) {
if ((h_l-schwelle < data[0]) && (h_r-schwelle < data[1])) {
StatusLED(RED);
if (pow_l==0) { dir_l=RWD; pow_l=power; }
if (pow_r==0) { dir_r=RWD; pow_r=power; }
}
suchen=2;
}

}

MotorDir(dir_l,dir_r);
MotorSpeed(pow_l,pow_r);

}while (1);
return 0;
}

Damit macht mein asuro das:
http://popen.pop3.ru/asuro/linie2.gif (http://www.youtube.com/watch?v=-kfi3EqBAcM)
Bild anklicken für youtube-Video
mit wirklicher Geschwindigkeit


Gruß

mic

Peacecamper
29.05.2007, 19:03
Mh.. irgendwie steige ich da nicht durch...

ehenkes
29.05.2007, 19:40
Grütze? Jawohl, bei einem fertig gekauften ASURO waren zwei Widerstände (R28 u. R15) falsch über Kreuz gesteckt. Nach einer längeren Entlöt- und Neueinsteckaktion (was ein Gefummel) sieht alles bestens aus: 1,2,4,8,16,33
Ist das so o.k. mit den 33?

Ein selbst zusammen gelöteter ASURO funktionierte auf Anhieb, aber ergab auch diese Zahlen wie oben, also die 33.

radbruch
29.05.2007, 19:48
Hihi, so ähnlich geht's wohl jedem der fremden, natürlich gewachsenen Code begutachtet.

Grobe Funktionsbeschreibeung:
Die eigentliche "Hauptschleife" steht zwischen do ... while. Zuerst werden die Line-Data gelesen und die BackLEDs ausgemacht. Dann erfolgen per If-Abfrage die Ermittlung der Position auf der Linie und die erforderlichen Reaktionen für MotorSpeed und MotorDir werden ermittelt (dir_l/dir_r und pow_l/pow_r). Zusätzlich werden je nach Reaktion auch die BackLEDs wieder eingeschaltet. Am Ende der Schleife werden die ermittelten Werte an die Motoren übergeben und die Schleife startet erneut. Bei jedem Schleifendurchgang werden so die Reaktionen auf die Linienabweichung neu berechnet.

Wenn der asuro die Linie komplett verlassen sollte, merkt sich "suchen", wohin die Linie verschwunden ist und der asuro dreht zurück, bis er sie wieder findet.

In h_l/d_l bzw h_r/d_r speichere ich die max. bzw. min. Werte die gemessen werden. Es wird dabei ein Mittelwerte mit dem letzten gespeicherten min/max-Wert gebildet um Ausreiserwerte zu dämpfen. Auch diese Werte werden bei jedem Schleifendurchgang aktuallisiert.

In solch einen Programmablauf kann man nun überall noch was anhängen, sei es eine Tastenabfrage, eine IR-Abstandsmessung oder was einem noch so einfällt.

Natürlich gibt es für verschiedene Aufgabenstellungen genausoviele Lösungsprogramme wie es Programmierer gibt. Mein Beispielcode soll dir nur mal zeigen, wie man die while-Schleifen loswerden kann. Am meisten lernt man selbst, wenn man sich die Codes der anderen anschaut und sich das Beste daraus selbst aneignet...

@ehenkes:
nein, ist nicht ok. Die Summe aller Taster sollte 63 sein, dann ist es ok. Jeder Taster wird dann genau durch ein Bit im Ergebniss von PollSwitch() abgebildet. (Musterthread Tasterkalibrierung (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=26648))

Gruß

mic

damaltor
29.05.2007, 22:35
die 33 ist nicht ganz so super. ist es immer 33 oder auch manchmal/meistens/gelegentlich 32?

der vorteil der exakten zahlen ist, dass man binär ausgedrückt folgende zahlenwerte erhält:

0b00000001 = 1
0b00000010 = 2
0b00000100 = 4
0b00001000 = 8
0b00010000 = 16
0b00000000 = 32

werden also mehrere taster gleichzeitig gedrückt, so bekommt man die summe:

0b00010101 = 16 + 4 + 1

die 33 allerdings ergibt das hier:
0b00100001 = 32+1 sieht also so aus wie wenn beide äusseren taster gedrückt wurden.

ehenkes
29.05.2007, 22:48
0b00000001 = 1
0b00000010 = 2
0b00000100 = 4
0b00001000 = 8
0b00010000 = 16
0b00100000 = 32

damaltor
30.05.2007, 09:52
shit, vertippt... ;) naja das prinzip ist ja klar. du kannst mal den widerstand der in reihe zum entsprechenden taster geschaltet ist (siehe schaltplan) durchmessen mit dem multi (vorher asuro abschalten) und mit dem eigentlich u erwartenden wert vergleichen.