Как заставить работать реле через millis()

NikitaS
Offline
Зарегистрирован: 22.10.2016

Есть задача включать реле на 50 минут и выключать на 20 минут. Пока что пробую на светодиоде по примеру Блинка без delay(). Для удобства тестирования светится 1 минуту, полминуты отдыхает. Вначале диод включается через положенную 1 минуту, а дальше не гаснет. Никак не могу понять, как довести до ума, без вашей помощи не обойтись мне! Вот код:

unsigned long previousMillis1 = 0;        // will store last time LED was updated
unsigned long previousMillis2 = 0;

const long interval_1 = 60000;//3000000;  
const long interval_2 = 30000;//900000;
int led = 13;

void setup()
{
 pinMode(led, OUTPUT);
}

void loop()
{
unsigned long currentMillis = millis();  
  {
if (currentMillis - previousMillis2 >= interval_1) {
    previousMillis2 = currentMillis;
digitalWrite(led,LOW);
}

delay(1000);

if (currentMillis - previousMillis1 >= interval_2) {
    previousMillis1 = currentMillis;
  digitalWrite(led, HIGH);
}
 }
}

 

b707
Онлайн
Зарегистрирован: 26.05.2017

строки 16, 22 и 28 лишние.

Внимательно прочитайте еще раз блинк_без_делай - разве там два Previousmillis ? и два условия? - нет, все делается в одном. - в этом ваша проблема

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Гаснет. Но потом сразу включается. Потому что интервалы у вас кратные и события происходят одно за другим. А зажигается светодиод в два раза чаще, чем тушится. 

Вот ваш же код:

unsigned long previousMillis1 = 0;        // will store last time LED was updated
unsigned long previousMillis2 = 0;

const long interval_1 = 6000;//3000000;
const long interval_2 = 3000;//900000;
int led = 13;

void setup()
{
  pinMode(led, OUTPUT);
}

void loop()
{
  unsigned long currentMillis = millis();
  {
    if (currentMillis - previousMillis2 >= interval_1) {
      previousMillis2 = currentMillis;
      digitalWrite(led, LOW);
    }

    //delay(1000);

    if (currentMillis - previousMillis1 >= interval_2) {
      previousMillis1 = currentMillis;
      digitalWrite(led, HIGH);
    }
  }
}

Светодиод визуально горит? А если поменять интервалы местами?
 

const long interval_1 = 3000;//3000000;
const long interval_2 = 6000;//900000;

 

NikitaS
Offline
Зарегистрирован: 22.10.2016

Код подправил. 2 Previousmillis мне нужны, потому что диод должен быть в потушенном состоянии ~в два раза меньше, чем во включенном состоянии. А как это реализовать через один Previousmillis, ума не приложу.

unsigned long previousMillis1 = 0;       
unsigned long previousMillis2 = 0;

const long interval_1 = 60000;//3000000;  
const long interval_2 = 30000;//900000;
int led = 13;

void setup()
{
 pinMode(led, OUTPUT);
}

void loop()
{
unsigned long currentMillis = millis();  
if (currentMillis - previousMillis2 >= interval_1) {
    previousMillis2 = currentMillis;
digitalWrite(led,LOW);
}
if (currentMillis - previousMillis1 >= interval_2) {
    previousMillis1 = currentMillis;
  digitalWrite(led, HIGH);
}
}

 

NikitaS
Offline
Зарегистрирован: 22.10.2016

sadman41 пишет:

Светодиод визуально горит? А если поменять интервалы местами?

const long interval_1 = 3000;//3000000;
const long interval_2 = 6000;//900000;

Да, горит. Если поменять местами, то 3 секунды горит, на 3 с. гаснет.

b707
Онлайн
Зарегистрирован: 26.05.2017

NikitaS пишет:

Код подправил. 2 Previousmillis мне нужны, потому что диод должен быть в потушенном состоянии ~в два раза меньше, чем во включенном состоянии.

Для этого не нужно два Previousmillis. Нужно всего лишь при каждом переключении диода менять интервал следующего переключения, приравнивая его то interval1. то interval2.

А Previousmillis и условие проверки должно быть одно.

NikitaS
Offline
Зарегистрирован: 22.10.2016

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

unsigned long previousMillis = 0;

const long interval_1 = 8000;//3000000;
const long interval_2 = 3000;//900000;
int led = 13;
int interv = interval_2;

void setup()
{
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interv) {
          if (interv == interval_2) interv = interval_1;
      else interv = interval_2;
      previousMillis = currentMillis;
            Serial.println(interv);
      digitalWrite(led, !digitalRead(led));
    }
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

unsigned long prev = 0;  //для тамера
int interval = 50; //интервал мин
#define led 13     // пин реле


void setup() {
 pinMode (led, OUTPUT);
 digitalWrite (led,1);

}

void loop() {
if (millis() - prev > (unsigned long)interval*60000UL ){

  if (digitalRead(led)) interval = 20;
  else                  interval = 50;

  digitalWrite (led, !digitalRead(led));
  
  prev = millis();
  }
}
NikitaS
Offline
Зарегистрирован: 22.10.2016

MaksVV, протестировал Ваш код. Все замечательно, кроме маленького нюанса, а именно - диод 50 минут не светится, 20 горит. А должно быть наоборот. Заменил единицу на 0 в 8-й строке Вашего кода, теперь вроде сначала горит. Буду тестировать дальше. Спасибо!

MaksVV
Offline
Зарегистрирован: 06.08.2015

Может вы реле уже подключили? У реле обычно логика включения инвертирована. Т.е. если на пине лог. 0 то реле включено.

NikitaS
Offline
Зарегистрирован: 22.10.2016

Да, решил сразу на Аттини13 с подключенным реле испробовать.

Я этого не знал. Это очень странно, и на первый взгляд нелогично. Для меня, новичка, к тому же неудобно. Но что поделаешь, раз так сделали.

NikitaS
Offline
Зарегистрирован: 22.10.2016

После нескольких включений-выключений 20 и 50 минут меняются местами, то есть горит 20 и выключается на 50 минут.

MaksVV
Offline
Зарегистрирован: 06.08.2015

может так 


unsigned long prev = 0;  //для тамера
int interval = 50; //интервал мин
#define led 13     // пин реле


void setup() {
 pinMode (led, OUTPUT);
 digitalWrite (led,0);

}

void loop() {
if (millis() - prev > (unsigned long)interval*60000UL ){

  if (!digitalRead(led)) interval = 20;
  else                  interval = 50;

  digitalWrite (led, !digitalRead(led));
  
  prev = millis();
  }
}

 

RoN
Offline
Зарегистрирован: 28.12.2017

У меня на данный момент схожая ситуация, отличие только в том что я планирую управлять двумя реле 1-е вкл/выкл кулера, а 2-е для вкл/выкл прибора.
В идеале должно быть так чтобы с помощью первой тактовой кнопки вводилось время работы прибора (2-го реле), например 25 минут, с помощью 2ой запуск таймеров.
Включение кулера (реле 1), происходит сразу при подаче питания.
Через 3 минуты происходит запуск прибора (2е реле) и по истечии 25 минут, должно оключится.
Выключение кулера (1е реле) происходит через 20 минут после отключения прибора (2го реле).
Пока пробую на светодиодах без кнопок, время ввожу программно. Данный код работает до момента выключения 1го реле и никак не могу заставить его погаснуть в нужное время. нужное время.
Код я писал не сам (взял изи видеуроков). Пожалуйста помогите.

//culler

    int ledPin1 =  12;      // the number of the LED pin
    int ledState1 = LOW;             // ledState used to set the LED
    unsigned long previousMillis1 = 0;        // will store last time LED was updated
    long OnTime1 = 0;           // milliseconds of on-time
    long OffTime1 = 2300;          // milliseconds of off-time
 //pribor   
    int ledPin2 =  13;      // the number of the LED pin
    int ledState2 = LOW;             // ledState used to set the LED
    unsigned long previousMillis2 = 0;        // will store last time LED was updated
    long OnTime2 = 300;           // milliseconds of on-time
    long OffTime2 = 300;          // milliseconds of off-time

    int Value = 1000;

    void setup() 
    {
      // set the digital pin as output:
      pinMode(ledPin1, OUTPUT);      
      pinMode(ledPin2, OUTPUT);      
    }
     
    void loop()
    {
      
      unsigned long currentMillis = millis();
      if((ledState1 == HIGH) && (currentMillis - previousMillis1 >= OnTime1))
      {
        ledState1 = LOW;  // Turn it off
        previousMillis1 = currentMillis;  // Remember the time
        digitalWrite(ledPin1, ledState1);  // Update the actual LED
      }
   else if ((ledState1 == LOW) && (currentMillis - previousMillis1 >= OffTime1 + Value))
      {
        ledState1 = HIGH;  // turn it on
        previousMillis1 = currentMillis;   // Remember the time
        digitalWrite(ledPin1, ledState1);    // Update the actual LED 
      }
  
       
     

      if((ledState2 == HIGH) && (currentMillis - previousMillis2 >= OnTime2))
      {
        ledState2 = LOW;  // Turn it off
        previousMillis2 = currentMillis;  // Remember the time
        digitalWrite(ledPin2, ledState2);  // Update the actual LED
         
      }
 
      else if ((ledState2 == HIGH) && (currentMillis - previousMillis2 >= OffTime2 + OffTime1 + Value))
      {
        //ledState2 = LOW;  // turn it on
        previousMillis2 = currentMillis;   // Remember the time
       // digitalWrite(ledPin2, ledState2);   // Update the actual LED
           
       }
    ledState1 = LOW;


    }

 

NikitaS
Offline
Зарегистрирован: 22.10.2016

MaksVV пишет:

может так 

Так работает, спасибо. Почему я не стал использовать delay(). Следующий код работает очень странно. На Аттини13 светится 1 минуту, гаснет на 20 сек. На Ардуино светится где-то 5 мин.:

const int led =  13;
#define inter1 50*6000UL
#define inter2 20*6000UL

//unsigned long inter1 = 3000000UL; // пробовал и так
//unsigned long inter2 = 1200000UL;

void setup()
{
 pinMode(led, OUTPUT);
}

void loop()
{
 digitalWrite(led, LOW);
 delay(inter1);
 digitalWrite(led, HIGH);
 delay(inter2);
}

 

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

RoN пишет:

Пропуйте


#define led1 13 
#define led2 12
uint32_t time;
uint32_t pausa = 3000;
byte(f_vk) = 1;
//int led = 13;


void setup() {
  // put your setup code here, to run once:
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  digitalWrite(led1, HIGH);
  digitalWrite(led2, LOW);
  //Serial.begin(9600);
  time = millis();
}

void loop() {
  if(f_vk == 1 && millis()-time >= pausa){
    digitalWrite(led2, !digitalRead(led2));
    time = millis();
    if(digitalRead(led2))pausa = 25000;
    else pausa = 20000, f_vk = 2;
  }

  if(f_vk == 2 && millis() - time >= pausa){
    digitalWrite(led1, LOW);
    f_vk = 0;  
  } 
}

 

AntonHT
Offline
Зарегистрирован: 29.12.2017

Как то от нечего делать набросал програмку выполняющую функцию часов, считает секунды, минуты, часы. Может чем поможет, покрайней мере ее можно переделать под ваши нужды.

#include <Wire.h>
//#include <WolfCrystal.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);
//WolfCrystal WC(&lcd);

byte sec = 0;
byte minut = 0;
byte hor = 0;
int timer = 0;
int currentSec = 0;

void setup() {
  lcd.init();
  lcd.backlight();
  //  lcd.print(WC.GS("Ардуино"));
  lcd.print("Timer 1");
  //  lcd.setCursor(8,1);
  //  lcd.print("LCD 1602");

}

void loop() {

  ///////////////////////// обработка таймера

  lcd.setCursor(0, 0);
  lcd.print("Timer 1");

  if ((millis() / 1000) - currentSec >= 1) {
    currentSec = millis() / 1000;
    sec ++;
  }

  if (sec == 60) {
    sec = 0;
    //  lcd.clear();
    minut ++;
  }

  if (minut == 60) {
    minut = 0;
    hor ++;
  }

  if (hor > 99) {
    hor = 0;
  }
  //////////////////////// вывод времяни

  if (sec == 0) {
    lcd.setCursor(6, 1);
    lcd.print("00");
  }
  else {
    lcd.setCursor(6, 1);
    if (sec < 10) lcd.print("0");
    lcd.print(sec);
  }
  lcd.setCursor(2, 1);
  lcd.print(":");
  lcd.setCursor(5, 1);
  lcd.print(":");

  if (minut == 0) {
    lcd.setCursor(3, 1);
    lcd.print("00");
  }
  else {
    lcd.setCursor(3, 1);
    if (minut < 10) lcd.print("0");
    lcd.print(minut);
  }

  if (hor == 0) {
    lcd.setCursor(0, 1);
    lcd.print("00");
  }
  else {
    lcd.setCursor(0, 1);
    if (hor < 10) lcd.print("0");
    lcd.print(hor);
  }
}

 

RoN
Offline
Зарегистрирован: 28.12.2017

vosara

Проверил ваш код на схеме возникла проблема в том что код работает иначе.

А именно при вкл питания включается первый диод (13ый пин) т.е. время 00:00

Потом включается второй светодиод (12ый пин), первый отключается, время 00:01

После 3-х секунд работы кода оба диода выключены.

далее на 28ой секунде происходит включение второго светодиода (12ый пин), первый выключен.

на 48 секунде включается первый светодиод.

Мой вариант кода предпологал постоянное включенное состояние первого светодиода. Второй должен включиться и выключится в процессе работы первого.  А после истечения определенного времени выключается первый.

Возможно ли это из-за светодиода? Я использую 2 RGB

Попробую переписать ваш код

 Большое спасибо за помощь!

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

Проверил в симуляторе, единственное что время уменьшил, ссылку на видео оставляю

https://drive.google.com/open?id=1w0vgJdgvNQo-IsD12zdsyBHwn3xzFtXJ

Ну и код с меньшими цыфрами

#define led1 13 
#define led2 12
uint32_t time;
uint32_t pausa = 3000;
byte(f_vk) = 1;
//int led = 13;


void setup() {
  // put your setup code here, to run once:
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  digitalWrite(led1, HIGH);
  digitalWrite(led2, LOW);
  //Serial.begin(9600);
  time = millis();
}

void loop() {
  if(f_vk == 1 && millis()-time >= pausa){
    digitalWrite(led2, !digitalRead(led2));
    time = millis();
    if(digitalRead(led2))pausa = 5000;
    else pausa = 2000, f_vk = 2;
  }

  if(f_vk == 2 && millis() - time >= pausa){
    digitalWrite(led1, LOW);
    f_vk = 0;  
  } 
}

 

RoN
Offline
Зарегистрирован: 28.12.2017

Получилось таки

  //culler
    int ledPin1 =  12;      // the number of the LED pin
    int ledState1 = LOW;             // ledState used to set the LED
    unsigned long previousMillis1 = 0;        // will store last time LED was updated
    long OnTime1 = 3000;           // milliseconds of on-time
    long OffTime1 = 0;          // milliseconds of off-time // добавить 0 к 138000 и получим 23 мин, сейчас 2.3 мин
                                    // 600 000 это 10 мин
 //pribor   
    int ledPin2 =  13;      // the number of the LED pin
    int ledState2 = LOW;             // ledState used to set the LED
    unsigned long previousMillis2 = 0;        // will store last time LED was updated
    long OnTime2 = 0;           // milliseconds of on-time // добавить 0 к 18000 и получим 3 мин, сейчас 0.3 мин=18 сек
    long OffTime2 = 10000;          // milliseconds of off-time // добавить 0 и получим 20 мин, сейчас 2 мин

    int Value = 15000;            // добавить 0 и получим 10 мин,сейчас 1 мин
    /*
    int ledState3 = LOW;             // ledState used to set the LED
    unsigned long previousMillis2 = 0;        // will store last time LED was updated
    long OnTime2 = 2000;           // milliseconds of on-time
    long OffTime2 = 2000;          // milliseconds of off-time
     */
    void setup() 
    {
      // set the digital pin as output:
      pinMode(ledPin1, OUTPUT);      
      pinMode(ledPin2, OUTPUT);      
    }
     
    void loop()
    {
      
      unsigned long currentMillis = millis();
      if((ledState1 == HIGH) && (currentMillis - previousMillis1 >= OnTime1))
      {
        ledState1 = LOW;  // Turn it off
        previousMillis1 = currentMillis;  // Remember the time
        digitalWrite(ledPin1, ledState1);  // Update the actual LED
      }
      else if ((ledState1 == LOW) && (currentMillis - previousMillis1 >= OffTime1 + Value))
      {
        ledState1 = HIGH;  // turn it on
        previousMillis1 = currentMillis;   // Remember the time
        digitalWrite(ledPin1, ledState1);    // Update the actual LED 
      }
      
      if((ledState2 == HIGH) && (currentMillis - previousMillis2 >= OnTime2))
      {
        ledState2 = LOW;  // Turn it off
        previousMillis2 = currentMillis;  // Remember the time
        digitalWrite(ledPin2, ledState2);  // Update the actual LED
         
      }
      else if ((ledState2 == LOW) && (currentMillis - previousMillis2 >= OffTime2 + Value))
      {
    //    ledState2 = HIGH;  // turn it on
        previousMillis2 = currentMillis;   // Remember the time
        digitalWrite(ledPin2, HIGH);   // Update the actual LED
           
       }

     ledState1= LOW;
 //   digitalWrite(ledPin2, HIGH); 
    }

 

RoN
Offline
Зарегистрирован: 28.12.2017

vosara пишет:

Проверил в симуляторе, единственное что время уменьшил, ссылку на видео оставляю

https://drive.google.com/open?id=1w0vgJdgvNQo-IsD12zdsyBHwn3xzFtXJ

Хм в симуляторе и правда работает.!

Видимо дело в том что RGB светодиоды гаснут при подаче HIGH а включаются LOW, возможно поэтому у меня не работает.

Еще раз большое спасибо за помощь!