..und im RoboDude gibt es auch eine neue Funktion:
Menuzeile -> Tools -> Reset MCU
Hiermit kann der Mikro Controller resettet werden, solange er mit dem PC verbunden ist.
Mit der Installation der neuen NiboRobolib wird leider noch die Doku der Lib Version 3.3 installiert
Deshalb hier ein paar Worte von mir vorab:
Leider ist - womöglich durch den Bug Fix "pwm calculation" - das Regelverhalten von motpid_setTargetRel(100,100,50) bei meinem Burger schlechter geworden:
Erstmal schiesst die PWM bis auf Maximum (1022) hoch, und dicht am Ziel (es fehlen 2 Ticks) geht's erstmal drüber hinaus, dann wieder rückwärts (aber auch zu weit), vorwärts (wieder knapp daneben), wieder rückwärts (und dann erst Punktlandung).
Sehr gut finde ich auch, dass es die Funktionen clock_elapsed_ms() und clock_get_systime_ms() gibt:
clock_get_systime_ms dürfte der *duino Funktion millis() entsprechen.
Wird clock_elapsed_ms() einmal in der Hauptschleife ("while(1==1) {..loop_duration = clock_elapsed_ms()..}") verwendet, wird deren Laufzeit gemessen.
Ohne delay() und xx_wait() sollte die Laufzeit so zwischen 0ms bis 3ms liegen.
Jetzt können unterschiedliche Wartezeiten parallel ablaufend programmiert werden:
Hier noch eine kleine Hilfsfunktion die vor main() einzufügen wäre
/////////////////////////////////////////////////////////////////////////
//
// Vergleichsfunktion liefert die Zeit (basetime - subtime) oder 0,
// wenn subtime >= basetime war. Mit dieser Funktion können
// "Eieruhren" für zeitgesteuerte Aktionen realisiert werden.
//
// #define LED1_OFF_TIME 400;
// #define LED1_ON_TIME 50;
//
// uint16_t led1_time = LED1_OFF_TIME;
// :
// // Dauer des letzten Schleifendurchlaufs
// loop_duration = clock_elapsed_ms();
// :
// if (led1_time = clock_get_event(led1_time, loop_duration) == 0) {
// // die Eieruhr ist abgelaufen
// if (led_get(LED_1)) {
// // LED leuchtet bereits -> abschalten
// led_set(LED_1, 0);
// // Aus-Zeit setzen
// led1_time = LED1_OFF_TIME;
// }
// else {
// // LED ist aus -> einschalten
// led_set(LED_1, 0);
// // Ein-Zeit setzen
// led1_time = LED1_ON_TIME;
// } // if led_get
// } // if clock_get_event
//
//
uint16_t clock_get_event(uint16_t basetime, uint16_t subtime) {
if (basetime > subtime) {
return (basetime - subtime);
}
else {
return 0;
}
} // clock_get_event
.und hier ein Teil der Hauptschleife in main()
while(1==1) {
// sei(); // is done within clock_elapsed_ms
//
// Laufzeit der Main_Loop:
// Aus der Variablen "clock_ms" ermittelte Zeitdifferenz entspricht
// der Laufzeit (Ausführungsdauer) der Hauptschleife.
//
loop_duration = clock_elapsed_ms();
//
// Von Autobahnbaustellenfahrzeugen inspiriertes
// Blinken der blauen LEDS
//
#define LED2_ON 50
#define LED2_OFF 200
#define LED3_ON 52
#define LED3_OFF 202
static uint16_t led2_interval = LED2_ON;
static uint16_t led3_interval = LED3_ON;
led2_interval = clock_get_event(led2_interval,loop_duration);
led3_interval = clock_get_event(led3_interval,loop_duration);
if (!led2_interval) {
if (led_get(2)) {
led_set(1,0);
led_set(2,0);
led2_interval = LED2_OFF;
} // if led_get()
else {
led_set(2,1);
led2_interval = LED2_ON;
} // else led_get()
} // if !led_interval
if (!led3_interval) {
if (led_get(3)) {
led_set(3,0);
led_set(4,0);
led3_interval = LED3_OFF;
} // if led_get()
else {
led_set(3,1);
led3_interval = LED3_ON;
} // else led_get()
} // if !led_interval
} // while(1==1)
Die beiden vorderen LEDs blinken in leicht unterschiedlicher Frequenz - versucht das mal mit delay() zu realisieren..
usart_rxavail() liefert jetzt die Anzahl der über den UART empfangenen Zeichen im Buffer - oK -
usart_txavail() klingt logisch, aber leider heisst die Funktion in Wirklichkeit usart_txfree()
Mit dieser Funktion kann man also vorher prüfen, ob die auszugebenden Zeichen überhaupt in den Ausgabebuffer passen; zur Erinnerung - wenn 6 Zeichen in den Buffer geschrieben werden sollen (z.Bsp. aktueller Inhalt einer int16 Variablen), aber nur Platz für zwei Zeichen ist, wartet die usart_sendefunktion bei jedem Zeichen, bis es in den Buffer passt - bei 9600 Baud dauert ein Zeichen ca.1ms (=(9600 Bit/sec) / (10,5 Bit/Zeichen) = 915 Zeichen/sec).
Nun das sieht ja nicht schlimm aus - wenn man nur eine Variable betrachtet - bei 8 Sensorwerten pro Schleifendurchlauf (bzw. alle 10ms) und den zusätzlichen Zeichen für "Neue Zeile" oder "Cursorpositionierung" wird es dann schon etwas länger dauern.
Ich habe mal eine Tabellenausgabe aller Sensorwerte in allen Modi (PASSIVE, ACTIVE, DIFFERENTIAL) programmiert, also 30 Werte (inkl. volt, key u. randomseed) die (fast) ständig aktualisiert werden, und das Blinken (siehe oben) auch noch funktioniert.. Damit die Durchlaufzeit der Hauptschleife möglichst kurz bleibt, wird vor jeder Ausgabe erst geprüft, ob genug Platz im Buffer ist; ansonsten wir die Routine wieder verlassen (break;) und erstmal etwas anderes im Programm ausgeführt.
Auszug aus dem switch(state)-Zweig
case 9: // Cursor für Ausgabe setzen
if (uart_txd_avail() > 8) {
// Cursorspalte für Tabellenspalte
curspalte = pgm_read_byte(&anatabs[tspalte] +1);
ansi_curpos(curzeile, curspalte);
test_share_state++;
} // if txd_avail
else break;
case 10: // Analogwert Ausgabe
if (uart_txd_avail() > 8) {
anaidx = pgm_read_byte(&zeilen[tzeile]);
if (tspalte == 0) {
print_u16d(analog_getValue(anaidx));
}
else if (tspalte == 1) {
print_u16d(surface_getAbs(anaidx));
}
else if (tspalte == 2) {
print_u16d(surface_get(anaidx));
}
test_share_state++;
} // if txd_avail
else break;