millis() не могу разобраться

staff67
Offline
Зарегистрирован: 21.04.2020

Объясните пожалуйста на примере данного кода, как работает millis()?

const int ledPin12 = 12;
const int ledPin13 = 13;
const int vhod_9 = 9;
unsigned long last_time;
void setup() {
pinMode (ledPin12, OUTPUT);
pinMode (ledPin13, OUTPUT);
pinMode (vhod_9, INPUT);
}
 
void loop() {
 if (digitalRead(vhod_9))
 {digitalWrite(ledPin12, HIGH);
 digitalWrite(ledPin13, LOW);
 if (millis() - last_time >= 1000){
  digitalWrite(ledPin12, LOW);
  digitalWrite(ledPin13, HIGH);
  last_time = millis();
   if (millis() - last_time >= 1000){
     digitalWrite(ledPin12, HIGH);
     digitalWrite(ledPin13, LOW);
 
 
   }}}}
написал это просто, что бы попробовать разобраться, ибо никак не могу понять.
По моей идее при подаче на вход 9 светодиод на 12 должен гореть, на 13 не гореть и через секунду наоборот. Что я делаю не так?

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

А почитать про "великое переполнение миллис"? Да и вообще - про правила форума - лениво?

И, кстати void loop() работает по кругу, а не так, как Вам кажется.

staff67
Offline
Зарегистрирован: 21.04.2020

Здравствуйте, спасибо за ответ. Великое переполнение millis() это же вроде которое через 49,7 дней не?

Про void loop я вкурсе, такой конец у кода, потому что нифега не работало (и не работает), просто попробовал дописать.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Миллис работает так: каждую миллисекунду возвращаемое значение увеличивается на 1.
Т.е. в любой момент времени millis() возвращает количество миллисекунд прошедшее с начала старта программы.

Теперь зная это самостоятельно сможете разобраться как с помощью этого значения замерять нужные отрезки времени ?

Запомнили сколько было, при начале замера, сравниваем с тем, сколько сейчас, когда дошли до нужной разницы, что то делаем

sadman41
Offline
Зарегистрирован: 19.10.2016

staff67 пишет:

Что я делаю не так?

Правила не читаете, код вставляете неправильно.

staff67
Offline
Зарегистрирован: 21.04.2020


const int ledPin12 = 12;
const int ledPin13 = 13;
const int vhod_9 = 9;
unsigned long last_time;
void setup() {
pinMode (ledPin12, OUTPUT);
pinMode (ledPin13, OUTPUT);
pinMode (vhod_9, INPUT);
}

void loop() {
 if (digitalRead(vhod_9))
 {digitalWrite(ledPin12, HIGH);
 digitalWrite(ledPin13, LOW);
 if (millis() - last_time >= 1000){
  digitalWrite(ledPin12, LOW);
  digitalWrite(ledPin13, HIGH);
  last_time = millis();
   if (millis() - last_time >= 1000){
     digitalWrite(ledPin12, HIGH);
     digitalWrite(ledPin13, LOW);


   }}}}

Прошу прощения.

staff67
Offline
Зарегистрирован: 21.04.2020

Спасибо за ответ, да я вроде это понимаю, не понимаю, почему в данном коде это не работает.

 if (millis() - last_time >= 1000)

переменная last_time при объявление должна ровняться нулю же вроде, а millis увеличивается каждую миллисекунду на 1.

 

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

А почему 18-я строка, а не 22-я? Какой тут императив?

А вообще - бред. Можете простыми словами описать то, что Вы хотите сделать? В программе - бредятина.

nik182
Offline
Зарегистрирован: 04.05.2015

Скобки нужны в правильных местах согласно задуманному алгоритму, а строки 19-21 вообще лишние, достаточно в строках 16 17 написать   digitalWrite(13, !digitalRead(13)); строки 13 14 перенести в сетап.

 
sadman41
Offline
Зарегистрирован: 19.10.2016

staff67 пишет:

Спасибо за ответ, да я вроде это понимаю, не понимаю, почему в данном коде это не работает.

 if (millis() - last_time >= 1000)

переменная last_time при объявление должна ровняться нулю же вроде, а millis увеличивается каждую миллисекунду на 1

Таких строки две. Одна не будет работать никогда.

Paul_it
Offline
Зарегистрирован: 25.06.2019

Он написал в первом комментарии темы, что хочет чтобы вроде 10, 11, 12 светодиоды через промежутки времени зажигались. Хочет короче попробовать delay() на millis() поменять

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Напишу Вам алгоритм, а Вы его запрограммируйте.

При инициации горит А, Б, не горит В: считываем миллис

В основной программе

Если ((миллис-минус-считыная миллис) больше (какое-то там значение)){

Меняем значение всех пинов на противоположные

считываем миллис

}

 

nik182
Offline
Зарегистрирован: 04.05.2015

Ты ещё кнопку забыл, после нажатия которой должно происходить всё остальное.

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

staff67 пишет:


const int ledPin12 = 12;
const int ledPin13 = 13;
const int vhod_9 = 9;
unsigned long last_time;
void setup()
{
  pinMode (ledPin12, OUTPUT);
  pinMode (ledPin13, OUTPUT);
  pinMode (vhod_9, INPUT);
}

void loop()
{
  if (digitalRead(vhod_9))
  { digitalWrite(ledPin12, HIGH);
    digitalWrite(ledPin13, LOW);
    if (millis() - last_time >= 1000)
    {
      digitalWrite(ledPin12, LOW);
      digitalWrite(ledPin13, HIGH);
      last_time = millis();
      if (millis() - last_time >= 1000)
      {
        digitalWrite(ledPin12, HIGH);
        digitalWrite(ledPin13, LOW);
      }
    }
  }
}

Прошу прощения.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

nik182 пишет:

Ты ещё кнопку забыл, после нажатия которой должно происходить всё остальное.

Пусть без кнопки напишет. Потом добавит.Дам одно "если" и одна переменная

nik182
Offline
Зарегистрирован: 04.05.2015

Она уже была в программе - строка 12.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

nik182 пишет:

Она уже была в программе - строка 12.

И правда! О как!

Ну допишите алгоритм! Это-ж легко!

nik182
Offline
Зарегистрирован: 04.05.2015

Я уже всё расписал в #8 Сделать эти исправления и заработает как надо. 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Как то так


const int ledPin12 = 12;
const int ledPin13 = 13;
const int vhod_9 = 9;
unsigned long last_time;
bool f_kn = 0;

void setup() {
  pinMode (ledPin12, OUTPUT);
  pinMode (ledPin13, OUTPUT);
  pinMode (vhod_9, INPUT);
}

void loop() {
  if (digitalRead(vhod_9) && f_kn == 0) {
    f_kn = 1;
    last_time = millis(); //Засекаем время
    digitalWrite(ledPin12, HIGH);
    digitalWrite(ledPin13, LOW);
  }

  if (f_kn == 1)
  {
    if (millis() - last_time >= 1000) { //проверяем прошла ли секунда
      digitalWrite(ledPin12, LOW);
      digitalWrite(ledPin13, HIGH);
      f_kn = 0;
    }
  }
}

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

nik182 пишет:

Я уже всё расписал в #8 Сделать эти исправления и заработает как надо. 

Да ну!



void loop(){
oldmillis=millis();
while(knopka){
if(millis()-oldmillis>mytimes){
digitalWrite(A, !digitalRead(A));
.....
oldmillis=millis();
}
 }
 }
mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

И кстати еще интересней так:


void loop(){
while(!knopka){
digitalWrite(A, "к примеру 1"));
.....
}
oldmillis=millis();
while(knopka){
if(millis()-oldmillis>mytimes){
digitalWrite(A, !digitalRead(A));
.....
oldmillis=millis();
}
 }
 }

 

staff67
Offline
Зарегистрирован: 21.04.2020

Привет, всем спасибо за ответы!

Этот код:

vosara пишет:

Как то так


const int ledPin12 = 12;
const int ledPin13 = 13;
const int vhod_9 = 9;
unsigned long last_time;
bool f_kn = 0;

void setup() {
  pinMode (ledPin12, OUTPUT);
  pinMode (ledPin13, OUTPUT);
  pinMode (vhod_9, INPUT);
}

void loop() {
  if (digitalRead(vhod_9) && f_kn == 0) {
    f_kn = 1;
    last_time = millis(); //Засекаем время
    digitalWrite(ledPin12, HIGH);
    digitalWrite(ledPin13, LOW);
  }

  if (f_kn == 1)
  {
    if (millis() - last_time >= 1000) { //проверяем прошла ли секунда
      digitalWrite(ledPin12, LOW);
      digitalWrite(ledPin13, HIGH);
      f_kn = 0;
    }
  }
}

 

Зажигает светодиод на 12 и примерно через 3 сек. он тухнет и загорается на 13ти. Не понятно почему. В коде мне вроде бы всё понятно, кроме того почему он не работает.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

staff67 пишет:

Этот код:

Дерьмовый. Плохо читали.

MiLy
Offline
Зарегистрирован: 13.01.2021

Привет всем. Я новенький, первый раз на форуме. Совсем недавно начал изучать ардуино. Есть вопрос по синхронизации мигания светодиодов на 3 ардуино. Суть в чём, есть 3 платы (самопал аля UNO). На каждой реле, светодиод в роли маяка, модуль nRF24 и датчик. Запустили платы в разное время. На каждой плате, датчик мониторит вокруг на наличие "посетителей", при обнаружении "коих" через него, плата подаёт команду по nRF (работаю как и должны китайские модули) остальным платам включить реле на Н-секунд. Маяки на платах начинают синхронно мигать (+-0,05 сек), НО вот при выключении реле появляется рассинхрон в их мигании на платах. Мигание маяками сделано через millis. Понимаю, что проблема как раз в этом зарыта. Можете объяснить, чего не учёл.

// библиотеки
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 10); // CE - CSN

// вводим директивы имён
#define adres1 0xAABBCCDD11LL
#define adres2 0xAABBCCDD22LL
#define adres3 0xAABBCCDD33LL

#define mayak 5
#define rele 7
#define datchik A0

// данные и переменные
int val; // переменная для датчика
int data[1]; //массив отправки по РД
int kodProverki = 777; //код передачи и проверки данных
int lvlSrab = 100; //уровень срабатывания по датчику
int timeRele = 25; //время работы реле
int a = 0; // переменная для цикла
// мигающий светодиод для визуального контроля работы
int mayakOn = 150; // светодиод включен
int mayakOff = 850; // светодиод выключени
bool statusMayak; // переменная статуса маяка
uint32_t timerMayak; // переменная отсчета millis для маяка

void setup() 
{
  delay(3000); //задержка перед началом работы
  
  //натройка пинов МК
  pinMode(rele, OUTPUT); // пин реле на выход
  digitalWrite(rele, LOW); // начальное состояние реле - выклюяено
  pinMode(mayak, OUTPUT); // пин светодиода 
  digitalWrite(mayak, statusMayak = LOW); // светодиод выключен, задан статус

  //Serial.begin(9600); // настройка монитора порта

  //настройка модуля nRF24
  radio.begin(); //инициализация модуля
  radio.setChannel (120); // канал работы (0-127) (115 - 127 без wifi)
  radio.setDataRate (RF24_250KBPS); // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS)
  radio.setPALevel (RF24_PA_MAX); // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)

  //выбираем адреса прослушиваемых труб
  //radio.openReadingPipe (1, adres1); // Открываем 1 трубу с идентификатором 1 передатчика 0xAABBCCDD11, для приёма данных
  radio.openReadingPipe (2, adres2); // Открываем 2 трубу с идентификатором 2 передатчика 0xAABBCCDD22, для приёма данных
  radio.openReadingPipe (3, adres3); // Открываем 3 трубу с идентификатором 3 передатчика 0xAABBCCDD33, для приёма данных

  //включаем режим приемника, слушаем выбранные трубы
  radio.startListening ();
}

void RELE() //срабатывание реле
{
  digitalWrite(rele, HIGH); //включаем реле
  for( a; a < timeRele; a++) //цикл для отработки реле положенного времени
  {
    
    digitalWrite(mayak, HIGH);
    delay(mayakOn);
    digitalWrite(mayak, LOW);
    delay(mayakOff); 
    //Serial.println(a); // контроль действий по монитору порта
  }
  digitalWrite(rele, LOW);
  a = 0;
}

void PEREDACHA() // перевод в режим передатчика и отправка данных
{
  // т.к. модули ПОЛУДУПЛЕКСНЫЕ, то работаем по следующему алгоритму
  radio.stopListening(); //выключаем режим передатчика
  //Serial.println("выключаем прослушивание"); // контроль действий по монитору порта
  /*
  radio.openWritingPipe(adres1); // открывание для передачи 1 трубу
  radio.write(data, 1); // передаем данные по 1 трубе
  delay(50); //задержка для передачи
  Serial.println("передали по 1 трубе"); // контроль действий по монитору порта
  */
  radio.openWritingPipe(adres2); // открываем для передачи 2 трубу
  radio.write(data, 1); // передаем данные по 2 трубе
  delay(50); // задержка для передачи
  //Serial.println("передали по 2 трубе"); // контроль действий по монитору порта
  
  radio.openWritingPipe(adres3); // открываем для передачи 3 трубу
  radio.write(data, 1); // передаем данные по 3 трубе
  delay(50); // задержка для передачи
  //Serial.println("передали по 3 трубе"); // контроль действий по монитору порта
  
}

void PRIEMNIK() // перевод в режим приемника для прослушивания данных
{
  //radio.openReadingPipe (1, adres1);
  radio.openReadingPipe (2, adres2);
  radio.openReadingPipe (3, adres3);
  radio.startListening();
  //Serial.println("слушаем эфир");
}

void MAYAK()
{
  if(millis() - timerMayak > (statusMayak ? mayakOn : mayakOff)) // если разница будет больше, то
  {
    statusMayak = !statusMayak; // инвертируем статус маяка
    digitalWrite(mayak, statusMayak); // выводм на пин маяка его статус (вкл или выкл)
    timerMayak = millis(); // сбрасываем таймер отсчета
  }
}

void loop() 
{
  val = analogRead(datchik);
  if( val < lvlSrab)
  {
    data[0] = kodProverki; // назначаем в данные код
    PEREDACHA();
    RELE();
    PRIEMNIK();
    timerMayak = millis();
  }

  if(radio.available()) // проверяем буфер на имеющиеся принятые данные, если они есть, то
  {
    radio.read(data,1); // читаем данные
    if(data[0] == kodProverki) // сверяем пришедшие данные с теми что есть, если равны то
     {
      RELE();
     }
  }

  MAYAK();
}
  

  

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

Стандартная практика: ОДНА ардуина должна всем посылать синхроимпульсы, не надеясь на их внутренний millis(), иначе будешь наблюдать такие Лиссажу, как наблюдаешь сейчас. 

MiLy
Offline
Зарегистрирован: 13.01.2021

DetSimen пишет:

Стандартная практика: ОДНА ардуина должна всем посылать синхроимпульсы, не надеясь на их внутренний millis(), иначе будешь наблюдать такие Лиссажу, как наблюдаешь сейчас. 

Поскольку радиомодули nRF24L01+ полудуплексные ,то пока не представляю, как одна ардуино может получить команду на включение реле, если она не в режиме приёмника, а в режиме передатчика (который передаёт синхроимпульсы остальным). Возможно ли синхронизировать по радиокоманде millis не через WDT?

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

Думай. На то тебе и образование дадено. 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Корифеи, вы таки будете смеяться, но у меня только что возник академический интерес в теме, смежной с micros()!! :-D

Сейчас рядом тему заппилю

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

 

[/quote]

Зажигает светодиод на 12 и примерно через 3 сек. он тухнет и загорается на 13ти. Не понятно почему. В коде мне вроде бы всё понятно, кроме того почему он не работает.

[/quote]

staff67 пишет:

По моей идее при подаче на вход 9 светодиод на 12 должен гореть, на 13 не гореть и через секунду наоборот. Что я делаю не так?

И что там не так РАБОТАЕТ

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

MiLy пишет:

Поскольку радиомодули nRF24L01+ полудуплексные ,то пока не представляю, как одна ардуино может получить команду на включение реле, если она не в режиме приёмника, а в режиме передатчика (который передаёт синхроимпульсы остальным). Возможно ли синхронизировать по радиокоманде millis не через WDT?

ну как? - передал синхроимпульс и слушаешь до следующего...

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

MiLy пишет:

Привет всем. Я новенький, первый раз на форуме. Совсем недавно начал изучать ардуино.  ...... На каждой реле, светодиод в роли маяка, модуль nRF24 и датчик. 

Осмелюсь дать рекомендацию по поводу использования nrf24. Потратил на них впустую много времени. Утром работает, а к обеду нет. К ночи оживает. Меняешь модуль и все по новой. Очень глючные они и нестабильные даже в одной посылке. Заниматься решением проблем с ними - заведомо терять ценное время. Если нужна локальная радиосвязь, я бы смотрел на другие технические решения, благо их много. Тем более у НРФ совсем убогие условия и на топологию, и на протокол.

MiLy
Offline
Зарегистрирован: 13.01.2021

Rumata пишет:

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

А можете порекомендовать что-то конкретное (кроме ZigBEE). В дальнейшем планирую использовать LoRa RA-02 (433). 

MiLy
Offline
Зарегистрирован: 13.01.2021

b707 пишет:

ну как? - передал синхроимпульс и слушаешь до следующего...

Спасибо за совет. Попробую.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

MiLy пишет:

А можете порекомендовать что-то конкретное (кроме ZigBEE). В дальнейшем планирую использовать LoRa RA-02 (433). 

Использую ESP (8266, 32) во всех проектах. В использовании AVR теперь не вижу никакого смысла. У меня везде покрытие WiFi. И дома и на даче и на работе. Это и определило выбор. Для передачи одиночных пакетов данных использую протокол UDP. О преимуществах пакета UDP над убогим 32-байтным пакетом nRF24 умолчу. Плюс, возможность "из коробки" управлять всем зоопарком устройств хоть blynk'ом, хоть putty. А собственный VPN сильно упрощает адресацию модулей на удаленных территориях - все в одной подсети. Для передачи данных "в поле" без интернета рассматривал LoRa. Даже заказал из китая несколько модулей, но до практической части пока не дошел. 

Есть и другие варианты, но я с ними не экспериментировал, поскольку ESP полностью закрыли вопрос межмодульной коммуникации. В одном я убежден - любой из этих вариантов будет заведомо перспективнее nFR24. Не зря даже сам разработчик этого ублюдочного решения, устрашившись содеянного быстро свернул производство. Теперь NRF только из самых трущобных китайских подвалов появляются