Задержка без Delay и переполнения счетчиков.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

В теме http://arduino.ru/forum/programmirovanie/mertsaet-displei-128kh64 прошло бурное обсуждение кода задержек без Delay.

Мною предлагалось использовать код 

unsigned long CTime01;

unsigned long LTime01;
void setup()
{;}
void loop()
{ 

    CTime01 = millis();
    if (CTime01 >= (LTime01 +1000)) //задержка 1с
    {
     //Тут обновляем
     LTime01 = CTime01;  
    }
}

На что пошли возражения про переполнение переменной LTime01. Предлагалось использовать код 

     if( millis() - t > interval )    
    {                               
        { action; }                 
        t = millis();               
    }      
         

Но этот код не учитывает время выполнения функции { action; }

Мои эксперименты подтвердили переплнение http://arduino.ru/forum/programmirovanie/mertsaet-displei-128kh64#comment-162410

Сейчас запустил с проверкой 

i = millis()
if(  max(i,t)-min(i,t) > interval )  

Жду...

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Okmor пишет:

Жду...

красавчик... ждёт он.

всё уже украдено проверено до вас

// 4294967294 - 4294967284 = 10
// 4294967295 - 4294967285 = 10
// 0          - 4294967286 = 10
// 1          - 4294967287 = 10
// 2          - 4294967288 = 10
// 3          - 4294967289 = 10
// 4          - 4294967290 = 10
// 5          - 4294967291 = 10
// 6          - 4294967292 = 10
// 7          - 4294967293 = 10
// 8          - 4294967294 = 10
// 9          - 4294967295 = 10
// 10         - 0          = 10
// 11         - 1          = 10

// тест переполнения unsigned long millis().
// проверка корректности условия if (nm - m > 10) когда m считано до переполнения millis(), nm - после переполнения.

// результат проверки - корректно переползаем переполнение из "до" в "после":

// 4294967294 - 4294967284 = 10
// 4294967295 - 4294967285 = 10
// 0          - 4294967286 = 10
// 1          - 4294967287 = 10
// 2          - 4294967288 = 10
// 3          - 4294967289 = 10
// 4          - 4294967290 = 10
// 5          - 4294967291 = 10
// 6          - 4294967292 = 10
// 7          - 4294967293 = 10
// 8          - 4294967294 = 10
// 9          - 4294967295 = 10
// 10         - 0          = 10
// 11         - 1          = 10


#include <DigiUSB.h>

// unsigned long 0 - 4294967295

unsigned long m  = 4294967283; // 10 миллисекунд до переполнения.
unsigned long nm = 4294967293; // 1 миллисекунд до переполнения.

void setup() {

DigiUSB.begin();

int n = 0;

while(n < 14){

if (DigiUSB.tx_remaining() > 40) { // проверка места в буфере USB.
++n;
++m;
++nm;

DigiUSB.print(nm);
DigiUSB.print(" - ");
DigiUSB.print(m);
DigiUSB.print(" = ");
DigiUSB.println(nm - m); // здесь предполагаем получить 10, если условие отрабатывается корректно.

DigiUSB.delay(1);

}

DigiUSB.delay(1);

}

}

void loop() {DigiUSB.delay(1);}

 

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Следующие исправления предложенные ЕвгенийП отработали коректно.

unsigned long CTime01;
unsigned long LTime01;
unsigned long CurM;
unsigned long PriorM;
void setup()
{
  Serial.begin(9600);
  ;}
void loop()
{ 
    CTime01 = micros();
    if(  max(CTime01,LTime01)-min(CTime01,LTime01) > 1000000 ) 
    {
     //*********************Тут что то делаем**************************
     CurM = millis(); 
     Serial.println("LTlong= "+String((long)LTime01)+"  LT= "+String(LTime01)+"   millis()= "+String(CurM)+ " Delay="+String(CurM-PriorM)); 
     PriorM = CurM; 
     //*********************Тут что то делаем**************************
LTime01 = CTime01; } }


Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

И конечный вариант:

unsigned long CTime01;
unsigned long LTime01;
void setup()
{
  Serial.begin(9600);
  ;}
void loop()
{ 
    CTime01 = micros();
    if(  max(CTime01,LTime01)-min(CTime01,LTime01) > 1000000 ) 
    {
     Serial.println("OK");
     LTime01 = CTime01;
    }
}

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Правильней было бы инициализировать LTime01 не нулем, а, хотя бы в конце setup LTime01 = micros(). Впрочем это всего лишь рекомендация, поскольку задача абстрактная и требуемые точности к первому интервалу не описаны.

 

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Okmor пишет:

Следующие исправления предложенные ЕвгенийП отработали коректно.

при чём тут Евгений, если тебе достаточно понять в теории и убедиться на практике, что 0 - 4294967286 = 10 когда 0 и 4294967286 имеют тип unsigned long.

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Okmor, правильный вариант (a-b)>c, ты утверждаешь, что правильно a>(b+c). С точки зрения высшей математики оба неравенства верны. Но мы имеем дело с программированием МК и с ограничением количества разрядов. Раз уж ты инженер-механик, давай в понятиях близких к механике рассмотрим в чем твоя ошибка. Допустим 'a' и 'b' это расстояния от 0 до 99, 'с' это интервал. Возьмем:

a=5 b=2 c=10  5-2<10 и 5<2+10 оба неравенства верны

a=95 b=92 c=10 95-92<10 и 95<92+10 во втором случае переход через ноль 92+10=2, твое неравенство ложно.

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

Okmor пишет:

На что пошли возражения про переполнение переменной LTime01. Предлагалось использовать код 

     if( millis() - t > interval )    
    {                               
        { action; }                 
        t = millis();               
    }      
         

Но этот код не учитывает время выполнения функции { action; }

ну, не учитывает - Лешак так видит.

не нужно считывать два раза millis() там, где это не требуется.

unsigned long nt = millis();
if( nt - t > interval ) {t = nt; 
{action;}
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Okmor пишет:

Следующие исправления предложенные ЕвгенийП 

Я предлагал использовать min и max? Это гнусная клевета! Я никогда не предлагал такой глупости! Требую извинений!

Я в отличе от Вас знаю как устроена арифметика, и знаю, что достаточно просто вычитать длинные числа (хоть они unsigned, хоть нет - это всё равно) и сравнивать разность с заданным интервалом. При этом всё будет отлично работать и плевать на переполнение. Собственно, так и устроен пример "блинк без делэй" на этом сайте, который Вы никак понять не можете. Как там учитывать время исполнения я тоже знаю.

И не приписывайте мне чужие глупости, я и своих достаточно совершаю!

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

ЕвгенийП пишет:

Требую извинений!

Рамзан Кадыров одобряет этот пост. :D

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

ЕвгенийП пишет:

Как там учитывать время исполнения я тоже знаю.

блин. я не могу въехать в каком месте блинка без делау вылазит проблема времени исполнения кода?

и так и эдак смотрел - в упор не вижу проблемы.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

ЕвгенийП пишет:

Okmor пишет:

Следующие исправления предложенные ЕвгенийП 

Я предлагал использовать min и max? Это гнусная клевета! Я никогда не предлагал такой глупости! Требую извинений!

Я в отличе от Вас знаю как устроена арифметика, и знаю, что достаточно просто вычитать длинные числа (хоть они unsigned, хоть нет - это всё равно) и сравнивать разность с заданным интервалом. При этом всё будет отлично работать и плевать на переполнение. Собственно, так и устроен пример "блинк без делэй" на этом сайте, который Вы никак понять не можете. Как там учитывать время исполнения я тоже знаю.

И не приписывайте мне чужие глупости, я и своих достаточно совершаю!

Извините ЕвгенийП.  -Вы цитировали пост vde69. Думаю так будет правильней.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Клапауций 322 пишет:

Okmor пишет:

Следующие исправления предложенные ЕвгенийП отработали коректно.

при чём тут Евгений, если тебе достаточно понять в теории и убедиться на практике, что 0 - 4294967286 = 10 когда 0 и 4294967286 имеют тип unsigned long.

10 плюсов не получается  поставить Клапауций 322 за упрорство и сдержанность  ;)

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

trembo пишет:

10 плюсов не получается  поставить Клапауций 322 за упрорство и сдержанность  ;)

достаточно сделать 10 аккаунтов tremboХХХ... и, ты личный читер Клапауция.

*кстати, почему я сам себя любимого могу плюсовать и минусовать? блин - я самокритичный и скромный.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Okmor пишет:

Извините ЕвгенийП.  -Вы цитировали пост vde69. Думаю так будет правильней.

 

Я цитировал со словами что "это не имеет отношения к теме", а Вы приписали мне его идею - явную глупость - нехорошо. Так не дискутируют.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Клапауций 322 пишет:

trembo пишет:

10 плюсов не получается  поставить Клапауций 322 за упрорство и сдержанность  ;)

достаточно сделать 10 аккаунтов tremboХХХ... и, ты личный читер Клапауция.

*кстати, почему я сам себя любимого могу плюсовать и минусовать? блин - я самокритичный и скромный.

Просто мне напомнило тему про то, на что делить показания АЦП при вычислении напряжения: на 1023 или на 1024

Мой прадед говорил:
«Имею желание купить дом, но не имею возможности.
Имею возможность купить козу, но не имею желания».
Так выпьем за то, чтобы наши желания всегда совпадали с нашими возможностями.

Тоже иногда хочется плюсовать себя ( когда другие с этим не справляются)

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

trembo пишет:

Просто мне напомнило тему про то, на что делить показания АЦП при вычислении напряжения: на 1023 или на 1024

да. есть такой тупняк.

писал себе как-то часы на стрелочных головках амперметра 

// analogWrite( 9, 240); // юстировка крайнего максимального положения стрелки измерительной головки
analogWrite(9, (t - ((t / 3600) * 3600)) * 240 / 3599); // минуты

обрати внимание на 3600 и 3599 :D

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Ух-ты!  А такого я ещё не видел!

Клапауций 322
Offline
Зарегистрирован: 31.12.2015

trembo пишет:

Ух-ты!  А такого я ещё не видел!

ну, дарю - пользуйся: t - это секунды RTC, стрелки движутся плавно с дискретностью юстировки.

// analogWrite( 9, 240); // юстировка крайнего максимального положения стрелки измерительной головки
analogWrite(9, (t - ((t / 3600) * 3600)) * 240 / 3599); // минуты
analogWrite(10, (t - ((t / 86400) * 86400)) * 240 / 86399); // часы