PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Asuro im Kreisbogen mit vorgebenen Radius fahren lassen



juelicher
24.02.2008, 12:50
Hallo zusammen ,
bin seit zwei Tagen dabei den Asuro im Kreisbogen fahrenzulassen,
Habe mit dem Programm aus Mehr Spaß mit Asuro Band 2 probiert,
gefällt mir nicht so richtig, weil der Trick mit dem doppelten zaehlen eines Rades nur für diesen Radius gilt.
Habe mir überlegt wenn ich den Asuro
um 5 Grad drehe und dann
um den Radius geteilt durch 9 eine Strecke fahrenlasse
dann wider um 5 Grad drehe und Strecke Radius/9 fahre entsteht ein Kreis, der zwar mit beliebiegen Radius ( ausprobiert von 200mm bis 400mm) gefahren wird.
Weil ich aber den GoTurn befehl zweimal ( einmal Drehen, dann fahre Strecke) aufrufe Ruckelt der Asuro sehr stark.

Hat jemand dieses Problem schon gelöst oder eine Idee wie ich das Ruckeln verhindern kann?

Gruß
Juelicher

juelicher
24.02.2008, 20:13
Hallo
Habe mal ein Programm versucht zu erstellen,

Macht aber nicht das was es soll.

Um Hilfe wird gebetten.

/*
Programm zum Kreisbogenfahren mit Radiusvorgabe
Radius geteilt durch neun ergibt zu fahrende Strecke.
Danach um 5° Grad drehen und wieder Radius/9 = Strecke fahren.
Mit einer Geschwindigkeit von 150 noch fest vorgegeben.
*/

#include <asuro.h>

int main(void)
{
Init();
EncoderInit();
StatusLED(GREEN);
// (distance,degree,speed)
//SerPrint ("Drehe um 85°\r");
GoTurnKreis ( 360, 180, 150); // Drehe um 5°

while (1) {}
return 0;
}

Die Funktion GoTurnKreis
ist
#include "asuro.h"
#include "myasuro.h"
void GoTurnKreis ( // Funktion soll einen Keisbogen fahen, indem um 5° drehen und Distance/9 fahren (wegen 10° schritten)
int distance, // Radius
int degree, // Winkel um 10 20 bis 360° drehen
int speed) // Geschwindigkeit
{
unsigned long enc_countdistance; // Vorgabewert der Ticks abhaengig von distance
unsigned long enc_countdegree; // Vorgabewert der Ticks abhaengig von degree
int tot_countdistance = 0; // ist Ticks linker Odometer abhaengig von distance
int tot_countdegree = 0; // ist Ticks linker Odometer abhaengig von degree
int diff = 0; // differenc Linker - Rechter Odometer
int l_speed = speed, r_speed = speed; // Geschwindigkeit Linker Motor und Rechter Motor
int i; // Laufvariable i fuer Winkel / 10 mal durchlaufen
int zyklus=degree/10; //
int drehdegree = 5; // Drehen um 5° Grad
/* calculate tics from mm */
enc_countdistance = abs (distance) * 10000L; // Vorzeischenlos um 10000 multiplizieren wegen berechnung in int als long
enc_countdistance /= MY_GO_ENC_COUNT_VALUE; // Korektur Werte meines Asuro
enc_countdistance /= 9L; // durch 9 wegen Kreisbogen
/* calculate tics from degree */
enc_countdegree = abs (drehdegree) * MY_TURN_ENC_COUNT_VALUE; // um rechnen in Ticks
enc_countdegree /= 360L;

/* stop the motors until the direction is set */
// MotorSpeed (0, 0); // Motoren stehen
for (i = 0; i < zyklus; i++) // Anzahl der Bewegungen degree durch 10 nur 10fache Werte vorgeben
{
//############### Asuro Radius /9 Strecke fahren ######################
StatusLED(GREEN);
l_speed = speed;
r_speed = speed;

if (distance < 0) // Fahrtrichtung bestimmen
{
MotorDir (RWD, RWD); // negative distance Rueckwaerts
}
else
{
MotorDir (FWD, FWD); // positive distance Vorwaerts
}
/* reset encoder */
EncoderSet (0, 0); // Vorgabewerte fuer Odometer
/* now start the machine */
MotorSpeed (l_speed, r_speed); // Motoren laufen mit Geschwindigkeit
while (tot_countdistance < enc_countdistance) // enc_count ist vorgabewert entweder Distance oder degree nicht beides
{
tot_countdistance += encoder [LEFT]; // Linkes Odometer wird gezaehlt
diff = encoder [LEFT] - encoder [RIGHT]; // zur Geschwindigkeitsregelierung
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;
}
}
/* reset encoder */
EncoderSet (0, 0);
MotorSpeed (l_speed, r_speed); // Geschwindigkeit setzen einstellen
Msleep (1);
}
//############### Asuro um 5° drehen in Uhrzeigersinn und gegen Uhrzeigersinn ######################
//StatusLED (RED);
l_speed = speed;
r_speed = speed;
if (degree < 0) // Drehrichtung bestimmen fuer 5° Grad
{
MotorDir (RWD, FWD); // wenn negativer Winkel gegen Uhrzeiger
}
else
{
MotorDir (FWD, RWD); // wenn positiver Winkel im Uhrzeiger
}
/* reset encoder */
EncoderSet (0, 0); // Vorgabewerte fuer Odometer
/* now start the machine */
MotorSpeed (l_speed, r_speed); // Motoren laufen mit Geschwindigkeit
while (tot_countdegree < enc_countdegree) // enc_count ist vorgabewert entweder Distance oder degree nicht beides
{
tot_countdegree += encoder [LEFT]; // Linkes Odometer wird gezaehlt
diff = encoder [LEFT] - encoder [RIGHT]; // zur Geschwindigkeitsregelierung
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;
}
}
/* reset encoder */
EncoderSet (0, 0);
MotorSpeed (l_speed, r_speed);
Msleep (1);
}
tot_countdistance = 0; // ist Ticks linker Odometer abhaengig von distance wird auf Null gesetzt fuer necksten Lauf
tot_countdegree = 0; // ist Ticks linker Odometer abhaengig von degree
diff = 0; // differenc Linker - Rechter Odometer
}
/* stop the motors until the direction is set */
MotorSpeed (0, 0); // Motoren stehen
MotorDir (BREAK, BREAK);
Msleep (200);
}

Habe die Funktion GoTurnKreis in asuro.h

void GoTurnKreis(int distance, int degree, int speed);
eingebunden.
im makefile auch


################################################## #############################
# Makefile for the project AsuroLib
################################################## #############################

## General Flags
PROJECT = AsuroLib
MCU = atmega8
TARGET = AsuroLib.elf
CC = avr-gcc.exe
AR = avr-ar
OBJDUMP = avr-objdump

## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall -gdwarf-2 -Os -I./inc
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d

## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0


## Objects that must be built in order to link
OBJECTS = globals.o adc.o encoder.o encoder_low.o i2c.o leds.o lcd.o\
motor.o motor_low.o print.o printf.o rc5.o sound.o switches.o\
time.o uart.o version.o encoderTest.o

## Objects explicitly added by the user
LINKONLYOBJECTS =

# Define directories, if needed. Geaendert auf C:/WinAVR-20071221 am 230208
DIRAVR = C:/WinAVR-20071221
#DIRAVR = C:/WinAVR
#DIRAVR = /usr/local/avr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = $(DIRAVR)/avr/include
DIRLIB = $(DIRAVR)/avr/lib

LIB = asuro
LIBFILE = lib$(LIB).a
HEADER = asuro.h

## Build
all: $(LIBFILE)
rm -rf *.o *~

%.o: %.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

$(LIBFILE): $(OBJECTS)
$(AR) cru $(LIBFILE) $(OBJECTS)

## Clean target
clean:
rm -rf *.o *~ $(LIBFILE)
rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
rm -rf dep/*.d

install:
cp $(LIBFILE) $(DIRLIB)/$(LIBFILE)
cp inc/$(HEADER) $(DIRINC)/$(HEADER)

lst: $(OBJECTS:%.o=%.lst)


%.lst: %.o
$(OBJDUMP) -h -S $< > $@

## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)


mit make-lib.bat die libasuro.a neu erstellt

Aber das drei Beinige Monster macht nicht was es soll!

Gruß
Juelicher

damaltor
24.02.2008, 22:53
welche odometriescheiben verwendest du?

juelicher
25.02.2008, 05:49
Meine Odometriescheiben haben zwei helle und zwei dunkle Felder,
sind direkt auf die Motorwelle geklebt und sind aus Platinenmaterial erstellt.
Die dunklen Flächen sind geätzt und verzinnt, hat den Vorteil das ich keinen Sinus bekomme sondern ein Rechteck als Odometerspannung, Die Triggerschwelle ist bei mir einfacher einzustellen. Pro Radumdrehung entsehen 100 Wecksel ( 4(Sekmente)*25(Zwei Uebersetzungen je 5/1) = 100).

Gruß
Juelicher

JensK
25.02.2008, 14:19
1. kann es kein anderer verwenden, der nicht auch diesen Mod hat, und 2. wird die messung oder viel mehr der asuro dadurch langsamer, wenn du nur 2 scharwz 2 weiß hast. oder irre ich mich da?

juelicher
25.02.2008, 16:23
Hallo Jensk,

1. in myasuro.h kannst du die Ticks fuer Go und Turn fuer deinen asuro anpassen.
2. wenn du eine 12 Scheibe hast, ist die in der Mitte des Getriebe montiert, also 12 Sekmente mal 5 ist 60 Ticks pro eine Radumdrehung, ich komme weil meine 4 Scheibe auf der Motorwelle liegt auf 4 mal 5 mal 5 ist 100 Ticks pro Radumdrehung.
Die Geschwindigkeit haengt vom Speed ab, Es ist die Frage ob das Odometer die 100 Ticks pro Radumdrehung bei max Speed 255 schaft, M1R oder Inka hatte eine 22 Lochscheibe in Durchlichttechnik verwendet, soweit ich noch weis hat das Funktioniert, betrachtet auf die schnelligkeit des Odometer und dem Atmega8 bei 8000000 Hz Taktfrequenz.
Mein Asuro hat ein Raddurchmesse von 38,6mm mal PI ist 121 mm. Der Asuro faehrt bei 100 Ticks ca. 121mm, wenn 300mm / sekunde als maximal Speed angenommen wird, sind das ca. 300/121*100=248 Ticks in der Sekunde die regiestriert werden mussen. Bei doppelter max Geschwindigkeit 600mm / sekunde sind das ca. 496 Ticks 7 sekunde.
Um einiger massen sicher zu sein das jedes Tick erfasst wird muß mit mindenstens doppelter Frequenz ca 1000Hz das Odometer abgefragt werden,
Bei 8000000Hz / 1000Hz= 8000 Befehle die der Asuro noch machen kann, bevor das Odometer wieder abgefragt werden muß. Annahme ein Befehl ist nur ein Takt beim Atmege8, selbst wenn es 3 Takte sind sind noch ca. 2666 Befehle moeglich.Ich hoffe das war jetzt nicht zu ausfuehrlich, aber wenn ich einen Ueberlegungsfehler habe Bitte Korregieren, denn ich will den Asuro in Echtzeit Zeitgesteuert betreiben und nicht Ereignisgesteuert wie jetzt.

Gruß
Juelicher

JensK
25.02.2008, 17:13
Ahhh ok gut jetzt hab ichs verstanden. also macht es doch sinn.. ok danke für die aufklärung..

gruß
jens

damaltor
26.02.2008, 13:30
der ADC braucht etwa 15-20 befelslängen um einmal abgefragt zu werden. siehe datenblatt! =)
ausserdem fährt der asuro deutlich schneller als 30cm in der sekunde bei voller geschwindigkeit, meiner schafft knapp einen meter.

rossir
26.02.2008, 22:38
Schöne Aufgabe. Ich mache das so.
#include "asuro.h"

typedef struct { int soll, ist, pwm; } TSTATE;
TSTATE left={0,0,0}, right={0,0,0};

int regelnP(TSTATE* x, int delta) {
x->pwm+=(delta*x->soll - 1000*x->ist)/1000;
x->pwm= (x->pwm>127) ? 127 : ((x->pwm<-127) ? -127 : x->pwm);
return x->pwm;
}

int main(void) {
Init();
EncoderInit();
EncoderStart();

left.soll=40; right.soll=60;
long lastTime=0;
while(1) {
left.ist=encoder[LEFT];
right.ist=encoder[RIGHT];
int delta=Gettime()-lastTime;
if(left.ist<10 && right.ist<10 && delta<50) continue;

EncoderSet(0, 0);
SetMotorPower(regelnP(&left, delta), regelnP(&right, delta));
lastTime+=delta;
}
}

juelicher
27.02.2008, 10:02
Hallo rossir

Habe deine Programm versucht zu Laden,
Asuro bleibt stehen und StausLED GREEN geht nur an.

Vermutlich muß vorher noch Parameter übergeben werden.
Bin aber in C noch nicht ganz Sattelfest, was habe ich übersehen.

Gruß
Juelicher

rossir
27.02.2008, 22:08
Wird wohl mein Fehler sein. Hängt wahrscheinlich sehr von der Encoderscheibe ab. Versuch mal schneller zu fahren und ändere die Zeile von

left.soll=40; right.soll=60;

auf

left.soll=80; right.soll=120;

Früher gab es die anpassbare Konstante ENCODERSEGMENTS in der Lib. In der Lib v2.7.1 habe ich das nicht mehr gefunden. Damit könnte man das Programm unabhängig von der verwendeten Encoderscheibe machen.