Hi,
ich habe das Programm von Hermann mal als Vorlage genommen und es etwas "verkompliziert".
Inhaltlich bleibt es bei dem Zweipunktregler. Allderdings versuche ich den Einfluß des Umgebungslichtes zu unterdrücken (ich meine die Idee dazu mal bei waste gefunden zu haben). Bei meinen Messungen (mit einer superhellen LED am Liniensensor) war es allerdings nötig, eine Wartezeit zwischen den Messungen mit aus- bzw. eingeschalteter LED einzuschieben, da die LED zu träge ist. Das mag mit anderen LEDs anders sein.
Weiterhin habe ich die Taster dazu verwendet, um "on the fly" die Parameter für Geschwindigkeit und Hell/Dunkelschwelle zu ändern. Dies geht mit schrittweisem Erhöhen oder erniedrigen oder direktem Eingeben über ein Terminalprogramm oder - im Falle der Hell/Dunkelschwelle - auch über das Messen des Wertes, wenn man den Roboter in der austarierten Stellung hält.
Die Funktionen UartGetc() und ReadInt() schlage ich vor als Erweiterung in die nächste Lib-Version aufzunehmen. Natürlich fehlt dann auch noch ein ReadLong(), dass aber analog zu ReadInt() zu programmieren wäre. Damit hätten die entsprechenden Print-Funktionen dann auch ihr Gegenstück.
Schaut Euch das mal an, experimentiert damit und sagt eure Meinung...
Gruß,
_HP_
EDIT: Der code wurde leicht verändert.
Code:
/****************************************************************************/
/*!
\file test.c
\brief
Programm zum Balancieren von ASURO auf den Hinterrädern.
\par Hinweis:
Die Regelung erfolgt mittels Zweipunktregler. Bitte auch die Infos zur\n
Funktion main() beachten.
\author _HP_
\version beta - 04.04.2007 - _HP_\n
first implementation
\version beta - 05.04.2007 - _HP_\n
bugfixing in ReadInt und kleine Änderungen im Hauptprogramm
*****************************************************************************/
/*****************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* any later version. *
* *
*****************************************************************************/
#include <asuro.h>
#include <stdlib.h>
#define INI_SPEED 240
#define INI_THRESHOLD 53
// Tastenwert bitorientiert, K1 = Bit5, K2 = Bit4, K3 = Bit3, K4 = Bit2,
// K5 = Bit1, K6 = Bit0
#define K1 (1 << 5) // Schalter an der linken Seite neben der IR-Diode
#define K2 (1 << 4)
#define K3 (1 << 3)
#define K4 (1 << 2)
#define K5 (1 << 1)
#define K6 (1 << 0)
/****************************************************************************/
/* */
/* Funktion: UartGetc() */
/* */
/*!
\brief
Einlesen eines Zeichens von der serielle Schnittstelle. Die Funktion wartet\n
solange, bis ein Zeichen gelesen wurde!
\param
keine
\return
gelesenes Zeichen
\author _HP_
\version beta - 04.04.2007 - _HP_\n
first implementation
\par Beispiel:
(Nur zur Demonstration der Parameter/Returnwerte)
\code
char c;
c = UartGetc();
\endcode
*****************************************************************************/
char UartGetc(void)
{
unsigned char data = 0x00; // gelesenen Zeichen
UCSRB = 0x10; // Empfaenger einschalten
while (data == 0x00)
{
if (UCSRA & 0x80) data = UDR;
}
return data;
}
/****************************************************************************/
/* */
/* Funktion: ReadInt() */
/* */
/*!
\brief
Einlesen einer Zahl im Integerbereich (+/- 32767) von der serielle /n
Schnittstelle./n
Die Funktion wartet bis entweder 6 erlaubte Zeichen (Ziffern und an erster\n
Stelle ein Vorzeichen) eingegeben, oder ein Zeichen im Bereich 0x00 - 0x1F\n
gelesen wurden!
\param
keine
\return
Integerwert der eingegebenen Zeichen
\author _HP_
\version beta - 04.04.2007 - _HP_\n
first implementation
\version beta - 05.04.2007 - _HP_\n
numbers[] um ein byte vergrößert, um immer ein NULL-Zeichen\n
am Ende zu haben
\par Beispiel:
(Nur zur Demonstration der Parameter/Returnwerte)
\code
int z;
z = ReadInt();
\endcode
*****************************************************************************/
int ReadInt(void)
{
unsigned char c; // gelesenes Zeichen
unsigned char i = 0; // Index in numbers
char numbers[7] = {0x00}; // Vorzeichen und 5 Ziffern + abschließendes /0
while (i < 6) // Es können maximal 5 Ziffern und ein Vorzeichen gelesen werden
{
c = UartGetc();
if ((c > 0x2F) && (c < 0x3A))
{
numbers[i++] = c;
}
if ((i == 0) && ((c == 0x2B) || (c == 0x2D))) // Vorzeichen an erste Position zulassen
{
numbers[i++] = c;
}
if (c < 0x20) // Beenden bei Eingabe eines nichtdruckbaren Zeichens
{
i = 10;
}
}
return atoi(numbers);
}
/****************************************************************************/
/* */
/* Funktion: ReadSensor() */
/* */
/*!
\brief
Das Licht an den Liniensensoren wird gemessen und die Summe von beiden\n
Sensoren wird zurückgegeben.
Die Funktion minimiert den Einfluß des Umgebungslichtes, indem eine Messung\n
zunächst bei ausgeschaltetem Umgebungslicht durchgeführt wird. Das Ergebnis\n
dieser Messung wird von der Messung mit eingeschalteter LED abgezogen.\n
Da die LED eine gewisse Trägheit besitzt, wird nach dem Ein- bzw. Ausschalten\n
eine kurze Zeit gewartet, bis die Messung erfolgt. Diese Zeit muss evtl. auf\n
den eigenen ASURO abgestimmt werden.
\param
keine
\return
Summe beider Fototransistoren, bereinigt um den Wert des Umgebungslichtes.
\author _HP_
\version beta - 04.04.2007 - _HP_\n
first implementation
\par Beispiel:
(Nur zur Demonstration der Parameter/Returnwerte)
\code
int Licht;
Licht = ReadSensor();
\endcode
*****************************************************************************/
int ReadSensor(void)
{
unsigned int FotoTrans[2]; // gemessene Werte der Fototransistoren (FotoTrans[0] ist links)
int LightEnv; // Summe des gemessen Umgebungslichtes beider Fototransistoren
unsigned char Delay = 10; // Wartezeit in 1/36 ms bis die FrontLED reagiert hat.
FrontLED(OFF);
Sleep(Delay);
LineData(FotoTrans);
LightEnv = FotoTrans[0] + FotoTrans[1];
FrontLED(ON);
Sleep(Delay);
LineData(FotoTrans);
return FotoTrans[0] + FotoTrans[1] - LightEnv;
}
/****************************************************************************/
/* */
/* Funktion: main() */
/* */
/*!
\brief
Programm zum Balancieren des ASURO auf den Hinterrädern.\n
Die Grundidee ist von HermannSW beschrieben im Thread\n
https://www.roboternetz.de/phpBB2/viewtopic.php?t=29269 .\n
Es ist notwendig, den ASURO hinten so zu beschweren, dass sich die Nase\n
nicht zu weit über dem Boden befindet, wenn er sich im Gleichgewicht\n
befindet.
Mit den Tastern kann man die Parameter für die Helligkeit im \n
Gleichgewichtszustand und die Geschwindigkeit des linken Motors im\n
laufenden Betrieb wie folgt ändern:\n
Taster linke Seite ändert die Helligkeitsschwelle der Sensoren im\n
Gleichgewichtszustand... \n
K1 gedrückt : Threshold++; \n
K2 gedrückt : Threshold--; \n
K3 gedrückt : Threshold über Terminalprogramm vorgeben \n
K1 und K2 gedrückt: Threshold aktuellen Wert der Sensoren übernehmen \n
Taster rechte Seite ändert die Geschwindigkeit... \n
K4 gedrückt : Speed über Terminalprogramm vorgeben \n
K5 gedrückt : Speed--; \n
K6 gedrückt : Speed++; \n
Bei jedem Betätign der Taster werden die neuen Werte für THRESHOLD \n
und SPEED über die Infrarotschnittstelle ausgegeben.
\param
keine
\author _HP_
\version beta - 04.04.2007 - _HP_\n
first implementation
\version beta - 05.04.2007 - _HP_\n
Auswerung der Taster verbessert und Umlaute in den Ausgaben entfernt
*****************************************************************************/
int main(void)
{
int Light; // Summe des gemessenen Lichtes der Fototransistoren ohne Umgebungslicht
int T1, T2; // Werte der Taster bei zwei aufeinanderfolgenden Messungen
int Threshold = INI_THRESHOLD; // Schwellwert des Lichtes für die Fototransistoren, der eingehalten werden soll.
int Speed = INI_SPEED; // Geschwindikeit der Motoren, wenn der Wert der Fototransistoren vom Sollwert abweicht.
Init();
FrontLED(ON);
MotorSpeed(Speed,0); // Regelung erfolgt nur über das linke Rad
MotorDir(BREAK,BREAK);
for(;;) {
// Ändern der Parameter mit den Tastern:
T1 = PollSwitch();
T2 = PollSwitch();
if (T1 && T2 && T1 == T2)
{
// Motor stoppen wenn Werte geänder werden
StatusLED(RED);
MotorSpeed(0,0);
// Taster linke Seite ändert die Hell/Dunkel-Schwelle...
if (T1 == K1) Threshold++;
if (T1 == K2) Threshold--;
if (T1 == K3)
{
SerPrint("\r\nBitte einen Wert fuer THRESHOLD eingeben: ");
Threshold = ReadInt();
}
if (T1 == (K1 + K2)) //K1 und K2 gedückt
{
SerPrint("\r\nAutokalibration von THRESHOLD!");
Threshold = ReadSensor();
}
if (Threshold < 0) Threshold = 0;
if (Threshold > 1023) Threshold = 1023;
// Taster rechte Seite ändert die Geschwindigkeit...
if (T1 == K4)
{
SerPrint("\r\nBitte einen Wert fuer SPEED eingeben: ");
Speed = ReadInt();
}
if (T1 == K5) Speed--;
if (T1 == K6) Speed++;
if (Speed < 0) Speed = 0;
if (Speed > 255) Speed = 255;
// Ausgabe der aktuellen Werte
SerPrint("\r\nTHESHOLD: ");
PrintInt(Threshold);
SerPrint(" SPEED: ");
PrintInt(Speed);
SerPrint("\r\n");
Msleep(200);
StatusLED(GREEN);
MotorSpeed(Speed,0);
}
// Licht an den Liniensensoren messen
Light = ReadSensor();
// Fahre rückwärts, wenn es zu dunkel und vorwärts wenn es zu hell wird.
if (Light < Threshold) MotorDir(RWD,BREAK);
else MotorDir(FWD,BREAK);
}
return 0;
}
Lesezeichen