Еще раз мигаем светодиодом без Delay

alexbmd
Offline
Зарегистрирован: 15.01.2016

leshak пишет:

toc пишет:

ещё можно чуть уменьшить количество вычислений в каждой итерации. Как то так ...

//проверяем не пора ли переключить
if(millis() > nextMillis ) {
   // сохраняем время следующего переключения
   nextMillis = millis() + INTERVAL; 

Нельзя. Что в вашем варианте произойдет когда millis() пойдет к значению, скажем 4,294,967,000?

Ваше условие - начнет постоянно срабатывать. И "будет глючит" 295 миллисекунд подряд

я когда проверял перезаполнение (еще до этого поста) на С компиляторе то ничего страшного не происходит , всё он там правильно считает. и как предложил toc имеем место быть. или  в ардуине компиляторе не так ?  (я знаю что там тоже С но всётаки с небольшими изменениями)

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

alexbmd пишет:

я когда проверял перезаполнение (еще до этого поста) на С компиляторе то ничего страшного не происходит , всё он там правильно считает. и как предложил toc имеем место быть. 

Я не знаю, что Вы проверяли, Вы же код не показываете. Но, так, как написал toc при переполнении работать не может, лешак прав 100%

alexbmd пишет:

или  в ардуине компиляторе не так ?  (

Это не свойство компилятора, это свойство арифметики в дополнительном коде и от компилятора не зависит.

alexbmd
Offline
Зарегистрирован: 15.01.2016
unsigned long debounceTime = 4294967290 ; //4.294.967.295
unsigned long workTime = 4294967290; //

int main()
{
 for (int i=0;i<26;i=i+5){
  printf("%d =",i);
    debounceTime = debounceTime + i;
  unsigned long result = debounceTime - workTime;
  printf("%lu ",result);
  printf("\n");
 }
}

вот только что набросал, нормальный результат выводит, не уходит в ошибку или минус или еще куда. да и тут это как то давно обсуждали говориличто компилятор понимает перезапуск перемной

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

alexbmd пишет:

unsigned long debounceTime = 4294967290 ; //4.294.967.295
unsigned long workTime = 4294967290; //

int main()
{
 for (int i=0;i<26;i=i+5){
  printf("%d =",i);
    debounceTime = debounceTime + i;
  unsigned long result = debounceTime - workTime;
  printf("%lu ",result);
  printf("\n");
 }
}

вот только что набросал, нормальный результат выводит, не уходит в ошибку или минус или еще куда. да и тут это как то давно обсуждали говориличто компилятор понимает перезапуск перемной

Обратите внимание на строчку 9 - это и есть арифметика в дополнительном коде. Именно поэтому интервал рассчитывается корректно. Похоже, вы просто немного не понимаете, в чём дело. Тут столько копий уже сломано на теме переполнения беззнаковых переменных - может, стоит почитать, для начала? ;)

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

alexbmd пишет:

нормальный результат выводит, 

И что же Вы этим проверили?

У Вас в строке 9 используется вычитание, а у toc в строке  28

nextMillis = millis() + INTERVAL;

сложение.

Вы одно от другого отличаете?

Вы уж проверяйте то, что нуждается в проверке.

Вот здесь есть правильные проверки - http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis

И, да,

alexbmd пишет:

вот только что набросал

Набрасывают навоз на грядки и дерьмо на вентиллятор (да то, последнее "вбрасывают").

bwn
Offline
Зарегистрирован: 25.08.2014

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

Набрасывают навоз на грядки и дерьмо на вентиллятор (да то, последнее "вбрасывают").

Неа, последнее по транспортерной ленте должно подаваться, медленно, но верно. Иначе, нетехнологично.))))

alexbmd
Offline
Зарегистрирован: 15.01.2016

От блин я думал направление не играет роли :) спасибо Евгений

но у Гаммона понятнее объяснено для новичков

https://www.gammon.com.au/millis

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

А ещё художники тоже любят наброски набрасывать .. ;)

alexbmd
Offline
Зарегистрирован: 15.01.2016

так я художник :)

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

alexbmd пишет:

но у Гаммона понятнее объяснено для новичков

https://www.gammon.com.au/millis

Вот тут Вы молодец! В правильно направлении роете. Nick - мужик толковый и грамотный! А тот тут любят сослаться на, прости Господи, Гивера.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

может кто объяснить почему замена в нижеприведённом коде булевой переменной на байт экономит 8 байт памяти программ?
 

#define SECONDS(x)  ((x) * 1000UL)
#define MINUTES(x)  (SECONDS(x) * 60UL)
#define HOURS(x)  (MINUTES(x) * 60UL)
#define DAYS(x)   (HOURS(x) * 24UL)
#define WEEKS(x)  (DAYS(x) * 7UL)
#define port PORTB
#define pin 5

PROGMEM const unsigned long interval[2] = {HOURS(0) + MINUTES(0) + SECONDS(1), HOURS(0) + MINUTES(0) + SECONDS(2)};

unsigned long previousMillis;

void setup(){
  //Serial.begin(9600);
  port = DDRB = 1 << pin;
}

void loop(){
 // bool b = bitRead(port,pin);
   byte b = bitRead(port,pin);
  unsigned long Millis = millis();
  if (Millis - previousMillis >= pgm_read_dword_near(&interval[b])) { 
 //   Serial.println(b);
    bitWrite(port,pin,!b);
    previousMillis = Millis;
  }
 }

 

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

Виноват, бред написал. Сейчас разберусь.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Виноват, бред написал. Сейчас разберусь.

Я не увидел...да даже если бы и увидел... )))

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

Эффект сильно зависит от опций и его трудно воспроизвести. Например, у меня в Avr студии получилось наоборот. Но, общая идея здесь в том, что всё зависит от дальнейшего использовании b. Дело в том, что в строке 22 оно должно быть int для взятия индекса. А в строке 24 оно может быть как int, так и bool для отрицания.

Если её объявить как byte - она везде int и никаких усилий не требуется, т.к. всё подходит, а если объявить как bool, то в строке №22 его нужно преобразовывать и компилятор оставляет преобразование на этап выполнения. 

Чтобы убедиться в этом, можно явно пояснить компилятору, что ничего, кроме 0 и 1 там не будет. Для этого, например, в строке №20 можно заменить "bitRead(port,pin);" на "(port & bit(pin)) ? 1 : 0;". Попробуйте. Эффект уходит.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

не взлетело, на восемь байт больше также как и для bitRead(port,pin);
А тема называлась правильный выбор типа переменных )))

IDE 1.8.8 настроенная по умолчанию
 

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

ua6em пишет:

может кто объяснить почему замена в нижеприведённом коде булевой переменной на байт экономит 8 байт памяти программ?
 

#define SECONDS(x)  ((x) * 1000UL)
#define MINUTES(x)  (SECONDS(x) * 60UL)
#define HOURS(x)  (MINUTES(x) * 60UL)
#define DAYS(x)   (HOURS(x) * 24UL)
#define WEEKS(x)  (DAYS(x) * 7UL)
#define port PORTB
#define pin 5

PROGMEM const unsigned long interval[2] = {HOURS(0) + MINUTES(0) + SECONDS(1), HOURS(0) + MINUTES(0) + SECONDS(2)};

unsigned long previousMillis;

void setup(){
  //Serial.begin(9600);
  port = DDRB = 1 << pin;
}

void loop(){
 // bool b = bitRead(port,pin);
   byte b = bitRead(port,pin);
  unsigned long Millis = millis();
  if (Millis - previousMillis >= pgm_read_dword_near(&interval[b])) { 
 //   Serial.println(b);
    bitWrite(port,pin,!b);
    previousMillis = Millis;
  }
 }

 

В зависимости от того bool у вас или byte, компилятор создает различный код. В первом случае предполагается, что в переменой b может быть либо ноль, либо не ноль (не принципиально что именно). На этом строятся дальнейшие проверки и использование b в качестве индекса массива сводится к взятию либо первого элемента (если b = 0), либо второго.

С byte дело обстоит иначе. Хранящееся в переменной b значение принципиально (по крайней мере в данном коде). И оно непосредственно участвует в вычислении адреса нужного элемента массива (индекс элемента * размер элементов ...). В итоге код уже отличается от генерируемого для bool.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

VladimirTsibrov пишет:

 В итоге код уже отличается от генерируемого для bool.

Осталось определиться в каком случае надо присваивать переменной тип bool а в каком byte

С этим компилятором настолько всё неоднозначно, к примеру снимаем ремарку с 24 строки, чтобы получить перед главным циклом правильное время начала цикла, а исполнимый код вместо увеличения становится на 22 байта короче ))) ...И как тут не быть ...
 

#define SECONDS(x)  ((x) * 1000UL)
#define MINUTES(x)  (SECONDS(x) * 60UL)
#define HOURS(x)  (MINUTES(x) * 60UL)
#define DAYS(x)   (HOURS(x) * 24UL)
#define WEEKS(x)  (DAYS(x) * 7UL)
//PROGMEM const unsigned long interval_1 = HOURS(0) + MINUTES(0) + SECONDS(6);
//PROGMEM const unsigned long interval_2 = HOURS(0) + MINUTES(0) + SECONDS(18);
//const unsigned long interval_1 = HOURS(0) + MINUTES(0) + SECONDS(6);
//const unsigned long interval_2 = HOURS(0) + MINUTES(0) + SECONDS(18);
unsigned long interval_1 = HOURS(0) + MINUTES(0) + SECONDS(6);
unsigned long interval_2 = HOURS(0) + MINUTES(0) + SECONDS(18);
#define port PORTB
#define pin 5

unsigned long previousMillis;
int led = 13;

void setup(){
 // pinMode(led, OUTPUT);
//  Serial.begin(9600);
//  bitWrite(port,pin,HIGH);
 // digitalWrite(led, HIGH);
  port = DDRB = 1 << pin;
  //previousMillis = millis();
}

void loop(){
     if (millis() - previousMillis >= interval_2 && bitRead(port,pin) == HIGH) { 
     bitWrite(port,pin,LOW);
     previousMillis = millis();
     }
     
     if (millis() - previousMillis >= interval_1 && bitRead(port,pin) == LOW) { 
     bitWrite(port,pin,HIGH); 
    // digitalWrite(led, HIGH);
     previousMillis = millis();
     }
 }

 

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

ua6em пишет:
не взлетело, на восемь байт больше также как и для bitRead(port,pin);

У меня 1.8.9 - нормально взлетает. Собственно, я уже говорил - от опций зависит.

В любом случае, суть дела Вам уже пояснили и я, и VladimirTsibrov.

ua6em пишет:
А тема называлась правильный выбор типа переменных )))

Неправда, тема называлась "Еще раз мигаем светодиодом без Delay"

Если Вас так сильно интересует правильный выбор типа, то, Вы невнимательно читаете, я Вам уже писал, что операция взятия индекса требует int

alexbmd
Offline
Зарегистрирован: 15.01.2016

ua6em, а если закастить?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Если Вас так сильно интересует правильный выбор типа, то, Вы невнимательно читаете, я Вам уже писал, что операция взятия индекса требует int

Читал внимательно, но вот понять )))
Как в том анекдоте про дважды два - семь, восемь где-то так, ну не сорок жеж...
Да сейчас поставлю 1.8.9 проверю...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

alexbmd пишет:

ua6em, а если закастить?

Это вы с кем сейчас разговаривали )))
Я же говорю, знал когда-то диаграмму состояний сплава железо-углерод, ВСЁ!!! Ардуино - хобби, одно из ...
Языком Ардуино, в отличии от остальных двух десятков разговорных не владею )))

alexbmd
Offline
Зарегистрирован: 15.01.2016

bool 582

byte 574

1.8.9

каст не помогает уменьшить .  интересно девки пляшут

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

ua6em пишет:

Да сейчас поставлю 1.8.9 проверю...

Мне не верите?

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

ua6em пишет:

С этим компилятором настолько всё неоднозначно, к примеру снимаем ремарку с 24 строки, чтобы получить перед главным циклом правильное время начала цикла, а исполнимый код вместо увеличения становится на 22 байта короче ))) ...И как тут не быть ...

Я бы предположил, что компилятор, встретив в очередной раз строку

previousMillis = millis();

, принял решение об оптимизации этого вызова за счет другого ресурса. Я попробовал добавить указанную строку не в setup, а в начале loop - эффект тот же: размер скомпилированного файла уменьшился.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Мне не верите?

Верю!!! Но как говорил DIMAX - UA6EM, если что-то имеет теоретическую возможность пойти не так, оно у Вас обязательно пойдёт не так, может хобби сменить )))

VladimirTsibrov
Offline
Зарегистрирован: 05.03.2019

ua6em пишет:

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

Мне не верите?

Верю!!! Но как говорил DIMAX - UA6EM, если что-то имеет теоретическую возможность пойти не так, оно у Вас обязательно пойдёт не так, может хобби сменить )))

Закон Мерфи)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

VladimirTsibrov пишет:

 принял решение об оптимизации этого вызова за счет другого ресурса. Я попробовал добавить указанную строку не в setup, а в начале loop - эффект тот же: размер скомпилированного файла уменьшился.

Ясно, компилятор писали выходцы из СССР...только у нас решение принимется после третьего наступления ногой на грабли )))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DIMAX был прав ))))))))))))))))))))))))))))))))))))))

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

Ну, значит между тем моментом. когда я скачивал и сегодня, они поменяли какую-нибудь опцию.

По сути вопроса Вам ответили, ещё вопросы есть или уже просто так треплемся?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Ну, значит между тем моментом. когда я скачивал и сегодня, они поменяли какую-нибудь опцию.

По сути вопроса Вам ответили, ещё вопросы есть или уже просто так треплемся?

по сути понятно, прямо таки "море не отталкивает от себя ни одной реки" )

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ua6em пишет:

по сути понятно, прямо таки "море не отталкивает от себя ни одной реки" )


Но если море мешает судоходству, то роем обводной канал.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

qwone пишет:
ua6em пишет:

по сути понятно, прямо таки "море не отталкивает от себя ни одной реки" )

Но если море мешает судоходству, то роем обводной канал.

и причём тут море? )

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ua6em пишет:

qwone пишет:
ua6em пишет:

по сути понятно, прямо таки "море не отталкивает от себя ни одной реки" )

Но если море мешает судоходству, то роем обводной канал.

и причём тут море? )

Ну сами зацепили метафоры, так Вам еще и их расжевывать для Вашего понимания.

море не отталкивает от себя ни одной реки =У каждой проблемы есть универсальное решение.

Но если море мешает судоходству, то роем обводной канал = как бы универсальное решение не оказалось еще больше проблемой.

ПС: у метафор всегда есть два прочтения - прямое и метафоричное. Так и ответных метафор должно быть тоже ответы на эти же прочтения.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

вообще то я о другом говорил, о ценности каждой капли знаний )))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ua6em пишет:

вообще то я о другом говорил, о ценности каждой капли знаний )))

Вот и я об этом. Говорите яснее, а не высоким стилем=языком метафор. А то Вам ответят метафорой и эта капля знаний утонет в метафоре. https://youtu.be/FZr4MEAOXWI?t=2151   Ну да много времени для просмотра.

alexbmd
Offline
Зарегистрирован: 15.01.2016
Добрый вечер
в обсуждаемом варианте мигания да и в 99% остальных
		if (millis() - t > 150S){
			//инвертируем диод
			t = millis();
		}

первый интервал (в даном случае 150 с) мы получается ничего не делаем. а тут возникла необходимость сразу заинвертировать , ну и потом дальше как обычно через заданный интервал. без дополнительной проверки дополнительной переменной не придумал как реализовать.

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

 

 

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

alexbmd пишет:
в даном случае 150 с
Неужели?

b707
Offline
Зарегистрирован: 26.05.2017

Если t =0, то так и будет - первое инвертирование сразу, а потом через оговоренный интервал

vlad072
Offline
Зарегистрирован: 01.08.2017

Мигаю примерно так:

#define LED 13;
bool flash = false; // мигать/не мигать
//.......
loop() {
  digitalWrite( LED, flash && ((millis() & 0x3FFul) > 0x370ul) ); // примерно 1Гц
//.......
}

 

b707
Offline
Зарегистрирован: 26.05.2017

vlad072 пишет:

Мигаю примерно так:

#define LED 13;
bool flash = false; // мигать/не мигать
//.......
loop() {
  digitalWrite( LED, flash && ((millis() & 0x3FFul) > 0x370ul) ); // примерно 1Гц
//.......
}

в этом варианте первый период мигания будет случайного размера. что вряд ли можно назвать правильным ответом на вопрос

alexbmd
Offline
Зарегистрирован: 15.01.2016

B707, точно спасибо. Обычно t инициализирую как millis (). И искал в других направлениях. А можно просто t=0. Спасибо

alexbmd
Offline
Зарегистрирован: 15.01.2016

Vlad, мы так пишем постоянно в порт, даже когда не надо, что лично я стараюсь избегать.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А какие соображения вынуждают Вас избегать записи в порт?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Боятся, видима, што порт протрёцца. 

Green
Онлайн
Зарегистрирован: 01.10.2015

Это если порт ввода. Эх, солнечная молдавия!

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Запомни Гоги. Вход это куда люди заходят,выход это откуда выходят. А если люди заходят и выходят , то это переход.

alexbmd
Offline
Зарегистрирован: 15.01.2016

andriano пишет:

А какие соображения вынуждают Вас избегать записи в порт?

не записи в порт, а повторной записи того же самого. смысл не проверяя писать тоже самое ?

плюс if хоть каплю но быстрее чем direct port manipulation , не говоря уже про digitalWrite

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

alexbmd пишет:

andriano пишет:

А какие соображения вынуждают Вас избегать записи в порт?

if хоть каплю но быстрее чем direct port manipulation

Разве?

Порт находится в общем адресном пространстве и работа с ним ничем не отличается от работы с ячейкой памяти.

Если мы используем if, то с чем мы его используем? Наверняка выделяем в памяти ячейку, в которой содержится информация, следует писать в порт или нет. Работа с этой ячейкой ничуть не быстрее, чем работа с самим портом. Да еще и лишний if... А если окажется, что нужно писать, так вообще двойная работа: и с ячейкой, и с портом. С какой стати быстрее?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

alexbmd пишет:
а повторной записи того же самого. смысл не проверяя писать тоже самое ?
Здесь Вы очень сильно запутались в причинах и следствиях. Есть исходник(тот который пишет программист) и есть код(по которому работает процессор). Так вот Программист может написать много, а в коде быть мало объема и наоборот. Буквально 10 буквиц и код многократно увеличивается. Дальше размер кода и время исполнения его. Казалось бы логично больше кода и больше времени исполнения. Но всякие циклы и процессор буквально будет только работать на этот код, А если в коде куча ветвлений, то многие ветви будут выполнятся в только в исключительных ситуациях, а нормальной ситуации процессор на них не будет затрачивать ни такта.

alexbmd
Offline
Зарегистрирован: 15.01.2016

Квон, абсолютно согласен. Это уже искусство а не программирование :) восхищаюсь теми кто его достиг.

Андриан, я прежде чем написать специально поверил. Я не бог программирования но все же.
На верху Влад привел запись в порт, а я свой if. Можете написать чтобы запись Влада была быстрее моегоif ?