Відповісти

Введіть повідомлення і натисніть Надіслати
Параметри

Назад

Огляд теми (нові повідомленні вгорі)

dimich
2024-03-20 10:07:51
Васятко пише:
dimich пише:

Цікавості починаються через 24 або 49 діб, при знаковому або беззнаковому переповненні лічильника,

Ще один адепт секти Свідків Переповнення Великого Міліс?

"якщо код кривий" пропустили? Звісно, при нормально написаному коді переповнення ні до яких збоїв не призводить.

Васятко
2024-03-20 09:30:10
dimich пише:

Цікавості починаються через 24 або 49 діб, при знаковому або беззнаковому переповненні лічильника,

Ще один адепт секти Свідків Переповнення Великого Міліс?

dimich
2024-03-20 04:53:15
просто зайшов пише:

вообще millis(); очень неудобная функция для 8ми битных микроконтроллеров ,  мало того что не точная, так еще и занимает кучу времени на обработку 32-х битной математики.

Так вся ця ардуіна - навчальний проект для початківців. Яка там ефективність чи оптимізація...
Що може бути простіше "кількість мілісекунд від початку роботи"? Цікавості починаються через 24 або 49 діб, при знаковому або беззнаковому переповненні лічильника, якщо код кривий smile

Щодо точності - у них є компенсація лічильника, яка ціла для 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);
}

Ну а там, де потрібна оптимізація за швидкодією або розміром, то бібліотеці ардуіно взагалі не місце.

dimich
2024-03-20 03:48:42
sxstalker пише:

спробував також і ваш код і також лед мигає навпаки smile
https://wokwi.com/projects/392817187868217345

Так ви позаміняли там затримки і додали ще один стан. То вже не мій код.

sxstalker пише:
case 0:
   if (now - last_time >= 10) { // LED має світити 2000 мс? вірно?
        digitalWrite(13, HIGH);

Після старту LED не світить 10 мс, потім вмикається. Навряд чи ви помітите цю затримку в 10 мс після старту.

sxstalker пише:
case 1:
   if (now - last_time >= 4000) { // LED має не світити 200 мс? вірно?
        digitalWrite(13, LOW);

Продовжує світитись 4 секунди. Вимикається.

sxstalker пише:
case 2:
  if (now - last_time >= 1000) { // LED має світити 500 мс? вірно?
    digitalWrite(13, HIGH);

Через 1 секунду вмикається

sxstalker пише:
    case 3:
      if (now - last_time >= 2000) { // LED має не світити 2000 мс? вірно?
        digitalWrite(13, LOW);
        last_time = now;
        state = 4; // переходим в початковий стан "0"
      }
      break;

І через 2 секунди вимикається.

sxstalker пише:
      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 с не світить.

sxstalker пише:

в цьому прикладі точно така ж біла в мене, перший цикл проходить все вірно а потім є блимання лед які зовсім по інтервалу не заявлені в масиві, можливо то глюк цієї віртуалки? чи я десь все ж таки щось не зрозумів?
https://wokwi.com/projects/392819629072839681

dur[state] вказує, скільки триває стан state.
led[state] вказує, яке значення має подаватись на пін світлодіода при переході в наступний, в state+1 стан.

Ви замінили початкове значення світлодіода на HIGH, і при переході зі стану "0" в "1" також виставляєься HIGH. В самій першій ітерації в станах "0" і "1" світлодіод HIGH, вони зливаються. Далі працює як там і написано: короткий блим в 200 мс, пауза 1.5 с, довгий блим 2 с, пауза 3 с і т.д..

просто зайшов
2024-03-20 01:06:57
sxstalker пише:

нашел ошибку 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; 	
  } 


}
просто зайшов
2024-03-20 00:59:23
sxstalker пише:

може мені краще дійде на цьому малюнку?
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; 	
    } 
}

}
sxstalker
2024-03-20 00:39:42

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;
  }
}
sxstalker
2024-03-20 00:27:55

нашел ошибку 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
2024-03-20 00:10:50

выбивает ошибку при запуске
OShIBKA.png
OShIBKA_2.png
==================================================

просто зайшов пише:
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; 	
  } 


}
просто зайшов
2024-03-19 23:52:48

забыл исправить
on = true; // зберігаєм поточний стан, що увімкнено
на
task=1
task=2
итд
сори...

просто зайшов
2024-03-19 23:49:51
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
2024-03-19 23:49:36

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

просто зайшов пише:

вообще millis(); очень неудобная функция для 8ми битных микроконтроллеров ,  мало того что не точная, так еще и занимает кучу времени на обработку 32-х битной математики.
Что мешало разрабам добавить для пользователей глобальный флаг в обработчик прерывания по таймеру0 не понятно...
Хотя это решается включением прерывания по совпадению TIMER0_COMPA_vect .

sxstalker
2024-03-19 23:46:48

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;
    }
   }
}
просто зайшов
2024-03-19 23:44:52

вообще millis(); очень неудобная функция для 8ми битных микроконтроллеров ,  мало того что не точная, так еще и занимает кучу времени на обработку 32-х битной математики.
Что мешало разрабам добавить для пользователей глобальный флаг в обработчик прерывания по таймеру0 не понятно...
Хотя это решается включением прерывания по совпадению TIMER0_COMPA_vect .

sxstalker
2024-03-19 23:38:06

заменил digitalWrite(13, LOW); на digitalWrite(13, HIGH);  в самом начале
первый цикл все работает верно
но как переходит к выполнению по второму кругу мигания то
со светодиодом какие-то происходят не заявленные мигания
где я что-то не понял возможно?
==================================================

просто зайшов пише:
sxstalker пише:

попробовал ваш код, но я так понимаю нужно инвертировать !HIGH и !LOW ? так как сейчас LED мигает наоборот smile

нет, мигает он правильно...
начальное значение LED=LOW, задача0 отсчитывает 2000мс, по истечению счета переключается на задачу1 и включает LED=HIGH
,  задача1 отсчитывает 200мс, по истечению счета переключается на задачу2 и выключает LED=LOW, и тд.

Підвал форуму