PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Asuro Programmierung



Berghuhn
11.10.2010, 17:55
Hallo,
Ich wollte ein paar Messungen mit den Linienensensoren meines ASURO'S machen und sie dann über die IR Schnittstelle an den PC senden.
Nun klappt das mit dem Convertieren nicht so ganz.

hier mal mein code:



#include "asuro.h"
#include <stdlib.h>

int main (void)
{

unsigned int lData[2];
unsigned char Wert;
Init();

for(;;)
{

FrontLED(ON);
LineData(lData);
itoa(lData[1],Wert,10);
SerWrite(Wert,4);

}
return 0;
}


Ich habe die stdlib.h auch in dem gleichen Ordner wie die anderen Dateien auch.
Danke schonmal im vorraus für eure Hilfe!

Valen
11.10.2010, 19:27
Hallo,
Ich wollte ein paar Messungen mit den Linienensensoren meines ASURO'S machen und sie dann über die IR Schnittstelle an den PC senden.
Nun klappt das mit dem Convertieren nicht so ganz.

hier mal mein code:



#include "asuro.h"
#include <stdlib.h>

int main (void)
{

unsigned int lData[2];
unsigned char Wert;
Init();

for(;;)
{

FrontLED(ON);
LineData(lData);
itoa(lData[1],Wert,10);
SerWrite(Wert,4);

}
return 0;
}


Ich habe die stdlib.h auch in dem gleichen Ordner wie die anderen Dateien auch.
Danke schonmal im vorraus für eure Hilfe!
unsigned char Wert;

ist einer Deklaration von nur einen Zeichen. Damit es mit SerWrite ausgesendet werden kann muss es ein Zeichenketten sein, sehe:

http://www.rn-wissen.de/index.php/C-Tutorial#Strings_.28Zeichenketten.29

Gab es kein Kompilation Fehler bis jetzt? Nächste versuch bitte diese dann auch posten.

Berghuhn
11.10.2010, 19:36
Nein, es gab keinen Kompilations Fehler.
Danke er sendet jetzt zumindest Zahlen =).
Jetzt aber nochmals ein Problem bei mir Funktioniert der Befehlt Msleep(); nicht. Hast du vllt eine Idee warum?

Valen
11.10.2010, 19:38
Welches Asuro Code-Bibliothek (asuro.c) verwendest du? In dem Original Bibliothek gibt es keine Msleep Funktion. Das gibt es nur in dem Erweiterte Asuro Bibliotheken.

Außerdem muss noch ein wert zwischen den Krumme Klammern.

markusj
11.10.2010, 19:39
Hallo,

Was hast du mit der stdlib.h gemacht? Normalerweise lässt du die schön in Ruhe im WinAVR-Ordner, das sind Headerfiles an denen du NICHTS ändern musst/sollst.
Davon abgesehen: Der Code oben compiliert bei mir problemlos (Aber nicht ohne Warnings -> Beheben). Du solltest nicht nur schreien wenn du Schmerzen hast, wenn du uns verrätst was wehtut würde das weiterhelfen.

Daher: Gehe zurück auf Los, ziehe keine 4000$ ein, verfasse eine vernünftige Fehlerbeschreibung und gib alle Fehlermeldungen mit an.

mfG
Markus

Berghuhn
13.10.2010, 19:49
Ok das mit dem Msleep(zeit); hat sich geklärt, da ich noch die Standart lib hatte.

Nun mein neues Problem:



#include "asuro.h"
#include <stdlib.h>


void Msleep(int dauer)
{
int z;
for(z=0;z<dauer;z++) Sleep(72);
}

unsigned int zaehler;
unsigned int zaehler2;
unsigned char ir1;

int main (void)
{

unsigned int lData[2];
unsigned int oData[2];
unsigned int oldO1;
unsigned int oldO2;

unsigned char sw, speed;
unsigned char ir;

unsigned char ir2;

Init();
OdometrieData(oData);
oldO1 = oData[0] + 500;
oldO2 = oData[1] + 500;
DDRD |= (1 << DDD1); // Port D1 als Ausgang
PORTD &= ~(1 << PD1); // PD1 auf LOW
OCR2 = 0xFC;
speed=130;
for(;;)
{
ir=PIND & (1 << PD0);
FrontLED(ON);
LineData(lData);
OdometrieData(oData);
if (ir || ir1)
{
if(lData[1] <= 50 && lData[1] >= 10)
{
BackLED(ON,ON);
StatusLED(GREEN);
MotorDir(RWD, RWD);
MotorSpeed(190, 190);
Msleep(500);
MotorDir(BREAK, RWD);
MotorSpeed(0, 150);
Msleep(500);

}
else if (PollSwitch() != 0)
{
Sleep(281);
if(PollSwitch() != 0)
{
BackLED(ON,ON);
StatusLED(GREEN);
MotorDir(RWD, RWD);
MotorSpeed(150, 150);
Msleep(1000);
MotorDir(BREAK, RWD);
MotorSpeed(0, 150);
Msleep(500);
}
else
{
FrontLED(ON);
BackLED(OFF,OFF);
StatusLED(RED);
MotorDir(FWD, FWD);
MotorSpeed(130, 130);
}
}
else
{
FrontLED(ON);
BackLED(OFF,OFF);
StatusLED(RED);
MotorDir(FWD, FWD);
MotorSpeed(130, 130);
}
if(oData[0] >= oldO1 - 1 && oData[0] <= oldO1 + 1)
{
zaehler++;
if(zaehler >= 100)
{
zaehler = 0;
BackLED(ON,ON);
StatusLED(GREEN);
MotorDir(RWD, RWD);
MotorSpeed(150, 150);
Msleep(750);
MotorDir(BREAK, RWD);
MotorSpeed(0, 150);
Msleep(400);
}
}
else
{
zaehler = 0;
oldO1 = oData[0];
}


if(oData[1] >= oldO2 - 1 && oData[1] <= oldO2 + 1)
{
zaehler2++;
if(zaehler2 >= 100)
{
zaehler2 = 0;
BackLED(ON,ON);
StatusLED(GREEN);
MotorDir(RWD, RWD);
MotorSpeed(150, 150);
Msleep(800);
MotorDir(BREAK, RWD);
MotorSpeed(0, 150);
Msleep(400);
}
}
else
{
zaehler2 = 0;
oldO2 = oData[1];
}
}
else
{
BackLED(ON,ON);
MotorDir(RWD,RWD);
MotorSpeed(speed,speed);
if (speed > 0) Msleep(500);
MotorDir(BREAK,RWD);
MotorSpeed(0,speed);
if (speed > 0) Msleep(500);
}



ir1=ir;
ir2=ir1;

sw = PollSwitch();

if (sw & 0x04)
{
OCR2 = 0xFC;
}
if (sw & 0x08)
{
OCR2 = 0xFB;
}

}
return 0;
}


Also der ASURO sollte eine Tischkante erkennen, was auch funktioniert (das tut er leider auch bei schwarz).
Zudem sollten die Taster überprüft werden, was auch funktioniert.
Er sollte auch noch über IR-Sensoren gegenstände schon aus der entfernung erkennen und merken wann ein Rad stehen bleibt(wenn er hängt), über die Odometriesensoren, was beides leider nicht funktioniert.

Es kommt eine Warnung bei mir und zwar folgende:

test.c:58: warning: large integer implicitly truncated to unsigned type

Was aber nichts damit zu tun haben sollte, dass dies nicht funktioniert.

Danke schonmal im vorraus.

radbruch
13.10.2010, 20:02
Sleep(281);

Maximalwert für Sleep() ist 255.

Berghuhn
13.10.2010, 20:05
ou :D
danke ^^
haste auch ne idee warum das nicht funktioniert liegt nicht daran.

Valen
13.10.2010, 22:15
Ob das den Komplete lösung ist weiss ich nicht aber du verwendest den BackLEDs zusammen mit Odometrie messungen. Die gehen nicht zusammen weil es den gleichen Ports am Atmega8 Chip Benutzt, aber in unterschiedliche Schaltzustanden. Also, BackLEDS anruffen raus, oder kein Odometrie verwenden.

Valen
14.10.2010, 00:31
...
if(oData[0] >= oldO1 - 1 && oData[0] <= oldO1 + 1)
...
if(oData[1] >= oldO2 - 1 && oData[1] <= oldO2 + 1)Diese beide abfragen sind nur True bei Stillstand der Rädern. (genauer gesagt: die Helligkeit oData[0/1] soll gleich hell/dunkel sein plus/minus 1 ADC wert als die letzte Messung) Aber dein Asuro kann kaum Stillstehen mit dein Programm. Was hast du vor mit diesen code (mit zaehler1 und zaehler2 usw.) Bitte erkläre die Kondition die du erfassen und zahlen möchtest.

Berghuhn
14.10.2010, 14:54
Ja ich wollte überprüfen ob der Wert jetzt dem Wert davor mit der toleranz von + - 1 entspricht. Da das auch mal sein kann, dass der Asuro beim fahren die 2 gleichen Werte bekommt wollte ich mit dem zaehler hochzählen. Wenn es dann 100 mal der gleiche wert ist sollte er umdrehen weil er da wahrscheinlich stecken geblieben ist.
Hab das ganze jetzt mit dem Motorwiederstand gemacht und es geht ganz gut. Es kommen aber manchmal noch "Fehlalarme" aber da muss ich noch ein bisschen mit den Werten spielen.

Mir ist jetzt aber aufgefallen dass wenn jetzt alles funktioniert der Asuro ziemlich ausgelastet ist. Er erkennt die Tischkante, aber oft einen kleinen wenig zu spät. Könnte das auch an der langsam leere Batterie liegen oder ist das weil er soviel zum arbeiten hat?

Valen
14.10.2010, 15:45
Hier ist den Verzögerung vermute ich. Wie oft passiert das, das kein IR Signal empfangen wird? Weil speed immer > 0 (einmal eingestellt mit 130, und keine änderung) ist wird er jeder Durchlauf (wann kein IR-Signal empfangen ist seit diesen Durchlauf und den vorherigen) einer halbe Sekunde warten


if (speed > 0) Msleep(500);

Valen
14.10.2010, 15:47
Hier ist den Verzögerung vermute ich. Wie oft passiert das, das kein IR Signal empfangen wird? Weil speed immer > 0 (einmal eingestellt mit 130, und keine änderung) ist wird er jeder Durchlauf (wann kein IR-Signal empfangen ist seit diesen Durchlauf und den vorherigen) einer halbe Sekunde warten


if (speed > 0) Msleep(500);

Double_A
14.10.2010, 15:57
Kann der überhaupt mit der 500 umgehen?
Asuro kann doch nur bis 255 rechnen... oder nicht?

Valen
14.10.2010, 16:02
In seinem Code für Msleep ist dauer definiert als int.

void Msleep(int dauer)

Deshalb kann dauer zwischen -32,768 bis 32,767 sein. Aber Sleep kann nur mit werten bis 255 arbeiten.

radbruch
14.10.2010, 16:10
Hallo


Da das auch mal sein kann, dass der Asuro beim fahren die 2 gleichen Werte bekommt...Ist dir klar, dass die Odometrie-Werte keine Impulse sind sondern nur die vom Sensor gemessene Helligkeit bedeutet? Die mit OdometrieData() eingelesenen Werte schwanken deshalb auch im Stillstand.

Der Werteverlauf (ohne Fremdlichteinflüsse) bewegt sich nahezu sinusförmig zwischen min- und Maxwert. Die Kunst bei der Odometrie besteht nun darin, aus diesen Werten einen Flankenwechsel zu erkennen. Ansätze und umfangreiche Diskussionen (teilweise mit sehr aufschlussreichen Diagrammen) gibt es schon ein paar hier im Forum. Um so eine Stillstandserkennung zu Programmieren benötigt man leider schon etwas höhere Weihen:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=49901

Eine Programmgrenze sehe ich hier:


else if (PollSwitch() != 0)
{
Sleep(255);
if(PollSwitch() != 0)
{


Wenn PollSwitch() "Störungen" einfängt, wird jedesmal eine Sleep(255)-Pause eingefügt.

Effektiver wäre folgender Ansatz für PollSwitch():

#include "asuro.h"

char t1, t2;

int main (void)
{
t1=0; // mit "keine Taste" vorbelegen
while(1)
{
t2=t1; // alten Wert der Tasten merken
t1=PollSwitch(); // aktuellen Wert einlesen
// t1=PollSwitch(); // eventuell nötig damit der ADC sauber umschalten kann

if(t1 && t1==t2) // nur wenn Taste gedrückt und beide Werte gleich sind
{
// Ab hier stehen dann alle Tastenfunktionen:
// if(t1==1 // K6
// if(t1==32 // K1
// if(t1||&b111000) // K4 oder K5 oder K6
}

// Linienabfrage

// Odometrie

// und was sonst noch nötig ist.
}
return 0;
}Dafür gibt es aber auch andere Lösungsansätze.

Gruß

mic

Berghuhn
14.10.2010, 23:12
So habe das mit den Tastern verbessert.
Der ganze Code sieht jetzt in etwa so aus:





#include "asuro.h"
#include <stdlib.h>

unsigned char ir1;

#define PWM_STEP 5
#define MESSZEIT 500 //ms
#define FULL_L 130
#define FULL_R 130

/* Motor vorwärts */
void MotorFwd(void)
{
MotorDir(FWD,FWD);
MotorSpeed(FULL_L,FULL_R);
}

/* Motor rückwärts */
void MotorRwd(void)
{
MotorDir(RWD,RWD);
MotorSpeed(FULL_L,FULL_R);
}

/* Motor rückwärts Links */
void MotorRwdL(void)
{
MotorDir(RWD,RWD);
MotorSpeed(FULL_L,0);
}

/* Motor rückwärts Rechts */
void MotorRwdR(void)
{
MotorDir(RWD,RWD);
MotorSpeed(0, FULL_R);
}

/* Motor stop */
void MotorStop(void)
{
MotorSpeed(0,0);
}

int main (void)
{

unsigned int lData[2];

unsigned char sw, speed;
unsigned char ir;
int t1, t2;
int u;
int Reibung_links;
int Reibung_rechts;
unsigned char ir2;


Init();
DDRD |= (1 << DDD1); // Port D1 als Ausgang
PORTD &= ~(1 << PD1); // PD1 auf LOW
OCR2 = 0xFB;
speed=130;
Encoder_Init();

for(;;)
{
ir=PIND & (1 << PD0);
FrontLED(ON);
LineData(lData);

if (PIND & (1 << PD0))
{
if(lData[1] <= 80 && lData[1] >= 10)
{
BackLED(ON,ON);
StatusLED(GREEN);
MotorDir(RWD, RWD);
MotorSpeed(190, 190);
Msleep(500);
MotorDir(BREAK, RWD);
MotorSpeed(0, 150);
Msleep(500);

}
else
{
FrontLED(ON);
BackLED(OFF,OFF);
StatusLED(RED);
MotorDir(FWD, FWD);
MotorSpeed(140, 140);
}

}
else
{
BackLED(ON,ON);
MotorDir(RWD,RWD);
MotorSpeed(speed,speed);
if (speed > 0) Msleep(500);
MotorDir(BREAK,RWD);
MotorSpeed(0,speed);
if (speed > 0) Msleep(500);
}



ir1=ir;
ir2=ir1;

sw = PollSwitch();

if (sw & 0x04)
{
OCR2 = 0xFC;
}
if (sw & 0x08)
{
OCR2 = 0xFB;
}

u=Batterie(); // u=922 entspricht 5.03V
Encoder_Set(0,0); // Messung starten
Msleep(500); // 500 ms Messen

Reibung_links = PWM*u*10/255-25*encoder[LEFT];
Reibung_rechts = PWM*u*10/255-25*encoder[RIGHT];

LineData(lData); // nochmals erneut prüfen ob er eine Tischkante erreicht hat,
//da er ja 0,5 Sekunden für das Messen gebraucht hat.

if(lData[1] <= 80 && lData[1] >= 10)
{
BackLED(ON,ON);
StatusLED(GREEN);
MotorDir(RWD, RWD);
MotorSpeed(190, 190);
Msleep(500);
MotorDir(BREAK, RWD);
MotorSpeed(0, 150);
Msleep(500);
}

if(Reibung_links >= 108 || Reibung_rechts >= 108) //Jetzt prüfen ob die Reibung den bestimmten Wert erreicht hat
{
BackLED(ON,ON);
StatusLED(YELLOW);
MotorDir(RWD, RWD);
MotorSpeed(150, 150);
Msleep(800);
MotorDir(BREAK, RWD);
MotorSpeed(0, 150);
Msleep(530);
}

t1 = PollSwitch();
t2 = PollSwitch();

if (t1 == 0 && t2 == 0)
{
MotorFwd(); /* vorwärts fahren */
FrontLED(ON);
BackLED(OFF,OFF);
}
else if (t1 && t2 && t1 == t2)
{
MotorStop();
if (t1 & 0x07) /* Tasten links gedrückt? */
{
MotorRwdL(); /* Rückwärtskurve links fahren */
FrontLED(OFF);
BackLED(ON,OFF);
}
if (t1 & 0x38) /* Tasten rechts gedrückt? */
{
MotorRwdR(); /* Rückwärtskurve rechts fahren */
FrontLED(OFF);
BackLED(OFF,ON);
}
Msleep(1000); /* 1 Sekunde fahren */
}
}
return 0;
}



Nun kommen aber noch 2 Warnungen:

test.c:136: warning: suggest parentheses around arithmetic in operand of |
test.c:137: warning: suggest parentheses around arithmetic in operand of |

in diesen Zeilen:

Reibung_links = PWM*u*10/255-25*encoder[LEFT];
Reibung_rechts = PWM*u*10/255-25*encoder[RIGHT];

Valen
15.10.2010, 00:06
Multiplikation und Teilungen haben eine höhere Priorität als Addieren und Subtraktion.

http://www.rn-wissen.de/index.php/C-Tutorial#Reihenfolge_der_Auswertung

Den Compiler gibt den Warnung das es möglich eine andere berechnungs-ordnung macht als du wünscht. Runde Klammern haben immer die Höchste Priorität. Ich empfehle dich auch den beiden seiten der || und && logische-stellungen im if-regeln mit runde Klammern zu trennen.

Berghuhn
15.10.2010, 07:04
Ok danke.
Das mit der Tischkante klappt nun auch wieder, nur wenn der Asuro schräg auf die Tischkante zufährt fällt er noch runter.
Hat jemand noch einen Verbesserungsvorschlag, damit das nicht passiert weil ich glaube nicht, dass man da sehr viel machen kann.