Ви не увійшли.
dimich пише:Цікавості починаються через 24 або 49 діб, при знаковому або беззнаковому переповненні лічильника,
Ще один адепт секти Свідків Переповнення Великого Міліс?
"якщо код кривий" пропустили? Звісно, при нормально написаному коді переповнення ні до яких збоїв не призводить.
Цікавості починаються через 24 або 49 діб, при знаковому або беззнаковому переповненні лічильника,
Ще один адепт секти Свідків Переповнення Великого Міліс?
вообще millis(); очень неудобная функция для 8ми битных микроконтроллеров , мало того что не точная, так еще и занимает кучу времени на обработку 32-х битной математики.
Так вся ця ардуіна - навчальний проект для початківців. Яка там ефективність чи оптимізація...
Що може бути простіше "кількість мілісекунд від початку роботи"? Цікавості починаються через 24 або 49 діб, при знаковому або беззнаковому переповненні лічильника, якщо код кривий
Щодо точності - у них є компенсація лічильника, яка ціла для 8 і 16 МГц, тобто довгострокова точність відповідає кварцу. Але джиттер.
Что мешало разрабам добавить для пользователей глобальный флаг в обработчик прерывания по таймеру0 не понятно...
Хотя это решается включением прерывания по совпадению TIMER0_COMPA_vect .
На AVRках замість флага можна читати молодший байт timer0_overflow_count, якщо трошки похуліганити:
extern volatile unsigned long timer0_overflow_count;
static inline uint8_t overflows() {
return *reinterpret_cast<volatile uint8_t *>(&timer0_overflow_count);
}
Ну а там, де потрібна оптимізація за швидкодією або розміром, то бібліотеці ардуіно взагалі не місце.
спробував також і ваш код і також лед мигає навпаки
![]()
https://wokwi.com/projects/392817187868217345
Так ви позаміняли там затримки і додали ще один стан. То вже не мій код.
case 0: if (now - last_time >= 10) { // LED має світити 2000 мс? вірно? digitalWrite(13, HIGH);
Після старту LED не світить 10 мс, потім вмикається. Навряд чи ви помітите цю затримку в 10 мс після старту.
case 1: if (now - last_time >= 4000) { // LED має не світити 200 мс? вірно? digitalWrite(13, LOW);
Продовжує світитись 4 секунди. Вимикається.
case 2: if (now - last_time >= 1000) { // LED має світити 500 мс? вірно? digitalWrite(13, HIGH);
Через 1 секунду вмикається
case 3: if (now - last_time >= 2000) { // LED має не світити 2000 мс? вірно? digitalWrite(13, LOW); last_time = now; state = 4; // переходим в початковий стан "0" } break;
І через 2 секунди вимикається.
case 4: if (now - last_time >= 2000) { // LED має не світити 2000 мс? вірно? digitalWrite(13, LOW); last_time = now; state = 0; // переходим в початковий стан "0" }
Продовжує бути вимкненим ще 2 секунди.
В станах 0 і 4 світлодіод вимкнено, вони зливаються в один період 2 с 10 мс, коли світлодіод не світить. Паттерн виходить такий:
4 с світить, 1 с не світить, 2 с світить, 2.01 с не світить.
в цьому прикладі точно така ж біла в мене, перший цикл проходить все вірно а потім є блимання лед які зовсім по інтервалу не заявлені в масиві, можливо то глюк цієї віртуалки? чи я десь все ж таки щось не зрозумів?
https://wokwi.com/projects/392819629072839681
dur[state] вказує, скільки триває стан state.
led[state] вказує, яке значення має подаватись на пін світлодіода при переході в наступний, в state+1 стан.
Ви замінили початкове значення світлодіода на HIGH, і при переході зі стану "0" в "1" також виставляєься HIGH. В самій першій ітерації в станах "0" і "1" світлодіод HIGH, вони зливаються. Далі працює як там і написано: короткий блим в 200 мс, пауза 1.5 с, довгий блим 2 с, пауза 3 с і т.д..
нашел ошибку case : 0 , исправил на case 0: и так далее но лед теперь все время светится
==================================================
исправил
unsigned long last_time;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
bool on = false; // поточний стан. з початку - вимкнено;
void loop() {
unsigned long now = millis();
static unsigned char task=0;
switch (task)
{
case 0:
digitalWrite(13, HIGH); // вмикаєм
if (now - last_time >= 2000) { // пройшло 1000 мс ?
last_time = now;
task=1;
}
break;
case 1:
digitalWrite(13, LOW); // вимикаєм
if (now - last_time >= 200) { // пройшло 300 мс ?
last_time = now;
task=2;
}
break;
case 2:
digitalWrite(13, HIGH); // вмикаєм
if (now - last_time >= 500) { // пройшло 1000 мс ?
last_time = now;
task=3;
}
break;
case 3:
digitalWrite(13, LOW); // вимикаєм
if (now - last_time >= 2000) { // пройшло 300 мс ?
last_time = now;
task=0;
}
break;
default :
task=0;
break;
}
}
може мені краще дійде на цьому малюнку?
https://forum.arduino.ua/img/members/3773/nesinkhronnoe-migaenie-svetodiodom-v-Arduino_20240319-2122.png
без millis() по системному тику 1 мс.
volatile unsigned char flag_1ms =0; // флаг : пройшла 1 мілісекунда
ISR(TIMER0_COMPA_vect) { // прерівание по совпадению таймера0 период 1мс.
flag_1ms =1;
}
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
// Timer/Counter 0 Interrupt(s) initialization
bitSet(TIMSK0, OCIE0A); // вмикаєм прерівание по совпадению таймера0
}
void loop() {
static unsigned int count_timer=0; // лічильник мілісекунд
static unsigned char task=0;
if( flag_1ms){
flag_1ms =0;
switch (task)
{
case 0:
digitalWrite(13, HIGH); // вмикаєм
if (count_timer==300) { // пройшло 300 мс ?
count_timer=0;
task=1;
}else{count_timer++;}
break;
case 1:
digitalWrite(13, LOW); // вимикаєм
if (count_timer==370) { // пройшло 370 мс ?
count_timer=0;
task=2;
}else{count_timer++;}
break;
case 2:
digitalWrite(13, HIGH); // вмикаєм
if (count_timer==180) { // пройшло 180 мс ?
count_timer=0;
task=3;
}else{count_timer++;}
break;
case 3:
digitalWrite(13, LOW); // вимикаєм
if (count_timer==410) { // пройшло 410 мс ?
count_timer=0;
task=4;
}else{count_timer++;}
break;
case 4:
digitalWrite(13, HIGH); // вмикаєм
if (count_timer==110) { // пройшло 110 мс ?
count_timer=0;
task=5;
}else{count_timer++;}
break;
case 5:
digitalWrite(13, LOW); // вимикаєм
if (count_timer==190) { // пройшло 190 мс ?
count_timer=0;
task=6;
}else{count_timer++;}
break;
case 6:
digitalWrite(13, HIGH); // вимикаєм
if (count_timer==650) { // пройшло 650 мс ?
count_timer=0;
task=7;
}else{count_timer++;}
break;
case 7:
digitalWrite(13, LOW); // вимикаєм
if (count_timer==3000) { // пройшло 3000 мс ?
count_timer=0;
task=0;
}else{count_timer++;}
break;
default :
task=0;
break;
}
}
}
dimich, змінивши трохи ваш код нарешті я здається допер як воно все працює
задача:
лед світить 4000 мс
лед не світить 1000 мс
лед світить 2000 мс
лед не світить 2000 мс
====================================================
int state = 0; // поточний стан. з початку - "0";
unsigned long last_time;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
void loop() {
unsigned long now = millis();
switch (state)
{
case 0: // додав цей кейс
if (now - last_time >= 10) { // LED має світити 2000 мс? вірно?
digitalWrite(13, HIGH);
last_time = now;
state = 1;
}
break;
case 1:
if (now - last_time >= 4000) { // LED має не світити 200 мс? вірно?
digitalWrite(13, LOW);
last_time = now;
state = 2;
}
break;
case 2:
if (now - last_time >= 1000) { // LED має світити 500 мс? вірно?
digitalWrite(13, HIGH);
last_time = now;
state = 3;
}
break;
case 3:
if (now - last_time >= 2000) { // LED має не світити 2000 мс? вірно?
digitalWrite(13, LOW);
last_time = now;
state = 4; // переходим в початковий стан "0"
}
break;
case 4:
if (now - last_time >= 2000) { // LED має не світити 2000 мс? вірно?
digitalWrite(13, LOW);
last_time = now;
state = 0; // переходим в початковий стан "0"
}
break;
}
}
нашел ошибку case : 0 , исправил на case 0: и так далее но лед теперь все время светится
==================================================
sxstalker пише:заменил digitalWrite(13, LOW); на digitalWrite(13, HIGH); в самом начале
первый цикл все работает верноладно если Вам это сложно, может так будет проще для понимания
unsigned long last_time; void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); } bool on = false; // поточний стан. з початку - вимкнено; void loop() { unsigned long now = millis(); static unsigned char task=0; switch (task) { case : 0 digitalWrite(13, HIGH); // вмикаєм if (now - last_time >= 2000) { // пройшло 1000 мс ? last_time = now; on = true; // зберігаєм поточний стан, що увімкнено } break; case : 1 digitalWrite(13, LOW); // вимикаєм if (now - last_time >= 200) { // пройшло 300 мс ? last_time = now; on = false; // зберігаєм поточний стан, що вимкнено } break; case : 2 digitalWrite(13, HIGH); // вмикаєм if (now - last_time >= 500) { // пройшло 1000 мс ? last_time = now; on = true; // зберігаєм поточний стан, що увімкнено } break; case : 3 digitalWrite(13, LOW); // вимикаєм if (now - last_time >= 2000) { // пройшло 300 мс ? last_time = now; on = false; // зберігаєм поточний стан, що вимкнено } break; default : break; } }
выбивает ошибку при запуске
==================================================
sxstalker пише:заменил digitalWrite(13, LOW); на digitalWrite(13, HIGH); в самом начале
первый цикл все работает верноладно если Вам это сложно, может так будет проще для понимания
unsigned long last_time; void setup() { pinMode(13, OUTPUT); digitalWrite(13, LOW); } bool on = false; // поточний стан. з початку - вимкнено; void loop() { unsigned long now = millis(); static unsigned char task=0; switch (task) { case : 0 digitalWrite(13, HIGH); // вмикаєм if (now - last_time >= 2000) { // пройшло 1000 мс ? last_time = now; on = true; // зберігаєм поточний стан, що увімкнено } break; case : 1 digitalWrite(13, LOW); // вимикаєм if (now - last_time >= 200) { // пройшло 300 мс ? last_time = now; on = false; // зберігаєм поточний стан, що вимкнено } break; case : 2 digitalWrite(13, HIGH); // вмикаєм if (now - last_time >= 500) { // пройшло 1000 мс ? last_time = now; on = true; // зберігаєм поточний стан, що увімкнено } break; case : 3 digitalWrite(13, LOW); // вимикаєм if (now - last_time >= 2000) { // пройшло 300 мс ? last_time = now; on = false; // зберігаєм поточний стан, що вимкнено } break; default : break; } }
забыл исправить
on = true; // зберігаєм поточний стан, що увімкнено
на
task=1
task=2
итд
сори...
заменил digitalWrite(13, LOW); на digitalWrite(13, HIGH); в самом начале
первый цикл все работает верно
ладно если Вам это сложно, может так будет проще для понимания
unsigned long last_time;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
}
bool on = false; // поточний стан. з початку - вимкнено;
void loop() {
unsigned long now = millis();
static unsigned char task=0;
switch (task)
{
case : 0
digitalWrite(13, HIGH); // вмикаєм
if (now - last_time >= 2000) { // пройшло 1000 мс ?
last_time = now;
on = true; // зберігаєм поточний стан, що увімкнено
}
break;
case : 1
digitalWrite(13, LOW); // вимикаєм
if (now - last_time >= 200) { // пройшло 300 мс ?
last_time = now;
on = false; // зберігаєм поточний стан, що вимкнено
}
break;
case : 2
digitalWrite(13, HIGH); // вмикаєм
if (now - last_time >= 500) { // пройшло 1000 мс ?
last_time = now;
on = true; // зберігаєм поточний стан, що увімкнено
}
break;
case : 3
digitalWrite(13, LOW); // вимикаєм
if (now - last_time >= 2000) { // пройшло 300 мс ?
last_time = now;
on = false; // зберігаєм поточний стан, що вимкнено
}
break;
default :
break;
}
}
ух, боюсь я тут пока вас не пойму еще, для меня это все пока за ширмой неизведанного
но если есть какой-то способ более правильный мигать лед так как я хочу то я только за чтобы научится новому
==========================================================================
вообще millis(); очень неудобная функция для 8ми битных микроконтроллеров , мало того что не точная, так еще и занимает кучу времени на обработку 32-х битной математики.
Что мешало разрабам добавить для пользователей глобальный флаг в обработчик прерывания по таймеру0 не понятно...
Хотя это решается включением прерывания по совпадению TIMER0_COMPA_vect .
dimich , в цьому прикладі точно така ж біла в мене, перший цикл проходить все вірно а потім є блимання лед які зовсім по інтервалу не заявлені в масиві, можливо то глюк цієї віртуалки? чи я десь все ж таки щось не зрозумів?
https://wokwi.com/projects/392819629072839681
===================================================================
unsigned int dur[4] = { 3000, 200, 1500, 2000 }; // масив тривалостей (duration) для кожного стану
byte led[4] = { HIGH, LOW, HIGH, LOW }; // масив значень digitalWrite для кожного стану
int state = 0; // поточний стан. з початку - "0";
unsigned long last_time;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
}
void loop() {
unsigned long now = millis();
if (now - last_time >= dur[state]) { // якщо час поточного стану вийшов
digitalWrite(13, led[state]); // вмикаєм або вимикаєм світлодіод
last_time = now;
state = state + 1; // переходим у наступний стан
// але максимально можливий номер стану - "3"
// якщо це був останній - переходим у початковий стан "0"
if (state > 3) {
state = 0;
}
}
}
вообще millis(); очень неудобная функция для 8ми битных микроконтроллеров , мало того что не точная, так еще и занимает кучу времени на обработку 32-х битной математики.
Что мешало разрабам добавить для пользователей глобальный флаг в обработчик прерывания по таймеру0 не понятно...
Хотя это решается включением прерывания по совпадению TIMER0_COMPA_vect .
заменил digitalWrite(13, LOW); на digitalWrite(13, HIGH); в самом начале
первый цикл все работает верно
но как переходит к выполнению по второму кругу мигания то
со светодиодом какие-то происходят не заявленные мигания
где я что-то не понял возможно?
==================================================
sxstalker пише:попробовал ваш код, но я так понимаю нужно инвертировать !HIGH и !LOW ? так как сейчас LED мигает наоборот
нет, мигает он правильно...
начальное значение LED=LOW, задача0 отсчитывает 2000мс, по истечению счета переключается на задачу1 и включает LED=HIGH
, задача1 отсчитывает 200мс, по истечению счета переключается на задачу2 и выключает LED=LOW, и тд.