Не работает код

arssev1
Offline
Зарегистрирован: 10.04.2014

Нужно выполнять цикл определенное количество миллисекунд (duration)

Почему это не работает

int timerBegin = millis();
int timerCounter;

while (timerCounter - timerBegin >= duration) {
    //исполняемый код
   timerCounter = millis();
}

 

vvadim
Offline
Зарегистрирован: 23.05.2012

для начала

unsigned long timerBegin;

 

 

 

arssev1
Offline
Зарегистрирован: 10.04.2014

Прям все красками заиграло... Ничего не изменилось

Nosferatu
Offline
Зарегистрирован: 04.11.2012
unsigned long timerBegin = millis();

while (millis() - timerBegin <= duration) {
    //исполняемый код
}

 

arssev1
Offline
Зарегистрирован: 10.04.2014

Спасибо огромное

Nosferatu
Offline
Зарегистрирован: 04.11.2012

Тут надо только учитывать, что millis()сбрасывается на ноль через  4294967295 миллисекунд (приблизительно 50 дней).

И если  сброс millis()на ноль произойдёт во время работы цикла, то этот цикл может работать 50 дней.

Поэтому надо в тела цикла вставить проверку и в случае необходимости выходить из него.

if(millis() - timerBegin < 0)
  break;

Если время работы цикла критично и останавливать его не желательно.

unsigned long timerBegin = millis();

if(timerBegin + duration > 4294967295){
  while (millis() - timerBegin <= duration) {
    //исполняемый код
    if(millis() - timerBegin < 0)
      break;
  }
}else{
  int duration2 = timerBegin + duration - 4294967295;
  while (millis() <= duration) {
    //исполняемый код
  }
}

Работоспособность кода не проверялась.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Опять про этот переход через ноль.....
Если честно- надоело.
Кто-нибудь может включить это крупными буквами в ФАК?

http://arduino.ru/forum/programmirovanie/eshche-raz-migaem-svetodiodom-b...

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

спрашивают , и будут спрашивать !
:(
и ФАКи не помогут !

viRus
Offline
Зарегистрирован: 23.01.2016

Здравствуйте, уважаемые форумчане!

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

Вобщем идея следующая - на даче есть освещение забора и двора. Нужно ежедневно автоматически включать освещение забора когда стемнеет и выключать его на рассвете, а освещение двора включать/отключать пультом 433МГц.

Посчитав, что для этой цели Arduino Nano - за глаза, и прикрутив к нему модуль реального времени, радиоприемник и двуканальное реле получил следующий тестовый стенд: 

(датчик влажности и температуры тут лишний)

Обладая весьма скромным опытом написания софта для ардуинки, и используя подходящие исходники из сети получил 2 скетча, в принципе делающие то что нужно:

1) Скетч управления освещением забора:

//Подключаем библиотеки:
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

int RelayA = 3;
 
void setup()  {
   Serial.begin(9600);
   // Ждём, пока запустится последовательный порт
   while (!Serial);
   // Устанавливаем функцию для получения времени с часов
   setSyncProvider(RTC.get);
   //Библиотека не получает время с часов каждый раз.
   //Задаётся функция для подключения к модулю часов
   //Библиотека получает с модуля время один раз
   //и далее ведёт отсчёт по внутренним часам Arduino,
   //синхронизируясь с часами по мере необходимости
   //выводим хранящееся в часах время
   Serial.print(hour());
   printDigits(minute());
   printDigits(second());
   Serial.println();
   
   if(timeStatus()!= timeSet)
   Serial.println("Unable to sync with the RTC");
   else
   Serial.println("RTC has set the system time");
   
   pinMode(13, OUTPUT); //инициализируем моргалку
   pinMode(RelayA, OUTPUT);
}
 
void loop()
{
   //Библиотека умеет определять, синхронизированы ли часы.
   if (timeStatus() == timeSet) {
   //Если синхронизированы, вызываем функцию для показа времени
   digitalClockDisplay();
   } else {
   //Если не синхронизированы, сообщим об этом
   Serial.println("The time has not been set.  Please run the Time");
   Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
   Serial.println();
   delay(500);
}
   delay(200);
   //вместо ожидания моргаем 13ым пином
   digitalWrite(13, HIGH);
   delay(500);
   digitalWrite(13, LOW);
   delay(1000);
}
 
   //Отображает время.
   void digitalClockDisplay(){
   Serial.print("Now: ");
   //День, месяц и год
   Serial.print(day());
   Serial.print("/");
   Serial.print(month());
   Serial.print("/");
   Serial.print(year());
   Serial.print(" ");
   if (weekday() == 1)
   Serial.print("Sunday");
   if (weekday() == 2)
   Serial.print("Monday");
   if (weekday() == 3)
   Serial.print("Tuesday");
   if (weekday() == 4)
   Serial.print("Wednesday");
   if (weekday() == 5)
   Serial.print("Thursday");
   if (weekday() == 6)
   Serial.print("Friday");
   if (weekday() == 7)
   Serial.print("Saturday");
   //Последовательно выводит часы, минуты, секунды
   Serial.print(" ");
   Serial.print(hour());
   printDigits(minute());
   printDigits(second());
   Serial.println();
   
   //delay(5000);
   
   if (((month() == 1) && (hour() >= 17)) || ((month() == 1) && (hour() < 9))) 
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 2) && (hour()>=18)) || ((month() == 2) && (hour()<9)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 3) && (hour()>=19)) || ((month() == 3) && (hour()<8)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 4) && (hour()>=20)) || ((month() == 4) && (hour()<6)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 5) && (hour()>=21)) || ((month() == 5) && (hour()<5)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 6) && (hour()>=22)) || ((month() == 6) && (hour()<5)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 7) && (hour()>=22)) || ((month() == 7) && (hour()<5)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 8) && (hour()>=21)) || ((month() == 8) && (hour()<6)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 9) && (hour()>=19)) || ((month() == 9) && (hour()<7)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 10) && (hour()>=18)) || ((month() == 10) && (hour()<8)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 11) && (hour()>=17)) || ((month() == 11) && (hour()<9)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 12) && (hour()>=17)) || ((month() == 12) && (hour()<10)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else
   {  digitalWrite(RelayA, HIGH);  // реле выключено
   Serial.println("Power OFF");}
   Serial.println();
   delay(5000);
}
   
void printDigits(int digits){
   // Функция для красивого вывода времени. Выводит ноль перед
   // односимвольными числами. "5" будет выведено как "05"
   Serial.print(":");
   if(digits < 10)
   Serial.print('0');
   Serial.print(digits);
}

2) Скетч радиоуправления:

// https://www.youtube.com/watch?v=-68WsZhl-PE

#define RX 2
#define TIMER_DIV
volatile byte level=255;
volatile unsigned long last, len;
byte p_level;
unsigned long p_len, p_len_prev;
struct 
{ 
  uint8_t state; 
  uint8_t data[3], dat_bit; 
} came; 
void set_bit(uint8_t *data, uint8_t n)
{
  data[n/8]|=1<<(n%8);
}

int RelayB = 4;
int statRelayB = 0;

#define CM_MAX_TE 450
#define CM_MIN_TE 250 
#define CM_BITS12 12 
#define CM_BITS24 24 

void process_came() 
{ 
  unsigned char b; 

  switch(came.state) 
  { 
    case 0: 
      if(p_level) break; 
      came.state=1; 
      break; 

    case 1: //start 
      if(!p_level) break; 

     else if(p_len>=CM_MIN_TE && p_len<=CM_MAX_TE) 
      { 
        came.state=2; 
        came.dat_bit=0; 
        came.data[0]=0x00; 
        came.data[1]=0x00; 
        came.data[2]=0x00; 
        
      } 
      else came.state=0; 
        
     
   
    case 2: //dat 
      if(p_level) 
      { 
        if(came.dat_bit==CM_BITS24) 
        { 
          came.state=0; 
          break; 
        } 

        if(p_len_prev<=CM_MAX_TE && p_len_prev>=CM_MIN_TE && 
           p_len<=CM_MAX_TE*2 && p_len>=CM_MIN_TE*2) b=0; 
         else 
        if(p_len_prev<=CM_MAX_TE*2 && p_len_prev>=CM_MIN_TE*2 && 
           p_len<=CM_MAX_TE && p_len>=CM_MIN_TE) b=1; 
         else 
        { 
          came.state=0; 
          break; 
        } 

        if(b) set_bit(came.data, came.dat_bit); 
        came.dat_bit++; 
        break; 
      } 
       else 
      { 
        if((p_len>5000)&&(came.dat_bit==CM_BITS12 || came.dat_bit==CM_BITS24)) came.state=100; 
      } 
      break; 
  } 
}  
void dump_hex(byte *buf, byte bits)
{
byte b;

for(b=0; b>(bits+7)/8; b++)
{
if(buf[b]>0x0f) Serial.print('0');
Serial.print(buf[b], HEX);
Serial.print(" ");
}
Serial.println("");
}
void rx_int()
{
if(level!=255) return;

len=micros()-last;
last=micros();

if(digitalRead(RX)==HIGH) level=0;
else level=1; 
}
void setup()
{ 
attachInterrupt(0, rx_int, CHANGE);

Serial.begin(9600); 
while(!Serial);

pinMode(RelayB, OUTPUT);
digitalWrite(RelayB, HIGH);

Serial.println("MEGA ARDUINO LOGGER");
Serial.println("");

interrupts();
} 

byte b;

void loop()
{ 
if(level!=255)
{
noInterrupts();
p_level=level;
p_len=len;
len=0;
level=255;
interrupts();

process_came();

p_len_prev = p_len;
}


if(came.state==100)
{
Serial.print(came.data[0],HEX);
Serial.print(came.data[1],HEX);
Serial.print(came.data[2],HEX);
//Serial.print("CAME[");
Serial.print("came[");
Serial.print(came.dat_bit);
Serial.print("]: ");

if (came.data[0] == 0xCF && came.data[1] == 0x6 && came.data[2] == 0x0 && came.dat_bit == 12)
{
  Serial.print("test");
  if (statRelayB == 0)
  statRelayB = 1;
  else
  statRelayB = 0;
}  
if (statRelayB == 1)
   {digitalWrite(RelayB, LOW);   // реле включено
   delay (500);}
   else
   digitalWrite(RelayB, HIGH);   // реле выключено

dump_hex(came.data, came.dat_bit);
came.state=0;
}
}

Все вроде бы хорошо, и остался сущий пустяк - объеденить их в 1 скетч, реализующий необходимый функционал. Но с этим беда..

У меня получилось:

// https://www.youtube.com/watch?v=-68WsZhl-PE

#define RX 2
#define TIMER_DIV
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

volatile byte level=255;
volatile unsigned long last, len;
byte p_level;
unsigned long p_len, p_len_prev;
struct 
{ 
  uint8_t state; 
  uint8_t data[3], dat_bit; 
} came; 
void set_bit(uint8_t *data, uint8_t n)
{
  data[n/8]|=1<<(n%8);
}

int RelayA = 3;
int RelayB = 4;
int statRelayB = 0;

#define CM_MAX_TE 450
#define CM_MIN_TE 250 
#define CM_BITS12 12 
#define CM_BITS24 24 

void process_came() 
{ 
  unsigned char b; 

  switch(came.state) 
  { 
    case 0: 
      if(p_level) break; 
      came.state=1; 
      break; 

    case 1: //start 
      if(!p_level) break; 

     else if(p_len>=CM_MIN_TE && p_len<=CM_MAX_TE) 
      { 
        came.state=2; 
        came.dat_bit=0; 
        came.data[0]=0x00; 
        came.data[1]=0x00; 
        came.data[2]=0x00; 
        
      } 
      else came.state=0; 
        
     
   
    case 2: //dat 
      if(p_level) 
      { 
        if(came.dat_bit==CM_BITS24) 
        { 
          came.state=0; 
          break; 
        } 

        if(p_len_prev<=CM_MAX_TE && p_len_prev>=CM_MIN_TE && 
           p_len<=CM_MAX_TE*2 && p_len>=CM_MIN_TE*2) b=0; 
         else 
        if(p_len_prev<=CM_MAX_TE*2 && p_len_prev>=CM_MIN_TE*2 && 
           p_len<=CM_MAX_TE && p_len>=CM_MIN_TE) b=1; 
         else 
        { 
          came.state=0; 
          break; 
        } 

        if(b) set_bit(came.data, came.dat_bit); 
        came.dat_bit++; 
        break; 
      } 
       else 
      { 
        if((p_len>5000)&&(came.dat_bit==CM_BITS12 || came.dat_bit==CM_BITS24)) came.state=100; 
      } 
      break; 
  } 
}  
void dump_hex(byte *buf, byte bits)
{
byte b;

for(b=0; b>(bits+7)/8; b++)
{
if(buf[b]>0x0f) Serial.print('0');
Serial.print(buf[b], HEX);
Serial.print(" ");
}
Serial.println("");
}
void rx_int()
{
if(level!=255) return;

len=micros()-last;
last=micros();

if(digitalRead(RX)==HIGH) level=0;
else level=1; 
}
void setup()
{ 
attachInterrupt(0, rx_int, CHANGE);

Serial.begin(9600); 
while(!Serial);
setSyncProvider(RTC.get);
   
   if(timeStatus()!= timeSet)
   Serial.println("Unable to sync with the RTC");
   else
   Serial.println("RTC has set the system time");

pinMode(13, OUTPUT); //инициализируем моргалку
pinMode(RelayA, OUTPUT);
pinMode(RelayB, OUTPUT);
digitalWrite(RelayB, HIGH);

Serial.println("NANO ARDUINO LOGGER");
Serial.println("");

interrupts();
} 

byte b;

void loop()
{ 
if(level!=255)
{
noInterrupts();
p_level=level;
p_len=len;
len=0;
level=255;
interrupts();

process_came();

p_len_prev = p_len;
}


if(came.state==100)
{
Serial.print(came.data[0],HEX);
Serial.print(came.data[1],HEX);
Serial.print(came.data[2],HEX);
//Serial.print("CAME[");
Serial.print("came[");
Serial.print(came.dat_bit);
Serial.print("]: ");

if (came.data[0] == 0xCF && came.data[1] == 0x6 && came.data[2] == 0x0 && came.dat_bit == 12)
{
  Serial.print("Signal A");
  if (statRelayB == 0)
  statRelayB = 1;
  else
  statRelayB = 0;
}  
if (statRelayB == 1)
   {digitalWrite(RelayB, LOW);   // реле включено
   delay (500);}
   else
   digitalWrite(RelayB, HIGH);   // реле выключено
   
dump_hex(came.data, came.dat_bit);
came.state=0;

}
//Библиотека умеет определять, синхронизированы ли часы.
   if (timeStatus() == timeSet) {
   //Если синхронизированы, вызываем функцию для показа времени
   digitalClockDisplay();
   } else {
   //Если не синхронизированы, сообщим об этом
   Serial.println("The time has not been set.  Please run the Time");
   Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
   Serial.println();
//   delay(500);
}
   //delay(200);
   //вместо ожидания моргаем 13ым пином
   digitalWrite(13, HIGH);
   delay(100);
   digitalWrite(13, LOW);
   delay(1000);
}

//Отображает время.
   void digitalClockDisplay(){
   Serial.print("Now: ");
   //День, месяц и год
   Serial.print(day());
   Serial.print("/");
   Serial.print(month());
   Serial.print("/");
   Serial.print(year());
   Serial.print(" ");
   if (weekday() == 1)
   Serial.print("Sunday");
   if (weekday() == 2)
   Serial.print("Monday");
   if (weekday() == 3)
   Serial.print("Tuesday");
   if (weekday() == 4)
   Serial.print("Wednesday");
   if (weekday() == 5)
   Serial.print("Thursday");
   if (weekday() == 6)
   Serial.print("Friday");
   if (weekday() == 7)
   Serial.print("Saturday");
   //Последовательно выводит часы, минуты, секунды
   Serial.print(" ");
   Serial.print(hour());
   printDigits(minute());
   printDigits(second());
   Serial.println();
   
   //delay(5000);
   
   if (((month() == 1) && (hour() >= 17)) || ((month() == 1) && (hour() < 9))) 
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 2) && (hour()>=18)) || ((month() == 2) && (hour()<9)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 3) && (hour()>=19)) || ((month() == 3) && (hour()<8)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 4) && (hour()>=20)) || ((month() == 4) && (hour()<6)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 5) && (hour()>=21)) || ((month() == 5) && (hour()<5)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 6) && (hour()>=22)) || ((month() == 6) && (hour()<5)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 7) && (hour()>=22)) || ((month() == 7) && (hour()<5)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 8) && (hour()>=21)) || ((month() == 8) && (hour()<6)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 9) && (hour()>=19)) || ((month() == 9) && (hour()<7)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 10) && (hour()>=18)) || ((month() == 10) && (hour()<8)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 11) && (hour()>=17)) || ((month() == 11) && (hour()<9)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else if (((month() == 12) && (hour()>=17)) || ((month() == 12) && (hour()<10)))
   {
   digitalWrite(RelayA, LOW);   // реле включено
   Serial.println("Power ON");}
   
   else
   {  digitalWrite(RelayA, HIGH);  // реле выключено
   Serial.println("Power OFF");}
   Serial.println();
   //delay(5000);
}
   
void printDigits(int digits){
   // Функция для красивого вывода времени. Выводит ноль перед
   // односимвольными числами. "5" будет выведено как "05"
   Serial.print(":");
   if(digits < 10)
   Serial.print('0');
   Serial.print(digits);
}

И.. ничего не работает) Вернее не работает функционал с радиоуправлением. Подскажите, пожалуйста, где тут ошибки?)

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

Ошибка в МОЗГУ!

Устал повторять.

1. Пойми что ты хочешь

2. Положи ТЗ  (техзадание) на бумагу

3. составь алгоритм

4 разбей на блоки

5 реализуй их по очереди

6 собери в кучу.

Поверь - все получится!

А, забыл про пункт 0 - если берешь чужие скетчи - пойми как они работаю прежде чем применять!!!!!!!

viRus
Offline
Зарегистрирован: 23.01.2016

Спасибо! Отлично!
Максимально бесполезный ответ - и не помог и оскарбил, молодец!
На самом деле все так и сделал, пока проект как раз на 6 стадии по твоему списку. Знаю что вопрос глупый и скорее всего там ерунда, но вот решил обратиться за помощью, неужели сложно помочь если знаешь?

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

Сложно. Потому что:

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

2. нет описания и даташита на модуль радиоприема, и пульта подачи сигнала.

3. непонятно работает ли собственно сам приемник на макете без всего остального?

viRus
Offline
Зарегистрирован: 23.01.2016

2. Взял приемник вместе с передатчиком вот здесь: http://www.aliexpress.com/snapshot/7192121336.html?orderId=71679949833286

Передатчик выкинул, использую стандартный универсальный брелок на 433 Мгц, код кнопки, как можно видеть из соответствующего скетча: CF60 12.

3. Как я уже писал выше - имеем 2 полностью рабочих по отдельности скетча, которые просто нужно объединить в один.

1. Самое главное - если не хочешь разобраться, помочь, какого тогда рожна голову морочишь?!)

viRus
Offline
Зарегистрирован: 23.01.2016

Разобрался, как и ожидалось, все было просто)
Очень полезный форум, что бы я без него делал))
Особенно без тебя, at0mix)))