PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Gesteuertes Vor- und Zurückfahren mit Hoch-und Tieflauframpe



radbruch
08.01.2007, 03:12
Hallo mal wieder,

wie angekündigt werde ich euch etwas nerven. *grins*

Die Ausbeute dieser Nacht ist ein gesteuertes Pendeln von Drehzahl 0 bis Max und zurück auf 0 mit einstellbaren Drehzahlen und Rampen. Wunderbar Motoren und Getriebe schonend ermöglicht es ein komfortables Fahren ohne zusätzliche Interrupt-Funktionen. Darauf lege ich im Moment noch Wert. Der Weg zum ersten Nicklaushäuschen ist steil und steinig. Hier mein Code, diesmal ungeputzt, aber dafür so wie er auf meinem asuro läuft:
/* Gesteuertes Vor- und Zurueckpendeln mit einstellbaren Geschwindigkeiten und Rampen
mic 7.1.2006
*/
#include <asuro.h>

unsigned char sw_data, i, tmp_char, step, speed_min, speed_max, rampe_v, rampe_r;
unsigned int data[2], j, tmp_int;
unsigned long loop_count, rampe_delay;
unsigned char odo_bit_l, odo_bit_r;
unsigned int odo_min_l, odo_max_l, odo_low_l, odo_high_l;
unsigned int odo_min_r, odo_max_r, odo_low_r, odo_high_r;
unsigned int count_l, count_r, count_soll_l, count_soll_r;
unsigned int speed_l, speed_r, speed_soll_l, speed_soll_r;

int MotorRampe(unsigned char sp_l, unsigned char sp_r, unsigned int r) {

if (loop_count > rampe_delay) {
if (sp_l != speed_l) {
if (sp_l > speed_l) speed_l ++;
if (sp_l < speed_l) speed_l --;
rampe_delay=loop_count+r*10;
}
if (sp_r != speed_r) {
if (sp_r > speed_r) speed_r ++;
if (sp_r < speed_r) speed_r --;
rampe_delay=loop_count+r*10;
}
MotorSpeed(speed_l,speed_r);
}
return ((sp_l == speed_l) && (sp_r == speed_r));
}

int main(void) {
Init();
SerWrite("\nHallo\nBatterie: ",17);
PrintInt(Batterie());

step=loop_count=rampe_delay=speed_l=speed_r=0;
speed_min=0; speed_max=250; rampe_v=30; rampe_r=50;

do {
loop_count ++;
switch (step) {
case (0): MotorDir(FWD,FWD); FrontLED(ON); BackLED(OFF,OFF); step++; break;
case (1): if (MotorRampe(speed_max,speed_max,rampe_v)) step++; break;
case (2): if (MotorRampe(speed_min,speed_min,rampe_r)) step++; break;
case (3): MotorDir(RWD,RWD); FrontLED(OFF); BackLED(ON,ON); step++; break;
case (4): if (MotorRampe(speed_max,speed_max,rampe_v)) step++; break;
case (5): if (MotorRampe(speed_min,speed_min,rampe_r)) step=0; break;
case (98): MotorDir(BREAK,BREAK); step++; break;
case (99): FrontLED(OFF); BackLED(OFF,OFF); step=99; break;
}
} while (1);
return 0;
}
Viel Spaß damit, es ist aber eigentlich nur eine Vorstufe zu meinen Odometrie-Versuchen die mit den gewöhnlichen MotorDir- und MotorSpeed-Funktionen nicht recht klappen.

Gruß

mic

Hans Z
08.01.2007, 10:55
Hallo,

das Ergebnis Deiner Nachtschicht lässt sich sehen. Leider kann ich das Programm momentan auf meinen Asuro nicht aufspielen, da ich ihn zu Hause habe.
Mein eigenes Programm läuft leider noch immer nicht zufriedenstellend. Ich habe bei meinem Ansatz versucht, die Odometriewerte auszulesen, was auch wunderbar klappt.
Ich lasse den linken und rechten Motor mit festen Motorspeed-Werten (z.B. 180) anlaufen. Dann versuche ich, je nachdem ob der rechte Motor dem linken voraus ist oder ihm nachhinkt, die Motorspeed des rechten Motors zu ändern. Der linke behält seinen fest eingestellten Wert.
Das Resultat meiner Programmierkünste ist bisher nur ein Asuro, der wie betrunken umherfährt – er zeigt einfach keinen Benimm.
Ich werde Dein Programm nicht kopieren und vielmehr versuchen jetzt in Richtung PWM umzuschwenken und über PWM im Allgemeinen nachlesen. Wäre doch gelacht…

Meine fertige Abfrage der Odometriescheiben kann ich ja weiterverwenden.


Meine C-Künste sind auch verbesserungsfähig. So hänge ich manchmal bei ganz normalen switch-Abfragen oder stolpere über ein überflüssiges Semikolon hinter einer if-Abfrage und wundere mich, weil nichts geht.

Das Nikolaushäuschen ist auch mein 1. Etappenziel.

Grüße, Hans

radbruch
08.01.2007, 11:38
Hallo Hans

Ich kopiere auch selten Programme, schau mir aber oft an wie andere ein Problem angehen und lösen(?). Leider sind Programme auf meinem Level ohne Bummelschleifen und ohne Interrupts recht rar hier. Bummelschleifen sind eine Sackgasse weil der Processor (ohne Interrupts) nichts anderes tun kann. Interrupts sind, vor allem für Einsteiger, sehr gefährlich wegen der asyncronen Ausführung. Deshalb mache ich meine Tests mit kleinen Schrittketten, das ist Übersichtlich und der Processor ist schnell genug dafür bei kleinen Progs.

PWM hat der Processor schon serienmässig eingebaut, nur so kann er mit nur einem Pin die Drehzahl des Motors steuern. Allerdings fehlt eben eine einstellbare Rampe. Natürlich sollte das ganze noch drehzahlgeregelt sein, aber der Weg dahin führt über erfassen und messen der Odo-Daten, das dauert bei mir noch etwas. Hier mal zur Inspiration mein Ansatz zum "kalibrieren" der Odo-Sensorik:
int init_odo() {

StatusLED(YELLOW); MotorDir(RWD,FWD);
odo_min_l=odo_max_l=odo_low_l=odo_high_l=count_l=0 ;
odo_min_r=odo_max_r=odo_low_r=odo_high_r=count_r=0 ;

MotorSpeed(150,150);
for (j==0; j<5000; j++) {
OdometrieData(data);
if (data[0] < odo_min_l) odo_min_l=data[0];
if (data[0] > odo_max_l) odo_max_l=data[0];
if (data[1] < odo_min_r) odo_min_r=data[1];
if (data[1] > odo_max_r) odo_max_r=data[1];
for (i=0; i<200; i++);
}
MotorSpeed(0,0);Msleep(100);
OdometrieData(data);

odo_low_l=((odo_min_l + odo_max_l)/3); // je ein drittel high-nix-low
odo_high_l=((odo_min_l + odo_max_l)/3)*2;
if (data[0] >= ((odo_min_l + odo_max_l)/2)) odo_bit_l=1; else odo_bit_l=0;

odo_low_r=((odo_min_r + odo_max_r)/3); // je ein drittel high-nix-low
odo_high_r=((odo_min_r + odo_max_r)/3)*2;
if (data[1] >= ((odo_min_r + odo_max_r)/2)) odo_bit_r=1; else odo_bit_r=0;
MotorDir(BREAK,BREAK);
}

Während der Messung fährt mein asuro FWD,RWD um das Störlicht von allen Seiten mitzumessen. Ich erfasse die jeweiligen Min und Max-Werte und setze dieSchwellen für High/Low auf jeweils 1/3 und 2/3 der gesammten Wertebereiche. Das funzt auch schon recht gut, nur die extremen "Ausrutscher" sollten noch rausgefiltert werden. Da ich auf glatten Fliesen teste, darf mein asuro keinen Schlupf an den Rädern haben.

Gruß

mic