Genauso sehe ich das. Ich hatte angenommen, dass bestehende Lösungen ein Hinweis für eure gesuchten Lösungen sein könnten.Zitat:
Zitat von Lisbeth2010
Druckbare Version
Genauso sehe ich das. Ich hatte angenommen, dass bestehende Lösungen ein Hinweis für eure gesuchten Lösungen sein könnten.Zitat:
Zitat von Lisbeth2010
Hallo oberallgeier,
Chapeau!
Habe erstmal nur die von dir angegebenen Punkte gelesen, werde aber den Thread mal in Ruhe ab Seite 1 lesen.
Genau das ist der Punkt:Zitat:
... Für meinem Nibobee habe ich so eine Regelung nicht gebaut. Da ist soviel Bibliothekszeug drin, ...
Grundsätzlich sind die Nibos so vorbereitet, dass sie eigentlich einen sehr einfachen Einstieg bieten sollen. Leider ist dazu die Doku noch nicht wirklich fertig und stellt den Einsteiger recht schnell vor große Hürden. (Die große Frage für den Programmierer: Was mache ich zuerst - die Doku oder das nächste Update :-k )
Für etwas fortgeschrittene Anwender sind die Libs dann wieder etwas zu unflexibel, vielleicht auch nur, weil Libs / FWs zu schwach beschrieben sind, bzw. der Funktionsumfang nicht komplett offengelegt ist, oder ergänzungswürdig ist.
Um eigene Libs / FWs zu schreiben muss man dann Experte oder Profi sein.
(Das soll keine negative Kritik sein, das ist meine Einschätzung aus meinem Erwartungs-/Betrachtungswinkel.)
Hier aber erst einmal mein persönlicher Status:
Ich selbst komme aus der hardwarenahen Programmierung für Industrieanwendungen. Hardwarenah bedeutet hierbei die Nutzung vorgefertigter Libs zu eingesetzten Komponenten. C kenne ich aus der Programmierung von Visualisierungen, aber ohne besonders zeitkritische Funktionsanforderung.
Meine Nibos sind meine ersten Kontakte mit der prozessornahen Programmierung, bin da im Frühjahr 2010 recht blauäugig herangegangen. (Ziel war es, die Nibos im Bereich der Ausbildung einzusetzen: erster Kontakt mit Elektronik und Löten, erster Kontakt mit Programmierung.)
Seit dem grabe ich mich durch die Libs, Studio4 mit seinen "Configuration Options" und die umfangreichen Datenblätter der Prozessoren. Das ist spannend, aber auch sehr zeitintensiv. Bin somit grundsätzlich im Thema, bei der programmtechnischen Umsetzung aber sicherlich noch Anfänger.
Da die Prozessoren beim Nibo2 in SMD-Ausführung verbaut sind, ist zumindest der Zugriff auf den ATmega88 (ohne nicht ganz ungefährliche Lötarbeiten) nur über den I²C-Flaschenhals möglich.
Hallo Lisbeth2010,
da workwind nun ein eigenes Forum aktiviert hat, stellt sich die Frage, wie weit und umfangreich er hier noch aktiv sein möchte und ob er auch die Zeit hat, zwei Foren zu betreuen.
Das ist zwar leider kompliziert, aber es wäre nicht schön, hier in diesem Forum Mitglieder abzuwerben, andererseits habe ich aber auch Verständnis, wenn workwind sein eigenes Forum bevorzugt. Ich hoffe, dass sich dazu ein brauchbarer Kompromiss finden wird.
Grundsätzlich wurde das Thema hier geboren, also gehört auch hier die Zusammenfassung hin.
Wenn eine Antwort von workwind ausbleibt, dann sollten wir ersteinmal zweigleisig fahren und die Einverständnis von workwind abfragen, seine Antworten hier zittieren zu dürfen.
Hallo!
Frage: Warum hat workwind Zeit ein eigenes Forum zu erstellen, zu betreuen usw., aber offensichtlich keine Zeit, die einzigen aktiven User (so ca. 5-10) mit ein paar Zusatzinformationen zu füttern?
Ich bin gerade noch damit beschäftigt, mehr Infos zu den Bodensensoren und deren Einsatz zu sammeln (absorbieren), deshalb bitte ich um ein wenig Geduld, bis ich wieder etwas "emittieren" kann.
Mein persönlicher Status: Physiker und technischer Informatiker mit Kenntnis des Atmel Prozessors AT90CAN128 und stolzer Besitzer eines ASUROs (selbst gelötet!!!), der allerdings für mein derzeitiges Projekt etwas zu schwach ist.
Noch etwas: Danke für die bisherigen Inputs!
Lisbeth2010
Hi
@oberallgeier - starker tobak, Donnerwetter! Muß ich in Ruhe "verdauen" - wie hast Du denn die Plots hinbekommen (mit welchem Programm aufgezeichnet/ausgewertet)?
@Lisbeth2010 - gemäß Deinem letzen Beitrag hast Du den ASURO - somit erübrigt sich mein penetrantes Fragen nach dem Bremsweg
@elektrolutz -die Bodensensoren SIND für die Erkennung eines Abgrundes - und dienen somit der Absturzerkennung. IMHO ist die Fkt copro_stop() bzw deren Übermittelung perI²C nicht ok, denn es ist bei mir mehrmals vorgekommen, daß der NIBO2 NICHT gestoppt hat, obwohl die Bedingung dafür vorhanden war - habe dies auch dem Hersteller gemeldet. Außerdem hatte ich mal irgendwo gelesen, daß die Übermittlung per I²C nur alle 10ms läuft - das ist aber nix für eine schnelle Regelung btw...und wenn ich die ISR mit dem Aufruf von copro_stop() alle 20ms tätige....
Hast DU jetzt schon mal den Bremsweg gemessen?
die einzig saubere Möglichkeit, das hinzubekommen ist:
- die Regelung läuft auf dem programmierbaren (per ISP) Atmega88
- es wird jeder Motor EINZELN geregelt
- der Atmega88 liest die Bodensensoren SELBST ein
->das alles GEHT DERZEIT NICHT => damit ist für mich das Thema erledigt
zum Thema "eigenes Forum" - da muß ich Lisbeth2010 recht geben...
mfg
Hero_123
Merci, de rien.Zitat:
Zitat von elektrolutz
Danke für die Anerkennung, es freut mich, dass es euch gefällt, hoffentlich nutzt es etwas, da ich ja keine Coprozessortechnik habe. Aber so bekommt ihr vermutlich einen Einblick über Reaktionsgeschwindigkeit bzw. Strecke-je-Tick, über die Regelungswirksamkeit insbes. beim Bremsen, verschiedene Bremsmöglichkeiten und so.Zitat:
Zitat von Hero_123
Auswertung und Darstellung: Aufzeichnung zeitgetreu in entsprechend große Felder, nach Ablauf des Testlaufs bzw. der Messung Übertragung per UART ans Terminal. Auswertung mit dem vermutlich weltweit meistgenutzten Simulatons- und Auswerteprogramm für technische Vorgänge - Excel. Vorgehensweise ist hier ausführlicher beschrieben.
Ganz meine Meinung. Damit das nicht zu sehr den normalen Programmablauf beeinflusst, läuft bei mir die Regelung der beiden Motoren zeitlich versetzt - mal der eine, mal der andere - siehe erstes Codefenster im Link. Übrigens regelt der asuro AFAIK nur einen "gemittelten" Motor und "schummelt" durch einen offset die Unterschiede rein.Zitat:
Zitat von Hero_123
[OT]Reg elungstechnik war für mich ziemlich mühselig. Ne vierLoch in der Klausur - vor vielen Jahren - deutet ja auf keine allzugroße Liebe hin. Aber wenns mal sein muss, dann muss man eben. Übrigens gibt es bei mir noch ungelöste Details - aber eher Nachkommastellen - die mir Kopfzerbrechen machen und deren Lösungsversuch ich schiebe und schiebe und schiebe. Stichwort dazu z.B. lückenlose und drehrichtungstreue Tickbilanzierung, damit Entfernung- und Richtungsrechnung genauer werden und fast nur noch der Räderschlupf als Fehlerquelle bleibt.[/OT]
Hallo zusammen,
bin gerade mal die Belegung des CoProz laut Schaltplan durchgegangen.
Der ist bis zum letzten Pin ausgereizt.
Leider sind die etwas zeitunkritischeren 5 Abstandsensoren auf den CoProz verdrahtet und die zeitkritischen Absturzsensoren liegen auf dem HauptProz. Hier möchte ich als einigermaßen erfahrener Löter aber nicht herumbrutzeln.
Mit recht überschaubarem Lötaufwand könnte man aber die Absturzsensoren fühlerartig mit schmalen Adapterplatinen in Fahrtrichtung vor den Nibo2 verlegen. Den im ungünstigsten Fall nur 20mm kurzen Bremsweg (3 Löcher auf der Odo-Scheibe - Mitte Sensoren bis Mitte Gleitpad) könnte man so recht einfach mindestens verdoppeln.
@Hero_123,
meine Anmerkung zu den Bodensensoren als Absturzsicherung war mit etwas Sarkasmus gespickt. O:)
Mit dem Bremsentest tüftel ich derzeit noch ein wenig herun. Habe beobachtet, dass die Erkennung eines Abgrundes durch die Sensoren durch einige Faktoren drastisch unterschiedlich ausfällt. Offensichtlich beeinflusst das Umgebungslicht die Erkennung der Sensoren nicht unerheblich, auch scheinen fremde IR-Quellen die Sensoren zu stören. Größtes Problem ist aber die plausible Erkennung einer Tischkannte, bei einer rechtwinklig geschnittenen Holzplatte (ca. 15mm stark) wird der Abgrund erst richtig erkannt, wenn der jeweilige Sensor schon ca. 5-10mm über den Rand hinaus ragt - bedeutet, der zulässige Bremsweg verkürzt sich um diese 5-10mm. Bei meiner realen Tischkannte am Arbeitstisch ist die Kannte abgerundet, ab Beginn der Abrundung ragt der Sensor zur sicheren Erkennung bis zu 15mm hinaus - der Bremsweg bis Mitte Gleitpad dann im ungünstigsten Fall nur noch 5mm.
Diese Werte habe ich durch händisches Verschieben meines Nibo2 ermittelt.
Simuliere ich den Abgrund durch eine schwarze Fläche verhält sich die Sensorerkennung nicht vergleichbar zu einer Tischkannte und reagiert zudem auf matte und glänzende Oberflächen sehr unterschiedlich.
So suche ich erst mal nach einer Lösung, den tatsächlichen Bremsweg als Wegstrecke mit einem Messstab nachmessen zu können.
Ich suche also nach einer Lösung, den Sichtbereich der Sensoren zu begrenzen und gleichzeitig die Einwirkungen fremder Lichtquellen abzuschotten, ohne dabei die Bodenfreiheit zu stark einzuschränken. Muss mal schauen, was ich aus schwarzen Pinselborsten machen kann.
Hi elektrolutz
Bodensensoren beim NIBO2 - der Einfluß des Streulichtes/Umgebungslichtes ist klar, da die Sensoren ja nicht abgeschirmt sind (da weist der Hersteller aber irgendwo in seiner Doku drauf hin). Abschirmung - gute Idee. Sensoren weiter nach vorne zu verlagern -> Ändern der HW (naja!!) -> Abstandserkennung muß darauf angepasst werden (ist sw-technisch kein Problem)
Sinnvollerweise müßten sowohl Boden- als auch Abstandssensoren beim Atmega88 eingelesen und verarbeitet werden. Regelung müßte auch geändert werden, ebenso ISP für den Atmega88-> FAZIT es muß ein NIBO3 her ;)
mfg
Hero_123
Ich könnte eine Funktion zum "aktiven" Bremsen in den COPRO bzw. MOTCO Code einbauen: Der Strom würde solange in entgegengesetzter Richtung fliessen, bis die Ticks von der Odometrie das erste mal in die andere Richtung gezählt würden. Danach würde der jeweilige Motor direkt abgestellt werden. Damit sollte der Roboter nahezu direkt anhalten...
Hallo workwind,
das hört sich sehr gut an.
Das wäre dann ein neuer Befehl, der aus einer Interrupt-Routine aufgerufen werden kann und die Interrupt-Verarbeitung nicht abschaltet!
Hi
Funktion zum "aktiven Bremsen" - sie muß NICHT ZWINGEND (!!) in einer timergesteuerten ISR aufgerufen werden, es reicht doch schon, wenn der Aufruf DIREKT nach Erkennen des Absturzes geschieht! Die ISR ist doch NUR EIN PFLASTER!!!
Interrupt-Verarbeitung - bei (derzeit) nahezu allen Fkt des copro wird die Interruptbehandlung während der Befehlsausführung abgeschaltet...
@workwind - entspricht dein Vorschlag des "aktiven Bremsens" nicht in etwa dem, daß man beim Erkennen des Absturzes negative Drehzahl als neuen Sollwert vorgeben soll?
mfg
Hero_123
Hallo
hätte da auch noch einen Vorschlag zu machen. Das mit dem negativen lauf finde ich richtig gut. Falls ein neuer Befehl verwendet wird ist es vielleicht besser diesen zu teilen. Wenn ich aus anderen Gründen das zählen der Ticks nich verwende, muss trotzdem ein stoppen erfolgen. Dazu könnte ich bei auslösen des stoppens eine bestimmte Zeitspanne, vielleicht 5 mS negativen strom geben. Man kann auch diese Zeit einstellbar machen, so von... bis. Man könnte dei Rückgabe der Ticks nach Stop auch als Wert zurückgeben. Damit könnte eine Längenmessung nach Stop erfolgen. Es währe auch nicht schlecht mal ein bisschen besser Beispiel oder Kommentare zu geben. Wenn die Befehle immer komplexer werden, dann beherschen nur noch wenige den genauen Programmablauf. Eigentlich soll der Nibo 2 doch was für Anfänger und Könner wein.
Achim
Das hatte ich in diesem Thread bereits angeregt:Zitat:
Zitat von oberallgeier am 01 Dez 2010, 0:20
Nein. Oder ganz präzise: jedenfalls nicht bei mir.Zitat:
Zitat von workwind am 04 Dez um 18:17
Das kommt auf die Regelung an. Also darauf, wie die Regelung im Einzelnen aufgebaut ist. Aber eine gute Regelung sollte ja nicht brutal und abrupt reagieren, wie das mit der von mir vorgeschlagenen Schubumkehr der Fall ist von der jetzt auch workwind spricht.Zitat:
Zitat von Hero_123
Hallo @All,
kann mir jemand bei der Verwendung der copro (motco) Funktionen helfen? copro_setTargetAbs(l,r,s) oder motco_setPosition(l,r,s).
Ich habe ein freeRTOS Beispiel für den Nibo. Läßt 2 LEDs in 2 verschiedenen Tasks mit unterschiedlicher Dauer blinken. Ist das vielleicht auch für andere User interessant?
Kann unter AVR Studio 4 auch in der Simulation laufen. Da sieht man dann auf PORTE mal schwarze und mal weiße Kästchen.
Mit den anderen Themen bin ich noch nicht weitergekommen, bleibe aber dran.
Lisbeth2010
Hallo Lisbeth
Komme mit deiner Frage nicht so klar. Du gibst den Befehle
copro_setTargetAbs(l,r,s) oder motco_setPosition(l,r,s).
an. Habe in meine Befehlsliste gesehen und im Internet nachgeschaut, da stehen die aber nicht drin. Sind mir nicht bekannt oder habe sie bisher übersehen.
An deinem Prg habe ich auf jeden Fall Interesse. Kannst es mir direkt mailen oder reinstellen.
Achim
Hallo Achim S.,
schau mal hier:
http://nibo.svn.sourceforge.net/viewvc/nibo/trunk/src/
Viele Grüße
Lisbeth2010
Hallo Lisbeth2010,
hier die Befehlsbeschreibung entsprechend Lib2.8:
Wo ist das Problem? Für "left" und "right" werden die gewünschen Zielwerte eingegeben und für "speed" die max. Geschwindigkeit. "Absolut" bedeutet, dass die Räder ihr Ziel von der derzeit aktuellen Zählerposition aus anfahren. Ist das Ziel kleiner der aktuellen Position, dann fährt das Rad also rückwärts.Zitat:
uint8_t copro_setTargetAbs ( int16_t left, int16_t right, uint16_t speed )
Zielposition für Räder setzen. Die Werte werden in Ticks angegeben. 40 Ticks entsprechen einer Radumdrehung.
Parameter:
left absoluter Sollwert für linkes Rad
right absoluter Sollwert für rechets Rad
speed Wert für maximale Geschwindigkeit
Wird benutzt von nibocc::Copro::set_target_abs().
Beim "...Rel..."-Befehl erfolgt die Positionierung um den angegebenen Wert bezogen auf die aktuelle Position.
Ob die Funktion beim Nibo1 "Abs" oder "Rel" ist, leider keine Ahnung. Müsste man ausprobieren, beim Nibo1 müsste dann aber vor dem Befehl noch eine entsprechende Bearbeitung des Zählers erfolgen, die bei Programmübertragung auf den Nibo2 entfallen sollte.
Das mit dem freeRTOS schaue ich mir mal an.
freeRTOS: ziemlich viele Dateien. Wie kann man das am Besten "posten"?
Viele Grüße
Lisbeth2010
@Lisbeth2010
bin doch etwas erstaunt - die Verwendung der Befehle steht doch in den doc-files der jeweiligen lib... "wer des Lesens mächtig..." ;)
freeRTOS - da sind wohl nicht nur die files, sondern doch etwas MEHR nötig
- eine Installationsbeschreibung
- eine Beschreibung der Befehle
- eine Einbindung in die NIBOLIB
- usw....
- oder bist Du da anderer Meinung?
woher hast du das freeRTOS (weblink etc)?
poste doch mal deinen Code!
mfg
Hero_123
Hallo!
Lesen kann ich, was soll das also?
Hier mal ein Video:
http://www.youtube.com/watch?v=SjmQ5mHueG8
1. Durchdrehen
2. Stoppen an einem Isolierband
Falls es jemand interessiert, der Code
Viele Grüße Lisbeth2010Code:/* Laufstall 04.12.2010 - IW
Boden: Fliese hellgrau
Umrandung: schwarzes Isolierband 15 mm breit
nur innerhalb der Umrandung rumfahren
*/
#include <avr/interrupt.h>
#include <nibo/niboconfig.h>
#include <nibo/iodefs.h>
#include <nibo/bot.h>
#include <nibo/i2cmaster.h>
#include <nibo/leds.h>
#include <nibo/delay.h>
#include <nibo/motco.h>
#include <nibo/irco.h>
#include <nibo/floor.h>
#include <nibo/adc.h>
/* eigene Funktion Zahlausgabe binär 0..63 */
int16_t wert;
void zahlausgabe(int16_t wert) {
if ((wert - 32) > 0) {
leds_set_status(LEDS_GREEN, 5);
wert = wert - 32;
} else {
leds_set_status(LEDS_OFF, 5);
}
if ((wert - 16) > 0) {
leds_set_status(LEDS_GREEN, 4);
wert = wert - 16;
} else {
leds_set_status(LEDS_OFF, 4);
}
if ((wert - 8) > 0) {
leds_set_status(LEDS_GREEN,3);
wert = wert - 8;
} else {
leds_set_status(LEDS_OFF,3);
}
if ((wert - 4)> 0) {
leds_set_status(LEDS_GREEN,2);
wert = wert - 4;
} else {
leds_set_status(LEDS_OFF,2);
}
if ((wert - 2)> 0) {
leds_set_status(LEDS_GREEN,1);
wert = wert - 2;
} else {
leds_set_status(LEDS_OFF,1);
}
if ((wert - 1)> 0) {
leds_set_status(LEDS_GREEN,0);
} else {
leds_set_status(LEDS_OFF,0);
}
} // end Zahlausgabe
/* eigene Funktion floor_measure() 2x wg. erster AD-Wandlung */
int16_t floor_mw[4];
void floor_measure_iw() {
floor_enable_ir();
floor_mw[0] = 1023-adc_read(0); // Bodensensor von oben in Fahrtrichtung rechts
floor_mw[1] = 1023-adc_read(1); // Bodensensor von oben in Fahrtrichtung links
floor_mw[2] = 1023-adc_read(2); // Liniensensor von oben in Fahrtrichtung links
floor_mw[3] = 1023-adc_read(3); // Liniensensor von oben in Fahrtrichtung rechts
//nochmal, wir haben ja Zeit...
floor_mw[0] = 1023-adc_read(0); // Bodensensor von oben in Fahrtrichtung rechts
floor_mw[1] = 1023-adc_read(1); // Bodensensor von oben in Fahrtrichtung links
floor_mw[2] = 1023-adc_read(2); // Liniensensor von oben in Fahrtrichtung links
floor_mw[3] = 1023-adc_read(3); // Liniensensor von oben in Fahrtrichtung rechts
floor_disable_ir();
}
/*-----------*/
/* Laufstall */
/*-----------*/
uint8_t speed_left = 100; // Ticks/Sekunde Testwert
uint8_t speed_right = 100; // Ticks/Sekunde Testwert
uint16_t floor_left;
uint16_t floor_right;
void laufstall() {
floor_left = floor_mw[1]/16;
floor_right = floor_mw[0]/16;
//zahlausgabe(floor_right); // da kein Display! keine negativen Werte!
// floor_left auf gelb: 7, auf schwarz: 0, auf Fliese 6, auf Fuge 3
// floor_right auf gelb: 8, auf schwarz: 0, auf Fliese 6, auf Fuge 3
if ((floor_left < 2) || (floor_right < 2)) { //ABGRUND: STOP
leds_set_status(LEDS_ORANGE,0);
leds_set_status(LEDS_ORANGE,5);
motco_stop();
motco_update();
delay(1000);
motco_setSpeed(-50, -50);
motco_update();
delay(1000);
motco_stop();
motco_update();
} else {
leds_set_status(LEDS_GREEN,0);
leds_set_status(LEDS_GREEN,5);
motco_setSpeed(speed_left,speed_right);
motco_update();
}
} // end laufstall
#define WHILE_1_TIME_GRID 10
uint8_t counter_2ms;
// ------------------------------------------------------------
// ---------- init timer2 -------------------------------------
// ------------------------------------------------------------
void init_timer2(void) {
TCCR2 = 0x00; // normal port operation
TCNT2 = 0x83; // set count value (131)
}
// ------------------------------------------------------------
// ---------- start timer2 ------------------------------------
// ------------------------------------------------------------
void start_timer2(void) {
cli(); // disable global interrupts
counter_2ms = 0;
// Datenblatt falsch!! S. 106 Table 56
TCCR2 |= 0x04; // CS02 = 1; CS01 = 0; CS00 = 1 -> clk/256
TIMSK |= (1<<TOIE2); //0x01; // enable timer overflow interrupt
sei(); // enable global interrupts
}
// ------------------------------------------------------------
// ---------- stop timer2 -------------------------------------
// ------------------------------------------------------------
void stop_timer2(void) {
cli(); // disable global interrupts
TCCR2 &= ~0x05; // stop timer
TIMSK &= ~(1<<TOIE2); // disable timer overflow interrupt
sei(); // enable global interrupts
}
// ------------------------------------------------------------
// ---------- timer2 ISR --------------------------------------
// ------------------------------------------------------------
ISR(TIMER2_OVF_vect) { // timer2 overflow
// reload counter value high byte; 0x83 corresponds to 1ms
// clk/128 entspricht 125 kHz entspricht 8 us
// Datenblatt falsch! clk/256 = 0x04 0 => 2ms
TCNT2 = 0x83; // 131 bis 256 also 125 mal 16 us
counter_2ms++;
if (counter_2ms >= WHILE_1_TIME_GRID) {
stop_timer2(); // Zeitdauer unbekannt, deshalb stoppen
// Bodensensoren messen (2 mal)
floor_measure_iw(); // schwarz = 0, weiß = 1023 bzw. 63=1023/16 Integer!
laufstall();
counter_2ms = 0;
start_timer2(); // alles abgearbeitet
} // end if counter
} // end ISR
/* die main */
int main() {
sei();
bot_init();
i2c_init();
leds_init();
floor_init();
init_timer2();
leds_set_status(LEDS_GREEN,5);
delay(2000); // damit er nicht gleich losrast!
leds_set_status(LEDS_OFF,5);
motco_setSpeedParameters(5,4,6); // Empfehlung vom "Chef"
start_timer2();
while (1) {
// tu was.. oder nix
delay(10000);
}
return 0;
}
Hallo nochmal,
wenn ich
//motco_setSpeed(-50, -50);
motco_setPosition(-20,-20, 20);
das Auskommentierte durch ...setPosition... ersetze, fährt Nibo eben nicht!!! rückwärts. Das war die Frage nach dem "Befehl".
Grüß Dich, workwind!
Die Lisbeth2010
Hallo Lisbeth2010,
Du rufst aus dem Interrupt-Context die delay() Funktion auf! Da es sich um einen Timer-IRQ handelt, kann während des delays ein weiterer IRQ ausgelöst werden - das gibt Chaos auf dem Stack....
Es ist sicherer im Timer-IRQ nur ein Flag zu setzen, und in der main-Funktion auf dieses Flag zu warten um von dort die laufstall() Funktion aufzurufen.
Das Flag muss dabei volatile definiert werden, da ansonsten der Optimizer die Zugriffe aus der main Funktion auf die Variable wegoptimiert.
Interrupt-Programmierung hat so seine Tücken!
Code:
volatile uint8_t timer_flag;
...
ISR(TIMER2_OVF_vect) { // timer2 overflow
...
counter_2ms++;
if (counter_2ms >= WHILE_1_TIME_GRID) {
timer_flag = 1;
counter_2ms = 0;
}
}
...
int main() {
...
while (1) {
if (timer_flag) {
floor_measure_iw();
laufstall();
timer_flag=0;
}
}
}
Hast Du gesehen, dass ich den Timer AUSSCHALTE?
Die Lisbeth2010
Ach ja, hier noch der freeRTOS Link:
http://elk.informatik.fh-augsburg.de...icz_thesis.pdf
Die Lisbeth2010
motco_setPosition hängt von den aktuellen Odometriewerten ab. Du solltest motco_resetOdometry(0, 0) vorher aufrufen, damit motco_setPosition(-20,-20, 20) die Räder rechts und links um 20 Ticks zurückgedreht.
//motco_setSpeed(-50, -50);
motco_resetOdometry(0, 0);
motco_setPosition(-20, -20, 20);
motco_update();
... geht auch nicht!
Die Lisbeth2010
Gegenprobe:
motco_setSpeed(-50, -50);
//motco_resetOdometry(0, 0);
//motco_setPosition(-20, -20, 20);
motco_update();
...geht!
Die Lisbeth2010
Geht denn Folgendes?
motco_resetOdometry(20, 20);
motco_setPosition(0, 0, 20);
motco_resetOdometry(20, 20);
motco_setPosition(0, 0, 20);
//motco_setSpeed(-50, -50);
//motco_resetOdometry(0, 0);
//motco_setPosition(-20, -20, 20);
motco_update();
... geht auch nicht!
"... geht auch nicht!" heisst er zuckt nicht einmal - oder bewegt er sich so wie er nicht soll?
Zuck nicht mal!
@Lisbeth2010
Dein "laufstall" - interessantes Programm.....hmhm....ja - aber warum alles in der timer-ISR?
der link zu freeRTOS..hm, ja...
freeRTOS - wolltest Du nicht den code posten, wo LEDS mittels freeRTOS unterschiedlich blinken? Einige User interessiert dieser Code bestimmt
mfg
Hero_123
Hallo Lisbeth2010,
Ich habe den Fehler im Motco Code gefunden, Du bekommst in Kürze einen neuen Initializer um die Motco Firmware zu updaten...
@workwind: Habe keine Erfahrung im Updaten der Firmware. Bitte Instruktionen für Nibo ohne Index!
@Hero_123:
"aber warum alles in der timer-ISR?" damit das Stoppen am Abgrund = Isolierband" funktioniert!!!!
"Einige User interessiert dieser Code bestimmt" nun ja,fix und fertige SW ist ja immer "interessant". Ich mach das hier hobbymäßig!! Ich hab auch nur die Information aus dem Link gehabt und einen Nibo!
Also nicht drängeln und nörgeln!
Die Lisbeth2010
Hier mal ein Screenshot der eingebundenen freeRTOS Dateien.
Und hier der Code der main.c, die hier freeRTOSminimal.c heißt. Das Programm hält an einer schwarzen Linie (Isolierband) an und fährt zurück. Der 2. Task schaltet nur eine LED. Als Zugabe: Binäre Ausgabe einer Zahl zwischen 0 und 63.
Danke auch an cypax.net, der das so oder ähnlich schon mal für den ASURO gemacht hat.
Das hex-File hat 31 kByte.
Für Nibo2 muß motco durch copro ersetzt werden.Code:/* FUNKTIONIERT!!! 09.12.2010 IW*/
#include <avr/interrupt.h>
#include "FreeRTOS.h"
#include "task.h"
#include <nibo/niboconfig.h>
#include <nibo/iodefs.h>
#include <nibo/bot.h>
#include <nibo/i2cmaster.h>
#include <nibo/leds.h>
#include <nibo/delay.h>
#include <nibo/floor.h>
#include <nibo/adc.h>
#include <nibo/motco.h>
int y = 1;
// a struct to pass parameters to tasks
typedef struct LED_PARAMETERS {
unsigned int LED; //the LED the task should use
unsigned int FlashRate; //the rate at which the LED should flash
} xLEDParameters;
//a simple function to set DDR-registers and initial state of the LEDs
void Init(void);
//this function starts two tasks
void StartLEDFlashTasks(unsigned char uxPriority);
//1st task
void TASK1(void *pvParameters);
//2nd task
void TASK2(void *pvParameters);
// Binäre Ausgabe auf LED
void zahlausgabe(int16_t wert);
// Bodensensoren messen
void floor_measure_iw();
// anhalten an Isolierband
void laufstall(void);
int main(void) {
Init();
bot_init();
i2c_init();
leds_init();
floor_init();
StartLEDFlashTasks (1);
// Start Scheduler
vTaskStartScheduler();
return 0;
}
void vApplicationIdleHook(void) {
y++;
}
//A simple function to set DDR-registers and initial state of the LEDs
void Init(void) {
// Set port E direction to outputs. (LED RED Nibo)
DDRE = 0xFC;
PORTE &= ~((1<<PE7) || (1<<PE6)); // aus (Startbedingung)
}
void StartLEDFlashTasks(unsigned char uxPriority){
//pointer to struct to pass task parameters
xLEDParameters *pxLEDParameters;
//FlashRate for 1st task
const unsigned int FlashRate1 = 2000/portTICK_RATE_MS;
//FlashRate for 2nd task
const unsigned int FlashRate2 = 4000/portTICK_RATE_MS;
// Create and complete the structure used to pass parameters to the next Created task.
pxLEDParameters = (xLEDParameters *) pvPortMalloc(sizeof(xLEDParameters));
pxLEDParameters->LED = (1<<PE7); //1st task will use LED on pin PE7
pxLEDParameters->FlashRate = FlashRate1;
// Create the task.
xTaskCreate(TASK1, (signed char *) "TASK1", configMINIMAL_STACK_SIZE, (void *) pxLEDParameters, uxPriority, (xTaskHandle *) NULL );
// Create and complete the structure used to pass parameters to the next Created task.
pxLEDParameters = (xLEDParameters *) pvPortMalloc( sizeof( xLEDParameters ) );
pxLEDParameters->LED = (1<<PE6); //2nd task will use LED on pin PE6
pxLEDParameters->FlashRate = FlashRate2;
// Create the task.
xTaskCreate(TASK2, (signed char *) "TASK2", configMINIMAL_STACK_SIZE, (void *) pxLEDParameters, uxPriority, (xTaskHandle *) NULL );
}
void TASK2(void* pvParameters) {
xLEDParameters *pxParameters;
pxParameters = (xLEDParameters *) pvParameters;
while(1) {
PORTE = PORTE | (pxParameters->LED);
vTaskDelay(pxParameters->FlashRate/2);
PORTE = PORTE & ~(pxParameters->LED);
vTaskDelay(pxParameters->FlashRate/2);
}
}
void TASK1(void* pvParameters) {
xLEDParameters *pxParameters;
pxParameters = (xLEDParameters *) pvParameters;
while(1){
floor_measure_iw(); // schwarz = 0, weiß = 1023 bzw. 63=1023/16 Integer!
laufstall();
}
}
/* eigene Funktion Zahlausgabe binär 0..63 */
int16_t wert;
void zahlausgabe(int16_t wert) {
if ((wert - 32) > 0) {
leds_set_status(LEDS_GREEN, 5);
wert = wert - 32;
} else {
leds_set_status(LEDS_OFF, 5);
}
if ((wert - 16) > 0) {
leds_set_status(LEDS_GREEN, 4);
wert = wert - 16;
} else {
leds_set_status(LEDS_OFF, 4);
}
if ((wert - 8) > 0) {
leds_set_status(LEDS_GREEN,3);
wert = wert - 8;
} else {
leds_set_status(LEDS_OFF,3);
}
if ((wert - 4)> 0) {
leds_set_status(LEDS_GREEN,2);
wert = wert - 4;
} else {
leds_set_status(LEDS_OFF,2);
}
if ((wert - 2)> 0) {
leds_set_status(LEDS_GREEN,1);
wert = wert - 2;
} else {
leds_set_status(LEDS_OFF,1);
}
if ((wert - 1)> 0) {
leds_set_status(LEDS_GREEN,0);
} else {
leds_set_status(LEDS_OFF,0);
}
} // end Zahlausgabe
/* eigene Funktion floor_measure() 2x wg. erster AD-Wandlung */
int16_t floor_mw[4];
void floor_measure_iw() {
floor_enable_ir();
floor_mw[0] = 1023-adc_read(0); // Bodensensor von oben in Fahrtrichtung rechts
floor_mw[1] = 1023-adc_read(1); // Bodensensor von oben in Fahrtrichtung links
floor_mw[2] = 1023-adc_read(2); // Liniensensor von oben in Fahrtrichtung links
floor_mw[3] = 1023-adc_read(3); // Liniensensor von oben in Fahrtrichtung rechts
//nochmal, wir haben ja Zeit...
floor_mw[0] = 1023-adc_read(0); // Bodensensor von oben in Fahrtrichtung rechts
floor_mw[1] = 1023-adc_read(1); // Bodensensor von oben in Fahrtrichtung links
floor_mw[2] = 1023-adc_read(2); // Liniensensor von oben in Fahrtrichtung links
floor_mw[3] = 1023-adc_read(3); // Liniensensor von oben in Fahrtrichtung rechts
floor_disable_ir();
}
/*-----------*/
/* Laufstall */
/*-----------*/
uint8_t speed_left = 20; // Ticks/Sekunde Testwert
uint8_t speed_right = 20; // Ticks/Sekunde Testwert
uint16_t taskdelay = 2000;
uint16_t floor_left;
uint16_t floor_right;
void laufstall() {
floor_left = floor_mw[1]/16;
floor_right = floor_mw[0]/16;
//zahlausgabe(floor_right); // da kein Display! keine negativen Werte!
// floor_left auf gelb: 7, auf schwarz: 0, auf Fliese 6, auf Fuge 3
// floor_right auf gelb: 8, auf schwarz: 0, auf Fliese 6, auf Fuge 3
if ((floor_left < 2) || (floor_right < 2)) { //ABGRUND: STOP und zurück
leds_set_status(LEDS_ORANGE,0);
leds_set_status(LEDS_ORANGE,5);
motco_stop();
motco_update();
vTaskDelay(taskdelay);
motco_setSpeed(-speed_left/2, -speed_right/2);
motco_update();
vTaskDelay(taskdelay);
motco_stop();
motco_update();
} else {
leds_set_status(LEDS_GREEN,0);
leds_set_status(LEDS_GREEN,5);
motco_setSpeed(speed_left, speed_right);
motco_update();
}
} // end laufstall
Die Lisbeth2010
@Lisbeth2010
- beim ersten c-File war in der main nur das delay(10000) -> da ist IMHO keine ISR nötigZitat:
damit das Stoppen am Abgrund = Isolierband" funktioniert!!!!
Du hattest selbst am 07.12 Code bezgl freeRTOS und den LEDS angebotenZitat:
"Einige User interessiert dieser Code bestimmt"
ne, haste recht, das rentiert sich nicht :(Zitat:
Also nicht drängeln und nörgeln!
- naja, unter "fix und fertige SW" versteht jeder was anderes - und Deinen Code kann man eh nur nutzen, wenn man das dafür passende freeRTOS installiert hat - also was solls...Zitat:
nun ja,fix und fertige SW ist ja immer "interessant".
Was meinst Du damit?Zitat:
und Deinen Code kann man eh nur nutzen, wenn man das dafür passende freeRTOS installiert hat - also was solls...
Die Lisbeth2010
Hab eben erst nochmal Deine Antworten richtig gelesen:
Zu Punkt 1: [Sarkasmus an] Nö, das wäre auch IMHO nicht nötig gewesen. Solle "nur" zeigen, daß unabhängig von dem Interrupt irgendetwas passieren kann. [Sarkasmus aus].
Zu Punkt 4: freeRTOS ist für alle da: Kernel UNABHÄNGIG vom Professor .. 'tschuldigung: Prozessor.
Nix für ungut sagt die Lisbeth2010
@workwind: Updates???
Bin noch bei motco_stopImmediate() ....
@Lisbeth2010
- hast also doch Probleme mit dem Lesen, habe NIE in Frage gestellt, ob freeRTOS für alle da istZitat:
Zu Punkt 4: freeRTOS ist für alle da: Kernel UNABHÄNGIG vom Professor .. 'tschuldigung: Prozessor.
und wegen "drängeln und nörgeln" ->denke, damit sollten wir es belassen, s'wird langsam kindisch, und für einen"flamewar" sollten wir beide das Forum nicht nutzenZitat:
@workwind: Updates???
vielleicht bekommst Du ja doch noch das, was du willst....