#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <inttypes.h>
#include <stdlib.h>
gehe zum Quellcode dieser Datei
Datenstrukturen | |
struct | my_t |
Makrodefinitionen | |
#define | FALSE 0 |
#define | TRUE 1 |
#define | OFF 0 |
#define | ON 1 |
#define | GREEN 1 |
#define | RED 2 |
#define | YELLOW 3 |
#define | LEFT 0 |
#define | RIGHT 1 |
#define | GREEN_LED_ON PORTB |= GREEN_LED |
#define | GREEN_LED_OFF PORTB &= ~GREEN_LED |
#define | RED_LED_ON PORTD |= RED_LED |
#define | RED_LED_OFF PORTD &= ~RED_LED |
#define | FWD (1 << PB5) |
#define | RWD (1 << PB4) |
#define | BREAK 0x00 |
#define | FREE (1 << PB4) | (1 << PB5) |
#define | IRTX (1 << PB3) |
#define | GREEN_LED (1 << PB0) |
#define | RED_LED (1 << PD2) |
#define | PWM (1 << PB1) | (1 << PB2) |
#define | RIGHT_DIR (1 << PB4) | (1 << PB5) |
#define | LEFT_DIR (1 << PD4) | (1 << PD5) |
#define | SWITCHES (1 << PD3) |
#define | SWITCH_ON PORTD |= SWITCHES |
#define | SWITCH_OFF PORTD &= ~SWITCHES |
#define | BATTERIE (1 << MUX0) | (1 << MUX2) |
#define | SWITCH (1 << MUX2) |
#define | IR_LEFT (1 << MUX0) | (1 << MUX1) |
#define | IR_RIGHT (1 << MUX1) |
#define | FRONT_LED (1 << PD6) |
#define | ODOMETRIE_LED (1 << PD7) |
#define | ODOMETRIE_LED_ON PORTD |= ODOMETRIE_LED |
#define | ODOMETRIE_LED_OFF PORTD &= ~ODOMETRIE_LED |
#define | WHEEL_LEFT (1 << MUX0) |
#define | WHEEL_RIGHT 0 |
Funktionen | |
void | Init (void) |
Initialisiert die Hardware: Ports, A/D Wandler, Serielle Schnittstelle, PWM Die Init Funktion muss von jeden Programm beim Start aufgerufen werden. | |
unsigned long | Gettime (void) |
Gibt die aktuelle Zeit in ms zurueck. | |
void | Msleep (int dauer) |
Wartefunktion in ms. | |
void | Sleep (unsigned char time36kHz) |
Wartefunktion. | |
void | EncoderInit (void) |
Den Interrupt Betrieb der Odometriesensoren-Messung initialisieren und starten. | |
void | EncoderSet (int setl, int setr) |
Interruptbetriebene Odometriesensoren Werte vorbelegen. | |
void | EncoderStop (void) |
Den Interrupt Betrieb der Odometriesensoren-Messung anhalten. | |
void | EncoderStart (void) |
Den Interrupt Betrieb der Odometriesensoren-Messung starten. | |
void | Go (int distance, int speed) |
Faehrt eine bestimmte Strecke mit einer bestimmten Geschwindigkeit. (Autor: stochri) Benutzt die Odometrie Sensoren im Interrupt Betrieb. Vor dem ersten Aufruf muss deshalb EncoderInit() aufgerufen werden. | |
void | Turn (int degree, int speed) |
Dreht um einen bestimmten Winkel mit einer bestimmten Geschwindigkeit. (Autor: stochri) Benutzt die Odometrie Sensoren im Interrupt Betrieb. Vor dem ersten Aufruf muss deshalb EncoderInit() aufgerufen werden. | |
void | UartPutc (unsigned char zeichen) |
Sendet einen einzelnen Character über die serielle Schnittstelle. | |
void | SerPrint (unsigned char *data) |
Sendet einen null-terminierten String ueber die serielle Schnittstelle. | |
void | PrintInt (int wert) |
Ausgabe eines Integer Wertes als String ueber die serielle Schnittstelle. | |
void | PrintLong (long wert) |
Ausgabe eines Long Wertes als String ueber die serielle Schnittstelle. | |
int | Batterie (void) |
Liest die Batteriespannung und gibt sie zurueck. Es erfolgt keine Konvertierung in einen Spannungswert. | |
void | LineData (unsigned int *data) |
Liest die Daten der beiden Linienverfolgungssensoren. Die Linien-Beleuchtungs-LED kann sowohl an- als auch ausgeschaltet sein. | |
void | OdometrieData (unsigned int *data) |
Liest die Daten der beiden Odometriesensoren (Radsensoren). Diese Funktion schaltet die Odometrie-LED's immer an. Diese Funktion schaltet die Back-LED's immer aus. | |
void | StatusLED (unsigned char color) |
Steuert die (lustige) mehrfarbige Status-LED. | |
void | FrontLED (unsigned char status) |
Steuert die vorne, nach unten zeigende, Front-LED. | |
void | BackLED (unsigned char left, unsigned char right) |
Steuert die beiden hinteren Back-LED's Wenn diese Funktion aufgerufen wird, funktioniert die Odometriemessung nicht mehr, da die gleichen Port-Pins (Port C:Pin 0 und 1) des Prozessors hierfuer verwendet werden. | |
void | MotorDir (unsigned char left_dir, unsigned char right_dir) |
Steuert die Drehrichtung der Motoren. | |
void | MotorSpeed (unsigned char left_speed, unsigned char right_speed) |
Steuert die Geschwindigkeit der Motoren. | |
void | SetMotorPower (int8_t leftpwm, int8_t rightpwm) |
Steuert die Motorgeschwindigkeit und Drehrichtung der Motoren. | |
void | SerWrite (unsigned char *data, unsigned char length) |
Senden von Daten ueber die serielle Schnittstelle. | |
void | SerRead (unsigned char *data, unsigned char length, unsigned int timeout) |
Lesen von Daten ueber die serielle Schnittstelle. | |
unsigned char | PollSwitch (void) |
Tastsensor Abfrage im 'Polling-Betrieb'. | |
void | StartSwitch (void) |
'Interrupt-Betrieb' zur Tastsensor Abfrage einschalten. | |
void | StopSwitch (void) |
'Interrupt-Betrieb' zur Tastsensor Abfrage anhalten. | |
void | Sound (uint16_t freq, uint16_t duration_msec, uint8_t amplitude) |
Soundausgabe ueber die Motoren. | |
Variablen | |
const char | version [5] |
int | switched |
Flag, dass der Interrupt SIG_INTERRUPT1 durch eine gedrueckte Taste ausgeloesst wurde. 0 = keine Taste, 1 = Taste gedrueckt. Kann im eigenen Programm immer abgefragt werden. | |
int | encoder [2] |
Odometriesensor Zaehler bei Interrupt Betrieb. encoder[0] links, encoder[1] = rechts. | |
volatile unsigned char | count36kHz |
Counter fuer 36kHz. | |
volatile unsigned long | timebase |
Sytemzeit in ms. | |
volatile int | autoencode |
Steuert, ob die Odometrie-Sensor Abfrage im Interrupt Betrieb laufen soll. | |
volatile my_t | my |
Toll, so kann man sich eine Mail sparen. Hallo Peter, ich bin mir ziemlich sicher, dass du schon das weitere Vorgehen fuer die ausge- lagerten asurotypischen Parameter hast. Ich habe hier mal einen Vorschlag fuer die Kommentare der benutzten Werte. Verpackt habe ich das hier in einer Daten- struktur my_t, die so natuerlich nicht benutzt werden muss.
Definiert in Datei asuro.h.
#define BATTERIE (1 << MUX0) | (1 << MUX2) |
#define GREEN_LED (1 << PB0) |
#define GREEN_LED_OFF PORTB &= ~GREEN_LED |
#define GREEN_LED_ON PORTB |= GREEN_LED |
#define IR_LEFT (1 << MUX0) | (1 << MUX1) |
#define IR_RIGHT (1 << MUX1) |
#define IRTX (1 << PB3) |
#define LEFT_DIR (1 << PD4) | (1 << PD5) |
#define ODOMETRIE_LED (1 << PD7) |
#define ODOMETRIE_LED_OFF PORTD &= ~ODOMETRIE_LED |
#define ODOMETRIE_LED_ON PORTD |= ODOMETRIE_LED |
#define PWM (1 << PB1) | (1 << PB2) |
#define RIGHT_DIR (1 << PB4) | (1 << PB5) |
#define SWITCH (1 << MUX2) |
#define WHEEL_LEFT (1 << MUX0) |
#define WHEEL_RIGHT 0 |
void BackLED | ( | unsigned char | left, | |
unsigned char | right | |||
) |
Steuert die beiden hinteren Back-LED's
Wenn diese Funktion aufgerufen wird, funktioniert die Odometriemessung
nicht mehr, da die gleichen Port-Pins (Port C:Pin 0 und 1) des Prozessors
hierfuer verwendet werden.
[in] | left | Schaltet die linke LED an bzw. aus. [ ON | OFF ] |
[in] | right | Schaltet die rechte LED an bzw. aus. [ ON | OFF ] |
Definiert in Zeile 155 der Datei leds.c.
00158 { 00159 if (left || right) 00160 { 00161 PORTD &= ~(1 << PD7); // Rad-LED's OFF 00162 DDRC |= (1 << PC0) | (1 << PC1); // Port als Output => KEINE Odometrie 00163 PORTC |= (1 << PC0) | (1 << PC1); 00164 } 00165 if (!left) 00166 PORTC &= ~(1 << PC1); 00167 if (!right) 00168 PORTC &= ~(1 << PC0); 00169 }
int Batterie | ( | void | ) |
Liest die Batteriespannung und gibt sie zurueck.
Es erfolgt keine Konvertierung in einen Spannungswert.
keine |
// In Variable wert den 10-Bit-Bateriespannungswert lesen // und bei Unterschreitung von 810 eine alles_stop-Funktion // aufrufen. int wert; wert = Batterie (); if (wert < 810) // 810 entsprechen ca. 4,455 Volt alles_stop (); // Spannung zu klein, Akkus schonen
Definiert in Zeile 80 der Datei adc.c.
00082 { 00083 ADMUX = (1 << REFS0) | (1 << REFS1) | BATTERIE; // interne 2.56V Referenz 00084 // Ref. mit ext. Kapazitaet 00085 ADCSRA |= (1 << ADSC); // Starte AD-Wandlung 00086 while (!(ADCSRA & (1 << ADIF))) // Ende der AD-Wandlung abwarten 00087 ; 00088 ADCSRA |= (1 << ADIF); // AD-Interupt-Flag zuruecksetzen 00089 return ADCL + (ADCH << 8); // Ergebnis als 16-Bit-Wert 00090 }
void EncoderInit | ( | void | ) |
Den Interrupt Betrieb der Odometriesensoren-Messung initialisieren und starten.
keine |
int main (void) { Init (); EncoderInit (); MotorDir (FWD, FWD); MotorSpeed (150, 150); while (1) ( // Dein Programm if (encoder [0] > 500) { EncoderStop (); MotorSpeed (0, 0); } } return 0; }
Definiert in Zeile 91 der Datei encoder.c.
00092 { 00093 /* 00094 Alle definierten Interrupts im Asuro sperren. 00095 */ 00096 cli(); 00097 00098 /* 00099 Port C als Input => dadurch gehen die Back-LED aus ... 00100 */ 00101 DDRC &= ~ ((1<<PC0) | (1<<PC1)); 00102 /* 00103 ... aber nun koennen die LED's am Rad eingeschaltet werden, und die 00104 Sensoren koennen gemessen werden. 00105 */ 00106 ODOMETRIE_LED_ON; 00107 00108 /* 00109 AD-Wandler einschalten, Parameter einstellen und Starten. (clk/128) 00110 */ 00111 ADCSRA = (1<<ADEN) | (1<<ADFR) | (1<<ADIE) | (1<<ADSC) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2); 00112 00113 /* 00114 Linken Odometrie-Sensor auswaehlen. (AVCC ref. with external capacitor) 00115 */ 00116 ADMUX = (1<<ADLAR) | (1<<REFS0) | WHEEL_LEFT; 00117 00118 /* 00119 Odometrie im Interruptbetrieb weiter bearbeiten. 00120 */ 00121 autoencode = TRUE; 00122 00123 /* 00124 Alle definierten Interrupts im Asuro wieder zulassen. 00125 */ 00126 sei(); 00127 00128 /* 00129 Die Odometrie Hell-/Dunkel-Zaehler zuruecksetzen/initialisieren. 00130 */ 00131 EncoderSet (0, 0); 00132 }
void EncoderSet | ( | int | setl, | |
int | setr | |||
) |
Interruptbetriebene Odometriesensoren Werte vorbelegen.
[in] | setl | Wert fuer links |
[in] | setr | Wert fuer rechts |
Definiert in Zeile 221 der Datei encoder.c.
void EncoderStart | ( | void | ) |
Den Interrupt Betrieb der Odometriesensoren-Messung starten.
keine |
Definiert in Zeile 189 der Datei encoder.c.
00190 { 00191 autoencode = TRUE; 00192 }
void EncoderStop | ( | void | ) |
Den Interrupt Betrieb der Odometriesensoren-Messung anhalten.
keine |
Definiert in Zeile 159 der Datei encoder.c.
00160 { 00161 autoencode = FALSE; 00162 }
void FrontLED | ( | unsigned char | status | ) | [inline] |
Steuert die vorne, nach unten zeigende, Front-LED.
[in] | status | Schaltet die LED an bzw. aus. [ ON | OFF ] |
Definiert in Zeile 120 der Datei leds.c.
unsigned long Gettime | ( | void | ) |
Gibt die aktuelle Zeit in ms zurueck.
Da der Asuro keine Atomuhr hat, ist es die vergangene Zeit seitdem er eingeschaltet wurde.
Genauer: nachdem der Interrupt Timer2 aktiviert wurde.
keine |
Definiert in Zeile 78 der Datei time.c.
00079 { 00080 return ((timebase * 256) + count36kHz) / 36; 00081 }
void Go | ( | int | distance, | |
int | speed | |||
) |
Faehrt eine bestimmte Strecke mit einer bestimmten Geschwindigkeit. (Autor: stochri)
Benutzt die Odometrie Sensoren im Interrupt Betrieb.
Vor dem ersten Aufruf muss deshalb EncoderInit() aufgerufen werden.
[in] | distance | Distanz in mm (- rueckwaerts, + = vorwaerts) |
[in] | speed | Geschwindigkeit (Wertebereich 0...255) |
// Laesst den Asuro ein Quadrat von 200 mm fahren, // bei einer Geschwindigkeit von 150. EncoderInit (); for (int i = 0; i < 4; i++) { Go (200, 150); Turn (90, 150); }
Definiert in Zeile 307 der Datei encoder.c.
00310 { 00311 uint32_t enc_count; 00312 int tot_count = 0; 00313 int diff = 0; 00314 int l_speed = speed, r_speed = speed; 00315 00316 // calculation tics/mm 00317 enc_count=abs(distance)*10000L; 00318 enc_count/=19363L; 00319 00320 EncoderSet(0,0); // reset encoder 00321 00322 MotorSpeed(l_speed,r_speed); 00323 if (distance<0) MotorDir(RWD,RWD); 00324 else MotorDir(FWD,FWD); 00325 00326 while (tot_count<enc_count) 00327 { 00328 tot_count += encoder[LEFT]; 00329 diff = encoder[LEFT] - encoder[RIGHT]; 00330 if (diff > 0) 00331 { //Left faster than right 00332 if ((l_speed > speed) || (r_speed > 244)) l_speed -= 10; 00333 else r_speed += 10; 00334 } 00335 if (diff < 0) 00336 { //Right faster than left 00337 if ((r_speed > speed) || (l_speed > 244)) r_speed -= 10; 00338 else l_speed += 10; 00339 } 00340 EncoderSet(0,0); // reset encoder 00341 MotorSpeed(l_speed,r_speed); 00342 Msleep(1); 00343 } 00344 MotorDir(BREAK,BREAK); 00345 Msleep(200); 00346 }
void Init | ( | void | ) |
Initialisiert die Hardware: Ports, A/D Wandler, Serielle Schnittstelle, PWM
Die Init Funktion muss von jeden Programm beim Start aufgerufen werden.
keine |
Definiert in Zeile 107 der Datei asuro.c.
00109 { 00110 /* 00111 Timer2, zum Betrieb mit der seriellen Schnittstelle, fuer die 00112 IR-Kommunikation auf 36 kHz eingestellt. 00113 */ 00114 TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20); 00115 OCR2 = 0x91; // duty cycle fuer 36kHz 00116 TIMSK |= (1 << TOIE2); // 36kHz counter 00117 00118 /* 00119 Die serielle Schnittstelle wurde waerend der Boot-Phase schon 00120 programmiert und gestartet. Hier werden die Parameter auf 2400 1N8 gesetzt. 00121 */ 00122 UCSRA = 0x00; 00123 UCSRB = 0x00; 00124 UCSRC = 0x86; // 1 Stop Bit | No Parity | 8 Data Bit 00125 UBRRL = 0xCF; // 2400bps @ 8.00MHz 00126 00127 /* 00128 Datenrichtung der I/O-Ports festlegen. Dies ist durch die Beschaltung der 00129 Asuro-Hardware nicht aenderbar. 00130 Port B: Seriell Senden; Richtungsvorgabe Motor links; Takt fuer die 00131 Geschwindigkeit beider Motoren; Grueneanteil-Status-LED 00132 Port D: Richtungsvorgabe Motor rechts; Vordere LED; 00133 Odometrie-LED (Radsensor); Rotanteil-Status-LED 00134 */ 00135 DDRB = IRTX | LEFT_DIR | PWM | GREEN_LED; 00136 DDRD = RIGHT_DIR | FRONT_LED | ODOMETRIE_LED | RED_LED; 00137 00138 /* 00139 PWM-Kanaele OC1A und OC1B auf 8-Bit einstellen. 00140 Sie werden fuer die Geschwindigkeitsvorgaben der Motoren benutzt. 00141 */ 00142 TCCR1A = (1 << WGM10) | (1 << COM1A1) | (1 << COM1B1); 00143 TCCR1B = (1 << CS11); // tmr1-Timer mit MCU-Takt/8 betreiben. 00144 00145 /* 00146 Einstellungen des A/D-Wandlers auf MCU-Takt/64 00147 */ 00148 ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1); 00149 00150 /* 00151 Sonstige Vorbereitungen. 00152 - Alle LED's ausschalten 00153 - Motoren stoppen und schon mal auf Vorwaerts einstellen. 00154 - Globale Variable autoencoder ausschalten. 00155 */ 00156 ODOMETRIE_LED_OFF; 00157 FrontLED (OFF); 00158 BackLED (ON, ON); 00159 BackLED (OFF, OFF); 00160 StatusLED (GREEN); 00161 00162 MotorDir (FWD, FWD); 00163 MotorSpeed (0, 0); 00164 00165 autoencode = FALSE; 00166 00167 /* 00168 Funktion zum ALLGEMEINEN ZULASSEN von Interrupts. 00169 */ 00170 sei (); 00171 }
void LineData | ( | unsigned int * | data | ) |
Liest die Daten der beiden Linienverfolgungssensoren.
Die Linien-Beleuchtungs-LED kann sowohl an- als auch ausgeschaltet sein.
[out] | data | Zeiger auf die gelesenen Daten: data[0] linker Sensor (Bereich 0..1023) data[1] rechter Sensor (Bereich 0..1023) |
Definiert in Zeile 128 der Datei adc.c.
00130 { 00131 int ec_bak = autoencode; // Sichert aktuellen Zustand 00132 00133 /* 00134 Autoencode-Betrieb vom ADC-Wandler unterbinden. 00135 */ 00136 autoencode = FALSE; 00137 00138 /* 00139 Linken Linien-Sensor lesen 00140 */ 00141 ADMUX = (1 << REFS0) | IR_LEFT; // Referenz mit externer Kapazitaet 00142 Sleep (10); 00143 ADCSRA |= (1 << ADSC); // Starte AD-Wandlung 00144 while (!(ADCSRA & (1 << ADIF))) // Ende der AD-Wandlung abwarten 00145 ; 00146 ADCSRA |= (1 << ADIF); // AD-Interupt-Flag zuruecksetzen 00147 data [0] = ADCL + (ADCH << 8); // Ergebnis als 16-Bit-Wert 00148 00149 /* 00150 Rechten Linien-Sensor lesen 00151 */ 00152 ADMUX = (1 << REFS0) | IR_RIGHT; // Referenz mit externer Kapazitaet 00153 Sleep (10); 00154 ADCSRA |= (1 << ADSC); // Starte AD-Wandlung 00155 while (!(ADCSRA & (1 << ADIF))) // Ende der AD-Wandlung abwarten 00156 ; 00157 ADCSRA |= (1 << ADIF); // AD-Interupt-Flag zuruecksetzen 00158 data [1] = ADCL + (ADCH << 8); // Ergebnis als 16-Bit-Wert 00159 00160 /* 00161 Autoencode-Betrieb vom ADC-Wandler wiederherstellen. 00162 */ 00163 autoencode = ec_bak; 00164 }
void MotorDir | ( | unsigned char | left_dir, | |
unsigned char | right_dir | |||
) | [inline] |
Steuert die Drehrichtung der Motoren.
[in] | left_dir | Richtung des linken Motors [ FWD | RWD | BREAK | FREE ] |
[in] | right_dir | Richtung des rechten Motors [ FWD | RWD | BREAK | FREE ] |
Definiert in Zeile 127 der Datei motor.c.
00130 { 00131 PORTD = (PORTD &~ ((1 << PD4) | (1 << PD5))) | left_dir; 00132 PORTB = (PORTB &~ ((1 << PB4) | (1 << PB5))) | right_dir; 00133 }
void MotorSpeed | ( | unsigned char | left_speed, | |
unsigned char | right_speed | |||
) | [inline] |
Steuert die Geschwindigkeit der Motoren.
[in] | left_speed | Geschwindigkeit linker Motor (Bereich 0..255) |
[in] | right_speed | Geschwindigkeit rechter Motor (Bereich 0..255) |
// Setzt die Geschwindigkeit fuer den linken Motor // auf 150 und stoppt den rechten Motor. MotorSpeed (150, 0);
Definiert in Zeile 84 der Datei motor.c.
void Msleep | ( | int | dauer | ) |
Wartefunktion in ms.
Diese Funktion nutzt die Sleep()-Funktion um mit dem uebergeben Parameter
Pausen in ms-Einheiten zu erhalten.
[in] | dauer | Wartezeit in Millisekunden. |
// 1.5 Sekunde warten Msleep (1500);
Definiert in Zeile 143 der Datei time.c.
00145 { 00146 int z; 00147 for (z = 0; z < dauer; z++) 00148 Sleep (36); 00149 }
void OdometrieData | ( | unsigned int * | data | ) |
Liest die Daten der beiden Odometriesensoren (Radsensoren).
Diese Funktion schaltet die Odometrie-LED's immer an.
Diese Funktion schaltet die Back-LED's immer aus.
[out] | data | Zeiger auf die gelesenen Daten: data[0] linker Sensor, data[1] rechter Sensor. (Bereich 0..1023) |
unsigned int data [2]; OdometrieData (data); if (data [0] > data [1]) // 0 linker Sensor; 1 ist rechter Sensor fahre_links (); // Ein bisschen nach links fahren if (data [0] < data [1]) fahre_rechts (); // Ein bisschen nach rechts fahren BackLED (ON, OFF); // linke Back-LED mal wieder anschalten
Definiert in Zeile 208 der Datei adc.c.
00210 { 00211 /* 00212 Vorbereitung zum lesen der Odometrie-Sensoren. 00213 */ 00214 DDRC &= ~((1 << PC0) | (1 << PC1)); // Port auf Input=>Back-LEDs gehen aus 00215 ODOMETRIE_LED_ON; // Odometrie-LED's einschalten 00216 00217 /* 00218 Linken Odometrie-Sensor lesen 00219 */ 00220 ADMUX = (1 << REFS0) | WHEEL_LEFT; // Referenz mit externer Kapazitaet 00221 ADCSRA |= (1 << ADSC); // Starte AD-Wandlung 00222 while (!(ADCSRA & (1 << ADIF))) // Ende der AD-Wandlung abwarten 00223 ; 00224 ADCSRA |= (1 << ADIF); // AD-Interupt-Flag zuruecksetzen 00225 data [0] = ADCL + (ADCH << 8); // Ergebnis als 16-Bit-Wert 00226 00227 /* 00228 Rechten Odometrie-Sensor lesen 00229 */ 00230 ADMUX = (1 << REFS0) | WHEEL_RIGHT; // Referenz mit externer Kapazitaet 00231 ADCSRA |= (1 << ADSC); // Starte AD-Wandlung 00232 while (!(ADCSRA & (1 << ADIF))) // Ende der AD-Wandlung abwarten 00233 ; 00234 ADCSRA |= (1 << ADIF); // AD-Interupt-Flag zuruecksetzen 00235 data [1] = ADCL + (ADCH << 8); // Ergebnis als 16-Bit-Wert 00236 }
unsigned char PollSwitch | ( | void | ) |
Tastsensor Abfrage im 'Polling-Betrieb'.
keine |
uint8_t t1, t2; unsigned char text [16]; while (1) { t1 = PollSwitch (); t2 = PollSwitch (); // 2x PollSwitch aufrufen und beide Rueckgabewerte auf Gleichheit ueberpruefen if (t1 && t2 && t1 == t2) // irgendeine Taste gedrueckt { itoa (t1, text, 10); // Tastenwert senden SerPrint (text); SerPrint ("\r\n"); // Zeilenvorschub } Msleep (500); // 0,5 sek warten }
Definiert in Zeile 77 der Datei switches.c.
00078 { 00079 unsigned int i; 00080 int ec_bak = autoencode; // Sichert aktuellen Zustand 00081 00082 /* 00083 Autoencode-Betrieb vom ADC-Wandler unterbinden. 00084 */ 00085 autoencode = FALSE; 00086 00087 DDRD |= SWITCHES; // Port-Bit SWITCHES als Output 00088 SWITCH_ON; // Port-Bit auf HIGH zur Messung 00089 ADMUX = (1 << REFS0) | SWITCH; // AVCC reference with external capacitor 00090 Sleep (10); 00091 00092 ADCSRA |= (1 << ADSC); // Starte AD-Wandlung 00093 while (!(ADCSRA & (1 << ADIF))) // Ende der AD-Wandlung abwarten 00094 ; 00095 ADCSRA |= (1 << ADIF); // AD-Interupt-Flag zuruecksetzen 00096 00097 i = ADCL + (ADCH << 8); // Ergebnis als 16-Bit-Wert 00098 00099 SWITCH_OFF; // Port-Bit auf LOW 00100 Sleep (5); 00101 00102 /* 00103 Autoencode-Betrieb vom ADC-Wandler wiederherstellen. 00104 */ 00105 autoencode = ec_bak; 00106 00107 /* 00108 Die Original Umrechenfunktion von Jan Grewe - DLR wurder ersetzt durch 00109 eine Rechnung ohne FLOAT-Berechnungen. 00110 return ((unsigned char) ((( 1024.0/(float)i - 1.0)) * 61.0 + 0.5)); 00111 00112 Wert 61L evtl. anpasssen, falls fuer K1 falsche Werte zurueckgegebn werden. 00113 */ 00114 return ((10240000L / (long)i - 10000L) * 61L + 5000L) / 10000; 00115 }
void PrintInt | ( | int | wert | ) |
Ausgabe eines Integer Wertes als String ueber die serielle Schnittstelle.
[in] | wert | Auszugebender Integer Wert (16Bit) |
2.60 - 28.09.2005 - m.a.r.v.i.n
strlen verwenden, anstelle fester Laenge
2.61 - 20.11.2006 - m.a.r.v.i.n
Initialisierung text String kann zu Fehler
beim Flashen mit RS232/IR Adapter fuehren
(Bug report von francesco)
2.70b- 07.01.2007 - m.a.r.v.i.n
SerPrint Funktion anstelle SerWrite verwenden
2.70rc2- 09.02.2007 - m.a.r.v.i.n
Text Laenge auf 7 erhoeht, fuer Ausgabe negativer Werte (Bug Report von HermannSW)
Definiert in Zeile 92 der Datei print.c.
00094 { 00095 char text [7]; // "-12345" 00096 00097 itoa (wert, text, 10); 00098 SerPrint (text); 00099 }
void PrintLong | ( | long | wert | ) |
Ausgabe eines Long Wertes als String ueber die serielle Schnittstelle.
[in] | wert | Auszugebender Long Wert (32Bit) |
Definiert in Zeile 131 der Datei print.c.
00133 { 00134 char text [12]; // '-'1234567891'\0' 00135 00136 ltoa (wert, text, 10); 00137 SerPrint (text); 00138 }
void SerPrint | ( | unsigned char * | data | ) |
Sendet einen null-terminierten String ueber die serielle Schnittstelle.
[in] | data | null-terminierter String |
// Beispiel fuer SerPrint SerPrint ("Hallo ASURO!\r\n");
Definiert in Zeile 200 der Datei print.c.
00202 { 00203 unsigned char i = 0; 00204 00205 while (data [i] != 0x00) 00206 UartPutc (data [i++]); 00207 }
void SerRead | ( | unsigned char * | data, | |
unsigned char | length, | |||
unsigned int | timeout | |||
) |
Lesen von Daten ueber die serielle Schnittstelle.
Die empfangenen Daten werden in der als Pointer uebergeben Variable data
dem Aufrufer zur verfuegung gestellt.
Der Aufrufer bestimmt ueber den Parameter Timeout, ob diese Funktion im
'blocking'- oder im 'nonblocking'-Mode laufen soll. Im 'blocking'-Mode
bleibt diese Funktion auf alle Faelle so lange aktiv, bis die, uber den
Parameter length, geforderte Anzahl Zeichen empfamgen wurde.
[out] | data | Zeiger auf die einzulesenden Daten |
[in] | length | Anzahl der zu lesenden Zeichen |
[in] | timeout | 0 = blockierender Mode Wird hier ein Wert groesser 0 uebergeben, wird nur eine gewisse Zeit lang versucht ein weiteres Zeichen ueber die Schnittstelle zu empfangen. Kommt in dieser Zeit kein weiteres Zeichen, wird im zurueckgegeben Parameter date das erste Zeichen auf 'T' gesetzt und die Funktion kehrt zum Aufrufer zurueck. Ansonsten wird die Funktion auf alle Faelle verlassen, wenn die als Parameter length geforderte Anzahl Zeichen empfangen werden konnten. |
Definiert in Zeile 135 der Datei uart.c.
00139 { 00140 unsigned char i = 0; 00141 unsigned int time = 0; 00142 00143 UCSRB = 0x10; // Empfaenger einschalten 00144 00145 if (timeout != 0) 00146 { 00147 /* 00148 Die Funktion wird auf alle Faelle, auch ohne empfangene Daten, wieder 00149 verlassen. --> nonblocking mode 00150 */ 00151 while (i < length && time++ < timeout) 00152 { 00153 if (UCSRA & 0x80) 00154 { 00155 data [i++] = UDR; 00156 time = 0; 00157 } 00158 } 00159 if (time > timeout) 00160 data [0] = 'T'; 00161 } 00162 else 00163 { 00164 /* 00165 Die Funktion wird auf alle Faelle erst nach dem Empfang von der 00166 vorgegebenen Anzahl Zeichen verlassen. blocking mode 00167 */ 00168 while (i < length) 00169 { 00170 if (UCSRA & 0x80) 00171 data [i++] = UDR; 00172 } 00173 } 00174 }
void SerWrite | ( | unsigned char * | data, | |
unsigned char | length | |||
) |
Senden von Daten ueber die serielle Schnittstelle.
Die zu senden Daten werden nicht als 0-terminierter C-String erwartet, sondern
es werden grundsaetzlich so viele Zeichen gesendet wie im 2.ten Parameter
angegeben werden.
[in] | data | Zu sendende Daten |
[in] | length | Die Anzahl der zu sendenden Zeichen. |
// Senden eines 'wunderbaren Textes' ueber die Schnittstelle. SerWrite ("Hello world", 11);
Definiert in Zeile 68 der Datei uart.c.
00071 { 00072 unsigned char i = 0; 00073 00074 UCSRB = 0x08; // Sender einschalten 00075 while (length > 0) // so lange noch Daten da sind 00076 { 00077 if (UCSRA & 0x20) 00078 { // warten, bis der Sendebuffer leer ist 00079 UDR = data[i++]; 00080 length --; 00081 } 00082 } 00083 while (!(UCSRA & 0x40)) // abwarten, bis das letzte Zeichen 00084 ; // uebertragen wurde. 00085 00086 for (i = 0; i < 0xFE; i++) // warten auf irgendwas; keiner weiss 00087 for (length = 0; length < 0xFE; length++); // wofuer 00088 }
void SetMotorPower | ( | int8_t | leftpwm, | |
int8_t | rightpwm | |||
) |
Steuert die Motorgeschwindigkeit und Drehrichtung der Motoren.
[in] | leftpwm | linker Motor (-rückwaerts, + vorwaerts) (Wertebereich -128...127) |
[in] | rightpwm | rechter Motor (-rückwaerts, + vorwaerts) (Wertebereich -128...127) |
// Setzt die Geschwindigkeit fuer den linken Motor auf 60 (vorwaerts), // und für den rechten Motor auf -60 (rueckwaerts) // Asuro soll auf der Stelle drehen. SetMotorPower (60, -600);
Definiert in Zeile 183 der Datei motor.c.
00186 { 00187 unsigned char left, right; 00188 00189 if (leftpwm < 0) // Ein negativer Wert fuehrt ... 00190 { 00191 left = RWD; // ... zu einer Rueckwaertsfahrt, ... 00192 leftpwm = -leftpwm; // aber immer positiv PWM-Wert 00193 } 00194 else 00195 left = FWD; // ... sonst nach vorne, ... 00196 if (leftpwm == 0) 00197 left = BREAK; // ... oder bei 0 zum Bremsen. 00198 00199 if (rightpwm < 0) 00200 { 00201 right = RWD; 00202 rightpwm = -rightpwm; 00203 } 00204 else 00205 right = FWD; 00206 if (rightpwm == 0) 00207 right = BREAK; 00208 00209 MotorDir (left, right); // Drehrichtung setzen 00210 00211 /* 00212 Die Geschwindigkeitsparameter mit 2 multiplizieren, da der Absolutwert 00213 der Parameter dieser Funktion nur genau die Haelfte von der MotorSpeed()- 00214 Funktion betraegt. 00215 */ 00216 MotorSpeed (leftpwm * 2, rightpwm * 2); 00217 }
void Sleep | ( | unsigned char | time36kHz | ) |
Wartefunktion.
Die maximale Wartezeit betraegt 7ms. Fuer laengere Wartezeiten siehe Msleep().
Diese Funktion nutzt den Timer 2-Interrupt um ein 'zeitgefuehl' zu erhalten.
Der Interrupt wird mit 36 kHz, durch die Init()-Funktion initialisiert,
aufgerufen und zaehlt dort die globale Variablen count36kHz weiter.
Diese Funktion nutzt diesen Zaehler und berechnet daraus mit dem uebergeben
Parameter den Zeitpunkt wann die Pausenzeit erreicht ist, Danach bricht sie
ab, und im Hauptprogramm ist eben eine Wartezeit eingelegt worden.
[in] | time36kHz | Wartezeit x/36kHz (sec) |
// 1 Millisekunde warten Sleep (36);
Definiert in Zeile 111 der Datei time.c.
00113 { 00114 unsigned char ziel = (time36kHz + count36kHz) & 0x00FF; 00115 00116 while (count36kHz != ziel) 00117 ; 00118 }
void Sound | ( | uint16_t | freq, | |
uint16_t | duration_msec, | |||
uint8_t | amplitude | |||
) |
Soundausgabe ueber die Motoren.
[in] | freq | Frequenz in Hz |
[in] | duration_msec | Laenge in Millisekunden |
[in] | amplitude | Amplitude |
// Laesst den Asuro einen Ton von 1kHz für eine 1/2 Sekunde mit max. Amplitude spielen Sound(1000, 500, 255);
Definiert in Zeile 46 der Datei sound.c.
00047 { 00048 uint16_t n,k,wait_tics; 00049 uint32_t period_usec,dauer_usec; 00050 00051 period_usec=1000000L/freq; 00052 dauer_usec=1000*duration_msec; 00053 k=dauer_usec/period_usec; 00054 00055 //IR Interuptfreq=36KHz 00056 //Wavefreq=18KHz 00057 00058 wait_tics=18000/freq; 00059 00060 MotorSpeed(amplitude,amplitude); 00061 00062 for (n=0;n<k;n++) 00063 { 00064 MotorDir(FWD,FWD); 00065 Sleep(wait_tics); 00066 MotorDir(RWD,RWD); 00067 Sleep(wait_tics); 00068 } 00069 MotorSpeed(0,0); 00070 }
void StartSwitch | ( | void | ) |
'Interrupt-Betrieb' zur Tastsensor Abfrage einschalten.
keine |
Definiert in Zeile 150 der Datei switches.c.
00151 { 00152 SWITCH_OFF; // Port-Bit auf LOW 00153 DDRD &= ~SWITCHES; // Port-Bit SWITCHES als INPUT 00154 MCUCR &= ~((1 << ISC11) | (1 << ISC10)); // Low level erzeugt Interrupt 00155 GICR |= (1 << INT1); // Externen Interrupt 1 zulassen 00156 }
void StatusLED | ( | unsigned char | color | ) | [inline] |
Steuert die (lustige) mehrfarbige Status-LED.
[in] | color | Zu setzende Farbe. [ OFF | GREEN | RED | YELLOW ] Bei einem nicht definierten Wert von 'color' aendert sich nichts an der LED. |
Definiert in Zeile 68 der Datei leds.c.
00070 { 00071 if (color == OFF) 00072 { 00073 GREEN_LED_OFF; 00074 RED_LED_OFF; 00075 } 00076 if (color == GREEN) 00077 { 00078 GREEN_LED_ON; 00079 RED_LED_OFF; 00080 } 00081 if (color == YELLOW) 00082 { 00083 GREEN_LED_ON; 00084 RED_LED_ON; 00085 } 00086 if (color == RED) 00087 { 00088 GREEN_LED_OFF; 00089 RED_LED_ON; 00090 } 00091 }
void StopSwitch | ( | void | ) |
'Interrupt-Betrieb' zur Tastsensor Abfrage anhalten.
keine |
Definiert in Zeile 179 der Datei switches.c.
void Turn | ( | int | degree, | |
int | speed | |||
) |
Dreht um einen bestimmten Winkel mit einer bestimmten Geschwindigkeit. (Autor: stochri)
Benutzt die Odometrie Sensoren im Interrupt Betrieb.
Vor dem ersten Aufruf muss deshalb EncoderInit() aufgerufen werden.
[in] | degree | Winkel (- rechts, + links) |
[in] | speed | Geschwindigkeit (Wertebereich 0...255) |
In der globale Variable encoder, werden die Hell-/Dunkelwechsel der
Encoderscheiben im Interruptbetrieb gezaehlt.
// Laesst den Asuro ein Quadrat von 200 mm fahren, // bei einer Geschwindigkeit von 150. EncoderInit (); for (int i = 0; i < 4; i++) { Go (200, 150); Turn (90, 150); }
Definiert in Zeile 411 der Datei encoder.c.
00414 { 00415 long enc_count; 00416 enc_count=abs(degree)*177L; 00417 enc_count /= 360L; 00418 00419 int tot_count = 0; 00420 int diff = 0; 00421 int l_speed = speed, r_speed = speed; 00422 00423 00424 EncoderSet(0,0); // reset encoder 00425 00426 MotorSpeed(l_speed,r_speed); 00427 if (degree<0) MotorDir(RWD,FWD); 00428 else MotorDir(FWD,RWD); 00429 00430 while (tot_count<enc_count) 00431 { 00432 tot_count += encoder[LEFT]; 00433 diff = encoder[LEFT] - encoder[RIGHT]; 00434 if (diff > 0) 00435 { //Left faster than right 00436 if ((l_speed > speed) || (r_speed > 244)) l_speed -= 10; 00437 else r_speed += 10; 00438 } 00439 if (diff < 0) 00440 { //Right faster than left 00441 if ((r_speed > speed) || (l_speed > 244)) r_speed -= 10; 00442 else l_speed += 10; 00443 } 00444 EncoderSet(0,0); // reset encoder 00445 MotorSpeed(l_speed,r_speed); 00446 Msleep(1); 00447 } 00448 MotorDir(BREAK,BREAK); 00449 Msleep(200); 00450 }
void UartPutc | ( | unsigned char | zeichen | ) |
Sendet einen einzelnen Character über die serielle Schnittstelle.
[in] | zeichen | auszugebendes Zeichen |
Definiert in Zeile 166 der Datei print.c.
00168 { 00169 UCSRB = 0x08; // enable transmitter 00170 UCSRA |= 0x40; // clear transmitter flag 00171 while (!(UCSRA & 0x20)) // wait for empty transmit buffer 00172 ; 00173 UDR = zeichen; 00174 while (!(UCSRA & 0x40)) // Wait for transmit complete flag (TXC) 00175 ; 00176 }
volatile int autoencode |
Steuert, ob die Odometrie-Sensor Abfrage im Interrupt Betrieb laufen soll.
volatile unsigned char count36kHz |
int encoder[2] |
Odometriesensor Zaehler bei Interrupt Betrieb.
encoder[0] links, encoder[1] = rechts.
int switched |
Flag, dass der Interrupt SIG_INTERRUPT1 durch eine gedrueckte Taste
ausgeloesst wurde. 0 = keine Taste, 1 = Taste gedrueckt.
Kann im eigenen Programm immer abgefragt werden.
volatile unsigned long timebase |