Вполне возможно, что часы складываются.
previousclock = millis () может застрять в высоком значении непосредственно перед сворачиванием.Вы можете расширить тест, включив в него случай, когда (currentmilis
BTW. Использовался исходный код игнаса (исходный код OP не читался без регистрации, и я не хочузарегистрировать)
РЕДАКТИРОВАТЬ: Я скопировал фрагмент ниже из wakkerbot, и немного отредактировал его.Это просто для демонстрации того, как с помощью wraparound ваши метки времени last_action застряли в верхней части интервала int (если значение bump не является делителем для int_max). Возможно, вы могли бы немного упростить логику выше / ниже, так как вас интересует тольковнутренние / внешние интервальные испытания.Конечно, typedef для Stamp должен быть адаптирован к типу millis () (unsigned long?) И fakemillis (), а ссылки на него заменены на millis ().
#include <stdio.h>
#define STAMP_INSIDE 0
#define STAMP_BELOW -1
#define STAMP_ABOVE 1
#define STAMP_BEYONDO -1
/* Intentionally very small, for fast wraparound
** Intentionally signed to stress test the logig.
*/
typedef signed char Stamp;
/* fake clock, returns incrementing value, but folds around
*/
Stamp fakemillis(void)
{
static Stamp ticker =0;
return ticker++;
}
/* Check if "test" is inside or above/below the interval {low,high}
** low and high may have been wrapped around zero (--> low > high)
** return
** 0 := "test" inside interval
** 1 := "test" below interval
** -1 := "test" above interval (but wrapped)
** The two impossible cases return -2.
*/
static int check_interval(Stamp low, Stamp high, Stamp test)
{
switch (4 *(high >= low)
+2 *(test >= low)
+1 *(test > high)
) {
case 0: return STAMP_INSIDE; /* inside (wrapped) */
case 1: /* outside (wrapped) */
return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;
case 2: break; /* impossible */
case 3: return STAMP_INSIDE; /* inside (wrapped) */
case 4: /* all below */
return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;
case 5: break; /* impossible */
case 6: return STAMP_INSIDE; /* inside normal case */
case 7: /* all above) */
return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;
}
return STAMP_BEYONDO;
}
/* Get new clock value, test if it is inside interval {*old, *old+width)
** iff inside: return STAMP_INSIDE;
** iff above (or below) return STAMP_ABOVE or STAMP_BELOW
** and UPDATE *old
*/
static int test_or_set(Stamp *old, Stamp width)
{
Stamp tick;
int diff;
tick = fakemillis();
diff = check_interval( *old, *old+width, tick);
if (!diff) return 0;
*old = tick;
return diff;
}
int main(void) {
Stamp goodlast=0;
Stamp tick=0;
Stamp badlast=0;
int goodtest;
int badtest;
unsigned uu;
for (uu = 0; uu < 260; uu++) {
tick= fakemillis();
if (tick > badlast+10) { badlast=tick; badtest=1; } else {badtest =0;}
goodtest = test_or_set ( &goodlast, 10);
printf("%x:Tick=%x bad=%x, badtest=%d good=%x goodtest=%d\n"
, uu, (unsigned) tick
, (unsigned) badlast, badtest
, (unsigned) goodlast, goodtest
);
}
return 0;
}
Если вы компилируете и запускаетевышеупомянутая программа на «нормальном» компьютере, вы можете увидеть, как плохое и самое плохое застревает.ИМХО, это то, что происходит и на вашем arduino.
Обновление: определенно переполнение / опрокидывание.(GIYF) http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1200662708
Update2: не связано, но плохая практика кодирования:
#define CMD_SET_SPEED "S"
...
/* Internal configuration */
if(buffer.substring(0,1)==CMD_SET_SPEED) {
updateSpeed(buffer.substring(1));
}
Здесь вы сравниваете две строки.(это может быть обработано, как задумано c ++, но в C это просто неправильно. Я бы также предложил заменить повторяющийся if (...) {...} гигантским оператором switch, который по крайней мере избежал бы вызовафункция substr () многократно. (или она встроенная?)
ОБНОВЛЕНИЕ 20111211: здесь есть функция сравнения и установки, не требующая переноса, для которой требуется указатель на значение для сравнения и установки, иширина предполагаемого интервала:
int test_and_set_if_beyond( unsigned long *pprev, unsigned long width )
{
unsigned long tick, low,high;
low = *pprev;
high = low+width;
tick = millis();
if (low < high) {
if (tick >= low && tick < high ) return 0; /* normal case */
}
else { /* interval is wrapped , clock could have wrapped */
if (tick >= low || tick < high) return 0;
}
*pprev = tick;
return 1;
}
Эта функция используется в разделе loop () следующим образом:
if (test_and_set_if_beyond ( &lightTimer, lightnessCheckPeriod)) {
int newLightness = analogRead(brightnessPin);
if(newLightness-lightness > LIGHT_TRESHOLD) {
say(RESPONSE_FLASH);
}
lightness = newLightness;
}
if (test_and_set_if_beyond ( &pingTimer, pingTimerPeriod)) {
say(RESPONSE_PING);
}
if (test_and_set_if_beyond ( &pingLEDTimer, pingTimerPeriod*2)) {
digitalWrite(failPin, HIGH);
}
feed();
Наконец: ИМХО причина, по которой RESET не работает, заключается вчто не все глобальные переменные инициализируются в функции setup (). Кроме того: я думаю, что вам следует избавиться от String Thessies (есть ли GC во время выполнения?) и использовать вместо этого обычные символьные буферы.