#26 2024-03-19 02:20:09

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 130

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

sxstalker пише:

підкажіть будь-ласка чому він падлюка не працює? :-)

Тому що після того як пройшло 300 мс завжди спрацьовує перша умова:

if (millis() - last_time >= 300)

і last_time оновлюється поточним значенням millis(). Таким чином друга умова

if (millis() - last_time >= 1000)

ніколи не спрацьовує.

Програма має зберігати свій поточний стан і перемикатись в залежності від нього.
Також рекомендую зчитувати millis() один раз на початку ітерації і надалі використовувати це зчитане значення.

bool on = false; // поточний стан. з початку - вимкнено

void loop() {
  unsigned long now = millis();

  if (!on) { // світлодіод вимкнено ?
    if (now - last_time >= 1000) { // пройшло 1000 мс ?
      digitalWrite(13, HIGH); // вмикаєм
      last_time = now;
      on = true; // зберігаєм поточний стан, що увімкнено
    }
  } else { // світлодіод увімкнено ?
    if (now - last_time >= 300) { // пройшло 300 мс ?
      digitalWrite(13, LOW); // вимикаєм
      last_time = now;
      on = false; // зберігаєм поточний стан, що вимкнено
    }   
  }
}

Неактивний

#27 2024-03-19 21:16:48

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

dimich, дуже дякую вам за допомогу  smile  ваш код мені вже більш зрозумілий став
захтів трохи поексперементувати з ним але знову в мене граблі якісь, вибачте що так тяжко мені заходить smile
захотів продовжити миготіння led але додавши ще різні значення терміну милис але знову в мене фіаско ))))

unsigned long last_time;

void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW); 

}

bool on = false; // поточний стан. з початку - вимкнено;

void loop() {
  unsigned long now = millis();

  if (!on) { // світлодіод вимкнено ?
    if (now - last_time >= 2000) { // пройшло 1000 мс ?
      digitalWrite(13, HIGH); // вмикаєм
      last_time = now;
      on = true; // зберігаєм поточний стан, що увімкнено
    }
  } 

  else if (on) { // світлодіод увімкнено ?
     if (now - last_time >= 200) { // пройшло 300 мс ?
        digitalWrite(13, LOW); // вимикаєм
       last_time = now;
       on = false; // зберігаєм поточний стан, що вимкнено
    }
  } 

  else if (!on) { // світлодіод вимкнено ?
    if (now - last_time >= 500) { // пройшло 1000 мс ?
      digitalWrite(13, HIGH); // вмикаєм
      last_time = now;
      on = true; // зберігаєм поточний стан, що увімкнено
    }
  } 

  else if (on) { // світлодіод увімкнено ?
     if (now - last_time >= 2000) { // пройшло 300 мс ?
        digitalWrite(13, LOW); // вимикаєм
       last_time = now;
       on = false; // зберігаєм поточний стан, що вимкнено
    }
  } 
/*
    else { // світлодіод увімкнено ?
      if (now - last_time >= 200) { // пройшло 300 мс ?
        digitalWrite(13, LOW); // вимикаєм
       last_time = now;
       on = false; // зберігаєм поточний стан, що вимкнено
    }   
  }
*/

}

Неактивний

#28 2024-03-19 22:29:08

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

може мені краще дійде на цьому малюнку?
nesinkhronnoe-migaenie-svetodiodom-v-Arduino_20240319-2122.png

Неактивний

#29 2024-03-19 22:31:06

просто зайшов
Гість

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

как-то так...

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:   
       if (now - last_time >= 2000) { // пройшло 1000 мс ?
          digitalWrite(13, HIGH); // вмикаєм
          last_time = now;
          task=1; // переходим к следующей задаче
        }
       break; 
    case 1:   
       if (now - last_time >= 200) { // пройшло 300 мс ?
          digitalWrite(13, LOW); // вимикаєм
          last_time = now;
          task=2; 
        }
       break; 
    case 2:     
       if (now - last_time >= 500) { // пройшло 1000 мс ?
          digitalWrite(13, HIGH); // вмикаєм
          last_time = now;
          task=3;
        }
       break; 
    case 3: 
        if (now - last_time >= 2000) { // пройшло 300 мс ?
           digitalWrite(13, LOW); // вимикаєм
           last_time = now;
           task=0;
        }
       break; 
    default :
       break; 	
  } 


}

#30 2024-03-19 22:34:33

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

як правильно написати код для такого мигання LED? можливо треба використати масив?

Неактивний

#31 2024-03-19 22:43:24

просто зайшов
Гість

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

можно через массив, можно как показано выше через switch/case

#32 2024-03-19 22:44:15

dimich
Учасник
Зареєстрований: 2023-12-01
Повідомлень: 130

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

Ця конструкція:

sxstalker пише:
  if (!on) {
...
  } else if (on) {
...
  } else if (!on) {
...
  } else if (on) {
...
  } 

не має сенсу. Якщо перша умова "if (!on)" виконалась, то решта вже не виконуються. А якщо не виконалась, то обовʼязково виконається друга - "if (on)", бо вона протилежна першій. А дві останні - ніколи не виконаються.

В попередньому прикладі у вас було всього два стани: світлодіод вимкнено, і світлодіод увімкнено. Тому було достатньо змінної типу bool, у якої всього два можливих значення.

В останньому прикладі у вас чотири стани:
* вимкнено перший раз (на 2000 мс)
* увімкнено перший раз (на 200 мс)
* вимкнено другий раз (на 500 мс)
* увімкнено другий раз (на 2000 мс)

Тому для збереження стану потрібна змінна такого типу, щоб могла приймати як мінімум 4 значення. Для простоти візьмем int. Стани будем нумерувати від 0 до 3. І для ясності перейменуєм змінну з "on" на "state".

int state = 0; // поточний стан. з початку - "0";

void loop() {
  unsigned long now = millis();

  if (state == 0) { // в стані "0"?
    if (now - last_time >= 2000) {
      digitalWrite(13, HIGH);
      last_time = now;
      state = 1; // переходим в стан "1"
    }
  } else if (state == 1) { // в стані "1"?
     if (now - last_time >= 200) {
      digitalWrite(13, LOW);
      last_time = now;
      state = 2; // переходим в стан "2"
    }
  } else if (state == 2) { // в стані "2"?
    if (now - last_time >= 500) {
      digitalWrite(13, HIGH);
      last_time = now;
      state = 3; // переходим в стан "3"
    }
  } else if (state == 3) { // в стані "3" ?
     if (now - last_time >= 2000) {
        digitalWrite(13, LOW);
       last_time = now;
       state = 0; // переходим в початковий стан "0"
    }
  }
}

Абсолютно те ж саме, тільки switch/case замість if/else. Так більш читабельно:

int state = 0; // поточний стан. з початку - "0";

void loop() {
  unsigned long now = millis();

  switch (state)
  {
    case 0:
      if (now - last_time >= 2000) {
        digitalWrite(13, HIGH);
        last_time = now;
        state = 1;
      }
      break;
    case 1:
      if (now - last_time >= 200) {
        digitalWrite(13, LOW);
        last_time = now;
        state = 2;
      }
      break;
    case 2:
      if (now - last_time >= 500) {
        digitalWrite(13, HIGH);
        last_time = now;
        state = 3;
      }
      break;
    case 3:
      if (now - last_time >= 2000) {
        digitalWrite(13, LOW);
        last_time = now;
        state = 0; // переходим в початковий стан "0"
      }
      break;
  }
}

Тепер зверніть увагу на те, що дії при переході між станами практично однакові. Відрізняються тільки
тривалості: 2000, 200, 500, 2000
значення, що передається у digitalWrite: HIGH, LOW, HIGH, LOW
номер наступного стану: 1, 2, 3, 0, 1, 2 ...

Таким чином можна використати один і той же код для циклічного переходу між станами. Тривалості та значення для digitalWrite помістимо у масиви, а значення з масивів вибиратимем по номеру стану:

unsigned int dur[4] = { 2000, 200, 500, 2000 };  // масив тривалостей (duration) для кожного стану
byte led[4] = { HIGH, LOW, HIGH, LOW };          // масив значень digitalWrite для кожного стану
int state = 0; // поточний стан. з початку - "0";

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;
    }
   }
}

Тепер зверніть увагу, що в масиві led всього два варіанти значень для digitalWrite: HIGH і LOW, і вони чергуються. Можна обійтись без цього масиву. Як його позбутись - вам в якості самостійного завдання smile

Остання редакція dimich (2024-03-19 22:45:57)

Неактивний

#33 2024-03-19 22:44:37

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

блін, це ж просто дійсно smile я чомусь собі вбив в голову що case можна використовувати тільки напрклад при опитуванні кнопки, і ось цей код не зрозумів поки що
static unsigned char task=0; // це ми тут оголошуємо змінну ? вірно?
switch (task)
=========================================================

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

как-то так...

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:   
       if (now - last_time >= 2000) { // пройшло 1000 мс ?
          digitalWrite(13, HIGH); // вмикаєм
          last_time = now;
          task=1; // переходим к следующей задаче
        }
       break; 
    case 1:   
       if (now - last_time >= 200) { // пройшло 300 мс ?
          digitalWrite(13, LOW); // вимикаєм
          last_time = now;
          task=2; 
        }
       break; 
    case 2:     
       if (now - last_time >= 500) { // пройшло 1000 мс ?
          digitalWrite(13, HIGH); // вмикаєм
          last_time = now;
          task=3;
        }
       break; 
    case 3: 
        if (now - last_time >= 2000) { // пройшло 300 мс ?
           digitalWrite(13, LOW); // вимикаєм
           last_time = now;
           task=0;
        }
       break; 
    default :
       break; 	
  } 


}

Неактивний

#34 2024-03-19 22:51:48

просто зайшов
Гість

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

"static unsigned char task=0; // це ми тут оголошуємо змінну ? вірно?"
нет, не верно
тут мы присваиваем начальное значение при запуске программы,
если убрать static , то переменная будет устанавливаться каждый раз при вызове функции.

#35 2024-03-19 22:56:11

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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

dimich пише:

Ця конструкція:

sxstalker пише:
  if (!on) {
...
  } else if (on) {
...
  } else if (!on) {
...
  } else if (on) {
...
  } 

не має сенсу. Якщо перша умова "if (!on)" виконалась, то решта вже не виконуються. А якщо не виконалась, то обовʼязково виконається друга - "if (on)", бо вона протилежна першій. А дві останні - ніколи не виконаються.

В попередньому прикладі у вас було всього два стани: світлодіод вимкнено, і світлодіод увімкнено. Тому було достатньо змінної типу bool, у якої всього два можливих значення.

В останньому прикладі у вас чотири стани:
* вимкнено перший раз (на 2000 мс)
* увімкнено перший раз (на 200 мс)
* вимкнено другий раз (на 500 мс)
* увімкнено другий раз (на 2000 мс)

Тому для збереження стану потрібна змінна такого типу, щоб могла приймати як мінімум 4 значення. Для простоти візьмем int. Стани будем нумерувати від 0 до 3. І для ясності перейменуєм змінну з "on" на "state".

int state = 0; // поточний стан. з початку - "0";

void loop() {
  unsigned long now = millis();

  if (state == 0) { // в стані "0"?
    if (now - last_time >= 2000) {
      digitalWrite(13, HIGH);
      last_time = now;
      state = 1; // переходим в стан "1"
    }
  } else if (state == 1) { // в стані "1"?
     if (now - last_time >= 200) {
      digitalWrite(13, LOW);
      last_time = now;
      state = 2; // переходим в стан "2"
    }
  } else if (state == 2) { // в стані "2"?
    if (now - last_time >= 500) {
      digitalWrite(13, HIGH);
      last_time = now;
      state = 3; // переходим в стан "3"
    }
  } else if (state == 3) { // в стані "3" ?
     if (now - last_time >= 2000) {
        digitalWrite(13, LOW);
       last_time = now;
       state = 0; // переходим в початковий стан "0"
    }
  }
}

Абсолютно те ж саме, тільки switch/case замість if/else. Так більш читабельно:

int state = 0; // поточний стан. з початку - "0";

void loop() {
  unsigned long now = millis();

  switch (state)
  {
    case 0:
      if (now - last_time >= 2000) {
        digitalWrite(13, HIGH);
        last_time = now;
        state = 1;
      }
      break;
    case 1:
      if (now - last_time >= 200) {
        digitalWrite(13, LOW);
        last_time = now;
        state = 2;
      }
      break;
    case 2:
      if (now - last_time >= 500) {
        digitalWrite(13, HIGH);
        last_time = now;
        state = 3;
      }
      break;
    case 3:
      if (now - last_time >= 2000) {
        digitalWrite(13, LOW);
        last_time = now;
        state = 0; // переходим в початковий стан "0"
      }
      break;
  }
}

Тепер зверніть увагу на те, що дії при переході між станами практично однакові. Відрізняються тільки
тривалості: 2000, 200, 500, 2000
значення, що передається у digitalWrite: HIGH, LOW, HIGH, LOW
номер наступного стану: 1, 2, 3, 0, 1, 2 ...

Таким чином можна використати один і той же код для циклічного переходу між станами. Тривалості та значення для digitalWrite помістимо у масиви, а значення з масивів вибиратимем по номеру стану:

unsigned int dur[4] = { 2000, 200, 500, 2000 };  // масив тривалостей (duration) для кожного стану
byte led[4] = { HIGH, LOW, HIGH, LOW };          // масив значень digitalWrite для кожного стану
int state = 0; // поточний стан. з початку - "0";

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;
    }
   }
}

Тепер зверніть увагу, що в масиві led всього два варіанти значень для digitalWrite: HIGH і LOW, і вони чергуються. Можна обійтись без цього масиву. Як його позбутись - вам в якості самостійного завдання smile

Неактивний

#36 2024-03-19 22:58:47

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

огромное спасибо вам! я еще почитаю тогда об этом smile
=================================

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

"static unsigned char task=0; // це ми тут оголошуємо змінну ? вірно?"
нет, не верно
тут мы присваиваем начальное значение при запуске программы,
если убрать static , то переменная будет устанавливаться каждый раз при вызове функции.

Неактивний

#37 2024-03-19 23:06:27

просто зайшов
Гість

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

рекомендую изучить "полный справочник по С" Герберт Шилдт
https://glagolew2010.narod.ru/
квалификаторы типов
и области видимости.

#38 2024-03-19 23:11:06

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

попробовал ваш код, но я так понимаю нужно инвертировать !HIGH и !LOW ? так как сейчас LED мигает наоборот smile
вот проект https://wokwi.com/projects/392815604378833921
==============================================

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

как-то так...

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:   
       if (now - last_time >= 2000) { // пройшло 1000 мс ?
          digitalWrite(13, HIGH); // вмикаєм
          last_time = now;
          task=1; // переходим к следующей задаче
        }
       break; 
    case 1:   
       if (now - last_time >= 200) { // пройшло 300 мс ?
          digitalWrite(13, LOW); // вимикаєм
          last_time = now;
          task=2; 
        }
       break; 
    case 2:     
       if (now - last_time >= 500) { // пройшло 1000 мс ?
          digitalWrite(13, HIGH); // вмикаєм
          last_time = now;
          task=3;
        }
       break; 
    case 3: 
        if (now - last_time >= 2000) { // пройшло 300 мс ?
           digitalWrite(13, LOW); // вимикаєм
           last_time = now;
           task=0;
        }
       break; 
    default :
       break; 	
  } 


}

Неактивний

#39 2024-03-19 23:12:10

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

спасибо! я обязательно посмотрю! smile
=========================================

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

рекомендую изучить "полный справочник по С" Герберт Шилдт
https://glagolew2010.narod.ru/
квалификаторы типов
и области видимости.

Неактивний

#40 2024-03-19 23:18:57

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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

dimich пише:

Ця конструкція:

sxstalker пише:
  if (!on) {
...
  } else if (on) {
...
  } else if (!on) {
...
  } else if (on) {
...
  } 

не має сенсу. Якщо перша умова "if (!on)" виконалась, то решта вже не виконуються. А якщо не виконалась, то обовʼязково виконається друга - "if (on)", бо вона протилежна першій. А дві останні - ніколи не виконаються.

В попередньому прикладі у вас було всього два стани: світлодіод вимкнено, і світлодіод увімкнено. Тому було достатньо змінної типу bool, у якої всього два можливих значення.

В останньому прикладі у вас чотири стани:
* вимкнено перший раз (на 2000 мс)
* увімкнено перший раз (на 200 мс)
* вимкнено другий раз (на 500 мс)
* увімкнено другий раз (на 2000 мс)

Тому для збереження стану потрібна змінна такого типу, щоб могла приймати як мінімум 4 значення. Для простоти візьмем int. Стани будем нумерувати від 0 до 3. І для ясності перейменуєм змінну з "on" на "state".

int state = 0; // поточний стан. з початку - "0";

void loop() {
  unsigned long now = millis();

  if (state == 0) { // в стані "0"?
    if (now - last_time >= 2000) {
      digitalWrite(13, HIGH);
      last_time = now;
      state = 1; // переходим в стан "1"
    }
  } else if (state == 1) { // в стані "1"?
     if (now - last_time >= 200) {
      digitalWrite(13, LOW);
      last_time = now;
      state = 2; // переходим в стан "2"
    }
  } else if (state == 2) { // в стані "2"?
    if (now - last_time >= 500) {
      digitalWrite(13, HIGH);
      last_time = now;
      state = 3; // переходим в стан "3"
    }
  } else if (state == 3) { // в стані "3" ?
     if (now - last_time >= 2000) {
        digitalWrite(13, LOW);
       last_time = now;
       state = 0; // переходим в початковий стан "0"
    }
  }
}

Абсолютно те ж саме, тільки switch/case замість if/else. Так більш читабельно:

int state = 0; // поточний стан. з початку - "0";

void loop() {
  unsigned long now = millis();

  switch (state)
  {
    case 0:
      if (now - last_time >= 2000) {
        digitalWrite(13, HIGH);
        last_time = now;
        state = 1;
      }
      break;
    case 1:
      if (now - last_time >= 200) {
        digitalWrite(13, LOW);
        last_time = now;
        state = 2;
      }
      break;
    case 2:
      if (now - last_time >= 500) {
        digitalWrite(13, HIGH);
        last_time = now;
        state = 3;
      }
      break;
    case 3:
      if (now - last_time >= 2000) {
        digitalWrite(13, LOW);
        last_time = now;
        state = 0; // переходим в початковий стан "0"
      }
      break;
  }
}

Тепер зверніть увагу на те, що дії при переході між станами практично однакові. Відрізняються тільки
тривалості: 2000, 200, 500, 2000
значення, що передається у digitalWrite: HIGH, LOW, HIGH, LOW
номер наступного стану: 1, 2, 3, 0, 1, 2 ...

Таким чином можна використати один і той же код для циклічного переходу між станами. Тривалості та значення для digitalWrite помістимо у масиви, а значення з масивів вибиратимем по номеру стану:

unsigned int dur[4] = { 2000, 200, 500, 2000 };  // масив тривалостей (duration) для кожного стану
byte led[4] = { HIGH, LOW, HIGH, LOW };          // масив значень digitalWrite для кожного стану
int state = 0; // поточний стан. з початку - "0";

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;
    }
   }
}

Тепер зверніть увагу, що в масиві led всього два варіанти значень для digitalWrite: HIGH і LOW, і вони чергуються. Можна обійтись без цього масиву. Як його позбутись - вам в якості самостійного завдання smile

Неактивний

#41 2024-03-19 23:26:51

просто зайшов
Гість

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

sxstalker пише:

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

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

#42 2024-03-19 23:38:06

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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

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

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

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

Неактивний

#43 2024-03-19 23:44:52

просто зайшов
Гість

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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

#44 2024-03-19 23:46:48

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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;
    }
   }
}

Неактивний

#45 2024-03-19 23:49:36

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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

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

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

Неактивний

#46 2024-03-19 23:49:51

просто зайшов
Гість

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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; 	
  } 


}

#47 2024-03-19 23:52:48

просто зайшов
Гість

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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

#48 2024-03-20 00:10:50

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

выбивает ошибку при запуске
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; 	
  } 


}

Неактивний

#49 2024-03-20 00:27:55

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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


}

Неактивний

#50 2024-03-20 00:39:42

sxstalker
Учасник
Зареєстрований: 2024-02-08
Повідомлень: 26

Re: Нужна помощь начинающему!!! 3-х режимный фонарик

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;
  }
}

Неактивний

Швидке повідомлення

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

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