-
RP6 - Stopwatch
Hallo zusammen,
ich hab seit ein paar Tagen einen RP6 und bin gerade dabei mich mit ihm bzw. der Robotertechnik im Allgemeinen anzufreunden.
Heute hab ich mich ein wenig mit der Stopwatch beschäftigt und dabei ein eigenartiges Phänomen festgestellt.
Hier ein einfaches Programm das die Stopwatch1 verwendet um alle 600ms die LEDS paarweise weiterlaufen zu lassen
Code:
#include "RP6RobotBaseLib.h" // The RP6 Robot Base Library.
int main(void)
{
initRobotBase();
writeString_P("Do some LED stuff!\n");
startStopwatch1();
uint8_t runningLight = 9;
uint16_t stopVal = 0;
while(true)
{
stopVal = getStopwatch1();
if (stopVal > 600)
{
writeInteger(getStopwatch1(), DEC);
writeChar('\n');
writeInteger(stopVal, DEC);
writeChar('\n');
writeChar('\n');
setLEDs(runningLight);
runningLight <<= 1;
if(runningLight > 36)
runningLight = 9;
setStopwatch1(0);
}
}
return 0;
}
Dazu habe ich mir eine Ausgabe eingebaut um den Wert der Stopwatch zu sehen.
Unerwarteterweise sieht jetzt der Output auf der Konsole so aus:
Code:
[READY]
Do some LED stuff!
601
601
601
601
601
601
601
601
601
601
512
767
512
767
512
767
601
601
das heißt der Wert den die Stopwatch liefert stimmt nicht immer mit dem Wert in der Variable (die eigentlich auch den Stopwatch-Wert haben sollte) überein.
Gibt es dafür eine plausible erklärung? :-k
danke schon mal im voraus,
Gruß,
Martin
-
Hallo
Code:
#include "RP6RobotBaseLib.h" // The RP6 Robot Base Library.
int main(void)
{
initRobotBase();
writeString_P("Do some LED stuff!\n");
startStopwatch1();
uint8_t runningLight = 9;
uint16_t stopVal = 0;
while(true)
{
cli();
stopVal = getStopwatch1();
sei();
if (stopVal > 600)
{
writeInteger(getStopwatch1(), DEC);
writeChar('\n');
writeInteger(stopVal, DEC);
writeChar('\n');
writeChar('\n');
setLEDs(runningLight);
runningLight <<= 1;
if(runningLight > 36)
runningLight = 9;
setStopwatch1(0);
}
}
return 0;
}
Genau bei stopVal = getStopwatch1(); tritt ein ISR-Aufruf auf. Das Highbyte der StopWatch ist schon erhöht, das Lowbyte noch nicht:
511 ist binär 01 11111111
512 ist binär 10 00000000
767 ist binär 10 11111111
Deshalb ist stopVal größer als 600 und die Stoppuhr aber immer noch kleiner als 600 ;)
Das Stichwort heißt "atomar".
Eigentlich logisch, aber das hat bisher noch keiner bemerkt. Glückwunsch!
Gruß
mic
[Edit]
Code:
#include "RP6RobotBaseLib.h" // The RP6 Robot Base Library.
int main(void)
{
initRobotBase();
startStopwatch1();
while(true)
{
if (getStopwatch1() > 600)
{
writeInteger(getStopwatch1(), DEC);
if(getStopwatch1() < 601) writeChar('*');
writeChar('\n');
setStopwatch1(0);
}
}
return 0;
}
Code:
#include "RP6RobotBaseLib.h" // The RP6 Robot Base Library.
int main(void)
{
initRobotBase();
startStopwatch1();
while(true)
{
cli();
if (getStopwatch1() > 600)
{
sei();
writeInteger(getStopwatch1(), DEC);
if(getStopwatch1() < 601) writeChar('*');
writeChar('\n');
setStopwatch1(0);
}
else sei();
}
return 0;
}
Schlanker und schneller wäre wohl ein schlichtes
}
sei();
anstelle von
}
else sei();
-
Dankeschön radbruch - für die Hilfe und die Glückwünsche :)
da hätte ich sonst wohl noch länger daran zu grübeln gehabt
mfG,
Martin
-
...dabei drängt sich noch folgende Frage auf: empfiehlt es sich dann generell vor timer-abfragen interrupts zu blockieren?
weil "verloren gehen" sollten sie ja ohnehin nicht wenn ich sie nachher mit sei() wieder freigebe
mfG,
Martin
-
Hallo
Ob man die Interrupts bei StopWatch-Abfragen generell sperren sollte hängt wohl in erster Linie von der geforderten Genauigkeit der Anwendung und dem gewählten Zeitintervall ab. Wenn man die Interrupts nicht sperren will, könnte man den Effekt auch mit einer kleinen Plausibilitätsprüfung vermeiden:
Code:
#include "RP6RobotBaseLib.h" // The RP6 Robot Base Library.
int main(void)
{
initRobotBase();
writeString_P("Do some LED stuff!\n");
startStopwatch1();
uint8_t runningLight = 9;
uint16_t stopVal = 0;
while(true)
{
stopVal = getStopwatch1();
if(stopVal != getStopwatch1())
stopVal = getStopwatch1();
if (stopVal > 600)
{
writeInteger(getStopwatch1(), DEC);
writeChar('\n');
writeInteger(stopVal, DEC);
writeChar('\n');
writeChar('\n');
setLEDs(runningLight);
runningLight <<= 1;
if(runningLight > 36)
runningLight = 9;
setStopwatch1(0);
}
}
return 0;
}
Entweder stört der Interrupt die erste Zuweisung oder die If-Abfrage oder er tritt dazwischen auf. In allen Fällen wird dann die zweite Zuweisung nicht mehr gestört sein. Oder der Interrupt stört gar nicht, dann ist schon die erste Zuweisung erfolgreich gewesen.
Oder allgemein:
Code:
#include "RP6RobotBaseLib.h" // The RP6 Robot Base Library.
int main(void)
{
initRobotBase();
startStopwatch1();
while(true)
{
if ((getStopwatch1() > 600) && (getStopwatch1() > 600))
{
writeInteger(getStopwatch1(), DEC);
if(getStopwatch1() < 601) writeChar('*');
writeChar('\n');
setStopwatch1(0);
}
}
return 0;
}
Gruß
mic
-
alles klar - danke nochmal für die Hilfe :)
mfG,
Martin