Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeitsteuerung für asuro
Hallo asurofreunde.da mein asuro mit 4 US-sensoren nun ewig ohne anzuecken durch die wohnung kurft,hab`ich mir überlegt,ob man eine zeitsteuerung ins US-prog.einflechten kann,sodass er z.B. nach einer frei wählbaren zeit selbst abschaltet,und nach dem nächsten einschalten die zeit wieder läuft.Habe leider keine peilung wie die befehlszeile aussehen muss,und ob die am anfang oder ende des prog. stehen muss.
Hat einer einen tipp,oder wurde das schon gefragt,und ich habs übersehen?
Dank und gruss Hans2
Wenn ich es jetzt richtig verstanden habe und du meinst, dass er einen bestimmten "Zeitwert" abspeichert, bevor man den ASURO ausschaltet und ihn dann weiter verwendet, dann geht das schon.
Versuch mal den Wert im EEPROM-Speicher vom ASURO abzuspeichern und nach dem Starten wieder einzulesen.
Falls du wissen möchtest, wie, musst du das schon selber rausfinden. 8-[ Ich kenn' mich nicht so gut mit dem EEPROM aus und hab die einzigen Befehle, die ich mal gesehen habe auch nicht mehr im Kopf. Aber guck' mal im Datenblatt vom ATMega8, da gibt's auf jeden Fall Informationen, oder hier (http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#EEPROM) müsste auch einiges an Infos vorhanden sein.
damaltor
18.03.2008, 02:45
wie der eeprom geht, weiss ich zwar. aber meinst du nicht, dass z.B. nach 10 minuten der asuro stehen bleibt, und nach dem nächsten start wieder 10 minuten fährt usw?
das liesse sich elegant über die vorhandene timebase lösen.
hallo damaltor,genau so dachte ich.er soll ca. 10 min. fahren,und sich dann selbst auschalten.dann mache ich den schalter aus,und stelle ihn weg. beim nächsten einschalten,soll er das gleiche wieder machen.wäre das möglich?.....gruss auch an d1ko.
Beste grüsse hans
du könntest auch einen timer einbauen, der nach zehn minuten den asuro in eine endlos sleep-schleife sichickt.
mfg liggi
Ach so, tut mir leid, ich hab' das irgendwie falsch verstanden. (Das EEPROM wirst du aber so oder so bei deinem Problem brauchen.^^)
Hier schon mal ein Ansatz, wie sich das lösen lässt:
(Ich benutze die alte ASURO-Library, also die, die auf der ASURO-CD mitgeliefert wird. Falls du die neue hast, lässt sich das Problem bestimmt ähnlich lösen (hoffe ich...).)
An deiner Stelle würde ich das Zählen einem Interrupt überlassen:
Öffne zuerst die Datei asuro.c (müsste in deinem ASURO-Verzeichnis unter ...\ASURO_src\FirstTry zu finden sein).
Dort müssten ziemlich am Anfang diese Zeilen stehen:
volatile unsigned char count72kHz;
/* uses timer2 (36kHz for IR communication */
/* counts falling and rising edge => 36kHz*2 = 72kHz */
SIGNAL (SIG_OUTPUT_COMPARE2)
{
count72kHz ++;
}
SIGNAL (SIG_OUTPUT_COMPARE2) ist ein Interrupt, der verwendet wird, um z.B in der Sleep-Funktion die 72kHz-Takte zu zählen. Immer, wenn eine 72.000stel Sekunde vorbei ist, wird der Interrupt ausgelöst, der den Counter inkrementiert. Die Sleep-Funktion sieht nebenbei so aus:
/* uses 72kHz timer => Sleep(x) = x/72kHz [sec] */
void Sleep(unsigned char time72kHz)
{
count72kHz = 0;
while (count72kHz < time72kHz);
}
Falls du dir den Rest dazu selber ausdenken möchtest, dann lies ab hier nicht mehr weiter :-$ .
Damit du jetzt die Zeit nach dem Einschalten zählen kannst, musst du nur noch in dem oben genannten Interrupt SIGNAL (SIG_OUTPUT_COMPARE2) einen Mechanismus einbauen, der zuerst die Millisekunden, Sekunden und dann die Minuten zählt. Wenn die gewünschte Zeit vorbei ist, sollte ein Flag im Interrupt aktiviert werden, den das Hauptprogramm benutzen kann.
Mehr verrat' ich nicht.^^
MFG D1K0
Hallo,d1ko,schade,dass du nicht mehr verrätst.Ich bin zwar gut im Elektronkbau,aber programmieren ist nicht meine stärke.Ich habe mir die aktuelle US-version runtergeladen,und in dem Prog,habe ich nur zeiten,drehrichtung,und geschwindigkeit geändert.Alles andere ist mir noch suspekt.Hatte gehofft,dass mir einer sagt,wo,und was ich ins dieses prog. einfügen muss.Gruss Hans aus bremen
Hallo Hans,
mit der schönen Funktion Gettime() aus der Lib 2.71 lässt sich eine Zeitsteuerung auch realisieren, wenn man sich mit Interrupts nicht auskennt:
der ASURO als Wecker (https://www.roboternetz.de/phpBB2/viewtopic.php?t=36431)
Gruss
M.
Hallo,d1ko,schade,dass du nicht mehr verrätst.Ich bin zwar gut im Elektronkbau,aber programmieren ist nicht meine stärke.Ich habe mir die aktuelle US-version runtergeladen,und in dem Prog,habe ich nur zeiten,drehrichtung,und geschwindigkeit geändert.Alles andere ist mir noch suspekt.Hatte gehofft,dass mir einer sagt,wo,und was ich ins dieses prog. einfügen muss.Gruss Hans aus bremen
Oh, ich dachte, ich hätte schon zuviel verraten und würde dir den Spaß verderben, wenn ich dir einfach den ganzen Code aufschreibe...
Also hier ein Lösungsvorschlag:
Im Interrupt wird wie oben erwähnt alles ausgerechnet:
D.h. du must in asuro.c folgendes ändern:
volatile unsigned char count72kHz = 0;
volatile unsigned int countmsec = 0;
volatile unsigned char countsec = 0;
volatile unsigned char countmin = 0;
volatile char flag = 0;
/* uses timer2 (36kHz for IR communication */
/* counts falling and rising edge => 36kHz*2 = 72kHz */
SIGNAL (SIG_OUTPUT_COMPARE2)
{
count72kHz ++;
if (count72kHz == 72)
{
countmsec++
count72kHz = 0;
}
if (countmsec == 1000)
{
countsec++;
countmsec = 0;
}
if (countsec == 60)
{
countmin++;
countsec = 0;
}
if (countmin == 10)
{
flag = 1;
}
}
Dadurch 10 Minuten nach dem Einschalten der Flag gesetzt.
(Man könnte auch Speicherplatz sparen und nur mit countsec die gewünschte Zeit in Sekunden angeben, aber ich hab es zur Demonstration einfach mal auch mit Minutenzähler gemacht.)
Du wolltest ja, dass er nach 10 Minuten nichts mehr macht. Dazu musst du im Hauptprogramm einfach den Flag in eine if-Schleife einbauen, in der eine Endlosschleife eingebaut ist.^^
Sieht dann so aus:
if (flag ==1)
{
// Motor etc. abschalten
while(1);
}
Das muss dann an irgendeiner Stelle in der Endlosschleife deines Programms eingebaut werden. (Es soll also ständig abgefragt werden.)
Mit dem Programm macht der ASURO also nach 10min nichts mehr.
Damit er die Zeit nach dem Einschalten weiter hochzählen kann, muss man den countmin-Wert vor dem Abschalten im EEPROM abspeichern und nach dem Einschalten auslesen und weiter hochzählen lassen.
Wie das mit dem EEPROM geht, weiß ich leider auch nicht genau.
Hoffe, ich konnte dir trotzdem helfen.
MFG D1K0
EDIT:
Sorry, ich hab vergessen die Millisekunden im Interrupt hochzuzählen (72 * 1000 Takte pro Sekunde). ](*,) .
Hab' das jetzt geändert. Ach ja, das Programm habe ich nicht getestet, ich weiß deshalb nicht, ob irgendwo ein Fehler drinsteckt oder nicht.
Hallo D1KO,ich hab`mir deinen vorschlag angeschaut,und hab`noch ne frage.Dein prog. bezieht sich aur IR,und ich spreche von Ultraschall.Das verwirrt mich nun.Vielleicht kannst du mir das nochmal erläutern.ob das trotzdem so ginge.
Danke und gruss
Hans2
Hallo D1KO,ich hab`mir deinen vorschlag angeschaut,und hab`noch ne frage.Dein prog. bezieht sich aur IR,und ich spreche von Ultraschall.Das verwirrt mich nun.Vielleicht kannst du mir das nochmal erläutern.ob das trotzdem so ginge.
Danke und gruss
Hans2
Ich denke, du beziehst dich auf den Teil:
/* uses timer2 (36kHz for IR communication */
/* counts falling and rising edge => 36kHz*2 = 72kHz */
Das hat nichts mit Infrarotsensoren zu tun, sondern mit der Infrarotkommunikation zwischen ASURO und PC. Es wird Timer2 benutzt und wenn ich das jetzt richtig verstanden habe, wird der auch bei der IR-Kommunikation verwendet.
Wenn du nicht die count72kHz-Variable auch für deine Ultraschallsensoren benutzt, müsste es eigentlich gehen.
Falls doch kannst du z.B. die Variable, die du für deine Sensoren brauchst in ucount72kHz umbenennen, sodass du dann eine Variable für den Ultraschall hast und eine für den 10min-Zähler.
Am Besten du testest es erst mal und sagst uns, ob es klappt oder nicht.
Aha,verstehe,ich werde testen
Danke Hans2
Moin, ich krame diesen Threat mal aus, da ich ein ähnliches Problem hab:
Ich möchte eine kontrollierte zeit lang eine Schleife ausführen und danach eine kontrollierte zeit lang eine andere Schleife ausführen.
ich hab mir verschiedene Threats durchgelesen und die hier beschriebene Lösung war die, die ich am meisten Verstand^^
Ich habe in der asuro.c folgendes geändert:
von:
volatile unsigned char count72kHz;
/* uses timer2 (36kHz for IR communication */
/* counts falling and rising edge => 36kHz*2 = 72kHz */
SIGNAL (SIG_OUTPUT_COMPARE2)
{
count72kHz ++;
}
in:
volatile unsigned char count72kHz;
volatile int flag = 0;
/* uses timer2 (36kHz for IR communication */
/* counts falling and rising edge => 36kHz*2 = 72kHz */
SIGNAL (SIG_OUTPUT_COMPARE2)
{
count72kHz ++;
flag=count72kHz;
}
Im Hauptprogramm sieht das bei mir folgendermaßen aus:
#include "asuro.h"
#include "Funktionen.h"
#define XGRENZE 630 //560 ohne Motoren
#define YGRENZE 650 //573 ohne Motoren
int main(void)
{
int count72kHz;
Init();
while (flag<72000)
{
StatusLED(GREEN);
WaitM(50);
StatusLED(RED);
WaitM(50);
}
flag = 0;
while (flag<144000)
{
StatusLED(GREEN);
WaitM(500);
StatusLED(RED);
WaitM(500);
}
while(1);
return 0;
}
Das ding ist, beim compilieren sagt der mir, das die variable flag unbekannt ist.
wie bekomm ich das hin?
was mache ich genau falsch?
accControl
09.12.2008, 22:37
soweit ich sehen kann, hast du die variable flag auch nicht definiert, zumindest hast du uns den teil vom code nicht mitgeschickt
um sowohl von der interrupt routine in asuro.c als auch von deinem hauptprogramm auf die variable flag zugreiffen zu können, musst du eine globale variable im asuro.c machen; diese musst du außerdem als 'volatile' deklarieren, da du auf diese sonst keinen zugriff hast
das heißt du schreibst im asuro.h
unsigned volatile long flag = 0;
und kannst dann auf sie zugreiffen
btw, das ist nicht der sinn eines flags
ein flag zeigt eine zustandsänderung an, das heißt du zählst in der interrupt-routine bis 72k und setzt dann das flag auf 1 (dann reicht auch ein char/integer) und fragst im hauptprogramm nur ab, ob das flag auf 1 oder 0 ist
sobald das flag auf 1 ist, reagierst du darauf und setzt es wieder auf 0 zurück, damit du die nächste zustandsänderung wieder erfassen kannst
mehr zu flags hier: http://de.wikipedia.org/wiki/Flag_(Informatik)
EDIT: ok, hab übersehen, dass du das flag definiert hast
du musst es auch in der asuro.h angeben, sonst findet das hauptprogramm die variable nicht.
dein nächstes problem sein, dass ein integer den wertebereich von -32k bis +32k annehmen kann und du somit nie auf einen wert von 72k kommen wirst - verwende einen long
hi, erstmal vielen dank
wie würdest du denn mein Problem sonst lösen?
wieso muss ich da volatile hinschreiben?
Arbeite relativ kurz erst mit c, hab davor, nur Software fürn pc mit Delphi geschrieben.
und wie genau mache ich eine globale variable?
accControl
10.12.2008, 14:14
wie würdest du denn mein Problem sonst lösen?
in der interrupt-routine solange eine variable inkrementieren, bis du auf 72000 bist, und wenn du auf 72000 bist dann das flag auf 1 setzen
im hauptprogramm baust du eine abfrage ein, die sobald das flag auf 1 ist ausgeführt wird, flag 1 auf 0 setzt (sonst 'meint dein hauptprogramm das du bei jedem durchlauf auf 72000 bist') und schreibst in diese abfrage dann das, was du sonst tust wenn flag auf 72000 ist
wieso muss ich da volatile hinschreiben?
nachdem du geschrieben hast, dass du erst am beginn mit C bist ist das jetzt nicht sehr einfach zu erklären
im prinzip musst du das hinschreiben, damit beide funktionen (hauptfunktion und interruptroutine) darauf zugreiffen und diese ändern können
und wie genau mache ich eine globale variable?
die globale variable hast du schon definiert, dass ist die volatile int flag;
eine globale variable ist eine variable, die auch außerhalb der funktion gültigkeit hat und somit von allen funktionen verwendet werden kann (gegenteil: lokale variable)
Falls es je,anden interessiert:
So sieht jetzt mein Timer aus:
So in der asuro.c
unsigned volatile char count72kHz;
unsigned volatile int countkhz,countmsek,countsek;
/* uses timer2 (36kHz for IR communication */
/* counts falling and rising edge => 36kHz*2 = 72kHz */
SIGNAL (SIG_OUTPUT_COMPARE2)
{
count72kHz ++;
countkhz ++;
if (countkhz == 72)
{
countmsek++;
countkhz = 0;
}
if (countmsek == 1000)
{
countsek++;
countmsek = 0;
countkhz = 0;
}
}
und im Hauptprogramm wird das folgendermaßen benutzt:
#include "asuro.h"
#include "Funktionen.h"
int main(void)
{
Init();
countsek=0;
while (countsek<10)
{
StatusLED(RED);
WaitM(100);
StatusLED(GREEN);
WaitM(100);
}
StatusLED(OFF);
WaitS(1);
countkhz=0;
countmsek=0;
countsek=0;
while (countsek<5)
{
StatusLED(GREEN);
WaitM(500);
StatusLED(RED);
WaitM(500);
}
StatusLED(OFF);
while(1);
return 0;
}
Das bewirkt, dass die StatusLED 10 Sekunden lang schnell bilinkt und danach 5 Sekunden lang langsamer.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.