URL-tags funktionieren so:
Linktext
bitte an die anführungszeichen denken. achtung: zwischen den tags und dem linktext dürfen KEINE leerzeichen stehen! auch in den tags sind KEINE leerzeichen!
Druckbare Version
URL-tags funktionieren so:
Linktext
bitte an die anführungszeichen denken. achtung: zwischen den tags und dem linktext dürfen KEINE leerzeichen stehen! auch in den tags sind KEINE leerzeichen!
Ich bin ein wenig ratlos und habe die Lösung leider noch nicht gefunden.
Wenn ich das AMUL.hex von Osser übertrage, dann funktioniert sie auf meinem ASURO.
Daraufhin habe ich ein AVRStudio Projekt mit den Daten des ASUROs angelegt. Beim compilieren (avr-gcc (GCC) 4.1.1 (WinAVR 20070122)) kommen dann je nach dem welche Optimierung ich wähle eine unterschiedlich Anzahl an Warnungen.
Schlimmer ist jedoch, das der erzeugte Code nicht lauffähig ist.
Hat jemand eine Idee, was ich da falsch mache?
Viele Grüße Heiko
welche warunungen kommen denn? poste die mal im code-fenster.
Hier ein Beispiel: Compiliert mit der Optimierung -0s
Die erste Warnung ist mir klar.Code:Build started 21.5.2007 at 22:55:16
avr-gcc.exe -mmcu=atmega8 -Wall -gdwarf-2 -DF_CPU=8000000UL -Os -fsigned-char -MD -MP -MT omtasktest.o -MF dep/omtasktest.o.d -c ../omtasktest.c
In file included from ../omtasktest.c:32:
c:/winavr/bin/../avr/include/avr/signal.h:36:2: warning: #warning "This header file is obsolete. Use <avr/interrupt.h>."
In file included from ../omtasktest.c:35:
../omttask.h:34: warning: call-clobbered register used for global register variable
../omtasktest.c: In function 'main':
../omtasktest.c:166: warning: passing argument 1 of 'OMT_add_driver' from incompatible pointer type
avr-gcc.exe -mmcu=atmega8 omtasktest.o omtasuro.o omtdriver.o omtisrs.o omttask.o -o ASURO.elf
avr-objcopy -O ihex -R .eeprom ASURO.elf ASURO.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex ASURO.elf ASURO.eep || exit 0
c:\WinAVR\bin\avr-objcopy.exe: there are no sections to be copied!
AVR Memory Usage
----------------
Device: atmega8
Program: 2250 bytes (27.5% Full)
(.text + .data + .bootloader)
Data: 422 bytes (41.2% Full)
(.data + .bss + .noinit)
Build succeeded with 3 Warnings...
Hier mal ein Fragment meiner "Einfachst" Multitasking Strukur:Zitat:
Zitat von robo.fr
Grundsätzlich wird (fast) das gleiche wie bei robo.fr erreicht.Code:int main (void)
{
unsigned long v_time = 0;
unsigned long v_P1_lasttime = 0; // PROZESS: Tasten auswerten
#define d_P1_wartezeit 50; // Zeit in ms
unsigned long v_P2_lasttime = 0; // PROZESS: Status-LEDs blinken
#define d_P2_wartezeit 200;// Zeit in ms
unsigned char v_P2_LEDonoff = 0;
unsigned long v_P3_lasttime = 0; // PROZESS: Linien-Sensoren
#define d_P3_wartezeit 5; // Zeit in ms
unsigned int v_P3_line [2];
unsigned long v_P4_lasttime = 0; // PROZESS: PID-REGLER
#define d_P4_wartezeit 2; // Zeit in ms
Init ();
while (1)
{
/*----------------------------------------------------------------------
Zeitbasis fuer die Prozesse aktualisieren
*/
v_time = Gettime ();
/*----------------------------------------------------------------------
PROZESS: Tasten auswerten.
*/
if (v_time > v_P1_lasttime)
{
v_P1_lasttime = v_time + d_P1_wartezeit;
/*
Tasten lesen ...
*/
v_taster = PollSwitch ();
if (v_taster != 0)
{
// Mach was mit der Taste
}
}
/*----------------------------------------------------------------------
PROZESS: Status-LED blinken lassen
*/
if (v_time > v_P2_lasttime)
{
v_P2_lasttime = v_time + d_P2_wartezeit;
if (v_P2_LEDonoff)
LED_STATUS_YELLOW
else
LED_STATUS_OFF
v_P2_LEDonoff ^= 1;
}
/*----------------------------------------------------------------------
PROZESS: Linien-Sensoren
*/
if (v_time > v_P3_lasttime)
{
v_P3_lasttime = v_time + d_P3_wartezeit;
LineData (v_P3_line);
}
/*----------------------------------------------------------------------
PROZESS: PID-Regler
*/
if (v_time > v_P3_lasttime)
{
v_P3_lasttime = v_time + d_P3_wartezeit;
// Motorregler-Aufruf
}
/*----------------------------------------------------------------------
PERMANTER RECHENPROZESS
*/
// Volle Rechenleistung ist hier verfügbar, ohne sich um ein
// 'Timing' zu kümmern.
// Natürlich darf hier keine Endlosschleife sein.
}
}
Als großen Vorteil meiner Schreibweise sehe allerdings, dass ich einen 'Prozess' komplett innerhalb einer if-{ }-Struktur habe und es somit (auf alle Fälle für mich) übersichtlicher scheint.
Was ich aber auf alle Fälle für vorteilhaft halte, ist, dass bei mir die CPU immer die while(1)-Schleife durchläuft und nicht in ein Warten übergeht.
So besteht die Möglichkeit innerhalb der Schleife eine permanente Aufgabe mit 'Höchstgeschwindigkeit' bearbeiten zu lassen. Als Idee wäre da z.b. eine Strategieberechnung für eine Wegsuche.
Aber dadurch 'verliere' ich die Möglichkeit von 'Zeitabläufen' nach 10, 15, 50 (oder so) Einheiten bestimmte Dinge zu tun.
Da läßt sich doch bestimmt eine Kombination finden!
Edit: Man ist das blöd. Natürlich kann man die permante Aufgabe in die While-Schleife am Ende von robo.fr's Code stecken, wo er auf den Ablauf der kleinsten Zeiteinheit wartet!
Wenn nun auch alle Sensoren per Interrupt 'von alleine' ihre Dienste erledigen, ist alles 'fertig'. Das wollen wir natürlich keinesfalls ;-)
Da kann ich nur zustimmen, Das Prinzip ist mir zwar so einigermaßen klar, aber aktuell kann ich auch noch nicht finden wo da der beschrieben Fehler stecken soll. (Hab das Programm noch nicht bei mir laufen lassen. Erst (versuchen zu) verstehen, dann staunen)Zitat:
Zitat von robo.fr
Hallo Damaltor. Wenn ich die benutzte, dann geht es aber nicht. Hab sie jetzt weggelassen (wie immer).Zitat:
Zitat von damaltor
Hallo Sternthaler,
Deine Programmstruktur ist scheint mir tatsächlich etwas einfacher. Es liegt meiner Meinung nach daran, dass die Einzel-Tastks in Deinem Beispiel mit konstanter Wiederholrate aufgerufen werden.Zitat:
Als großen Vorteil meiner Schreibweise sehe allerdings, dass ich einen 'Prozess' komplett innerhalb einer if-{ }-Struktur habe und es somit (auf alle Fälle für mich) übersichtlicher scheint.
Bei mir sind die Einzeil-Tasks kleine State-Machines. Die States können einerseits von der Timer-Variblen zeitlich automatisch durchgezählt werden, oder man kann von einem Zustand in den anderen springen, indem man die Timervariable auf den Wert des entsprechenden Zustands setzt. Es kann auch ein automatischer Ablauf gestartet werden, wenn man die Timervarible auf den ersten Zustand setzt und beim Erreichen des letzten Zustand die Timervariable einfach nicht mehr weiterzählern lässt.
Eigentlich wird bei meiner Struktur ja auch die while-Schleife ständig durchlaufen. Die Wiederholrate ist aber auf 1/10 Sekunde beschränkt. Alle Programmteile innerhalb der While-Schleife werden also mit 1/10 Sekunde Wiederholrate aufgerufen. So z.B. auch der Schrittregler im 2.ten Beispiel. Ich denke, dass für die meisten Aktionen diese Geschwindigkeit ausreichen sollte.Zitat:
Was ich aber auf alle Fälle für vorteilhaft halte, ist, dass bei mir die CPU immer die while(1)-Schleife durchläuft und nicht in ein Warten übergeht.
Der Vorteil des Herunterbremsens auf 1/10 Sekunde ist, dass die Programmteile innerhalb der While-Schleife genügend Rechenzeitreserve haben, falls diese im Laufe der Programmentwicklung etwas wachsen sollten.
Man könnte die While-Schleife auch beschleunigen, ich habe sie nur "vorsichtshalber" so langsam gemacht.
Da hast Du recht, das habe ich auch irgendwann einmal festgestellt. Man kann in die zentrale Warteschleife für den 1/10 Sekundentakt tatsächlich etwas Schnelles reinstecken.Zitat:
Edit: Man ist das blöd. Natürlich kann man die permante Aufgabe in die While-Schleife am Ende von robo.fr's Code stecken, wo er auf den Ablauf der kleinsten Zeiteinheit wartet!
Gruss,
robo
Richtig, bei mir gibt es nur Prozesse/Tasks mit konstanten Aufrufzeiten. Bis jetzt hatte ich noch keine Verwendung für State-Machines.
Als einzig Ausnahme katte ich bisher immer nur die Abhängigkeit des Tasten-Tasks zum starten einer Aktion. Hier sollte immer erst 1 Sekunde gewartet werden bevor die Aktion loslegt, wenn die Taste LOSgelassen wurde.
Nur als Frage, so in den Raum:
Wenn man Osser's echte Tasks nutzen würde, was benötigt man dann als Task um eine Sekunde auf das LOSlassen einer Taste zu warten, um etwas anzustoßen? Im Moment kann ich mir da nix vorstellen.
@Volley
Ich habe gerade mal nach 'call-clobbered' gegoogelt. Tut mir leid, ich verstehe nicht was da gesagt wird.
Unter www.dict.cc wird als Übersetzung gehauen angegeben. Und nun?
Hallo Sternthaler,
Hier habe ich mal als Beispiel für ein Multitasking Programm gemacht, welches die Tastenabfrage benutzt.Zitat:
Als einzig Ausnahme katte ich bisher immer nur die Abhängigkeit des Tasten-Tasks zum starten einer Aktion. Hier sollte immer erst 1 Sekunde gewartet werden bevor die Aktion loslegt, wenn die Taste LOSgelassen wurde.
Der ASURO fährt durch die Gegend und blinkt gleichzeitig mit der StatusLED. Wenn er auf ein Hindernis stößt, stoppt er den StatusLED-TASK nicht aber den "Pendeltask" und startet den "Rückwärtsdrehen" Task.
Wenn er auf das Loslassen der Taste warten würde, bliebe er meiner Meinung nach an der Wand kleben.
Gruss,
robo
Ist klasse dein Programm.
Sanftes Richtungswechseln und vor allem blinkende LED. (Ich bin ein Fan von blinkenden Lampen, ohne läuft bei mir der Asuro nicht mehr)
Die Reaktionszeit der Taster ist hier auf alle Fälle ausreichend. Ich hatte es noch nie geschafft den Asuro so stark zu stoppen/rückwärts fahren zu lassen, dass er nicht mit der Platine an die Wand 'knallt', wenn ein Taster erkannt wurde. (OK, ganz, ganz langsam fahren, dann klappt das natürlich)
Bei mir laufen die Taster im Interrupt, so dass ich mich da überhaupt nicht im main() kümmern muss. Und in meiner Task-Variante läuft die Tasten-Info-Abfrage in der main-loop, so dass der Prozess zum stoppen eigendlich in 0-Zeit begonnen wird.
Trotzdem war meine Frage auf Osser's echtes Task-System gemünzt, und auch, dass nach dem LOSlassen der Taste erst noch eine sec gewartet werden muss. Mache ich mit Klimmzügen bis jetzt immer dann, wenn ich über die Tasten erst eine Auswahl der vom Asuro zu erledigenden Aufgabe auswählen will. (Finger auf Taste, Finger weg, jetzt warten, los gehts)
Wieso? Das geht doch schon! Siehe Thread:Zitat:
Wenn nun auch alle Sensoren per Interrupt 'von alleine' ihre Dienste erledigen, ist alles 'fertig'. Das wollen wir natürlich keinesfalls
interruptgesteuertes Auslesen aller AD-Wandlerkanäle
https://www.roboternetz.de/phpBB2/viewtopic.php?t=29958