Вопрос по использованию millis()

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот мой скетч Полный здесь https://yadi.sk/d/U_gtAoSN3AtYSM

Головной файл тут 

/* class_Led.ino 
  #1 светодиод ->13
  #2 кнопка 1 -> 2 вкл светодиод
  #3 кнопка 2 -> 3 выкл светодиод
  #4 кнопка 3 -> 4 светодиод мигает
  
*/
// #1 светодиод
#include "Cl_led.h"
const byte led1_pin = 13;
Cl_led Led1(led1_pin, 1); // создать
// #2 кнопка
#include "Cl_do_btn.h"
const byte btn1_pin = 2;
void Do_Btn1() {
  Led1.ON();
}
Cl_do_btn Btn1(btn1_pin, 0,    // пин кнопки, уровень при наж кнопки
               & Do_Btn1   );  // какую функцию надо сделать
// #3 кнопка
const byte btn2_pin = 3;
void Do_Btn2() {
  Led1.OFF();
}
Cl_do_btn Btn2(btn2_pin, 0,    // пин кнопки, уровень при наж кнопки
               & Do_Btn2   );  // какую функцию надо сделать
// #4 кнопка
const byte btn3_pin = 4;
void Do_Btn3() {
  Led1.blink();
}
Cl_do_btn Btn3(btn3_pin, 0,    // пин кнопки, уровень при наж кнопки
               & Do_Btn3   );  // какую функцию надо сделать
void setup() {
  Led1.setup();
  Led1.T_blink = 500;// мигать 0.5 горит -0.5 нет
  Btn1.setup();
  Btn2.setup();
  Btn3.setup();
}

void loop() {
  Led1.loop();
  Btn1.loop();
  Btn2.loop();
  Btn3.loop();
}

Вроде millis() нет. Но внутри класса он очень нужен. И без него эта конструкция не работала бы.

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

ivpo пишет:
Нет, я исключительно про своё применение - выполнять что-либо раз в полсекунды-секунду-две

Получить +2кб в прошивку ради сомнительной выгоды получения количества секунд невовремя? Если ваша задача в этом, то применяйте. 

olegtur77
Offline
Зарегистрирован: 09.04.2015

Кто подскажет решение?
есть схемка мигалки(автомодель), в ней повротники, мигают в зависимости от положения ручки(канального импульса), светодиоды на разных портах соответсвенно. работает. Есть вторая функция - включается отдельным каналом -"аварий" ка, при этом оба выхода (светодиоды) должны мигать синхронно. Но вот вторую функцию, кроме как на отдельный выход и включение через диоды не получилось реализовать.
Как правильно сделать одновременый вывод на оба светодиода.
 

Вот часть управления "поворотами"

//чтение канала руля, управление поворотами
  ppm_str = pulseIn (pinCh1, HIGH, 20000); //read RC channel 2
    if (ppm_str < str_min ) {
      ms = millis();
// период мигания стопов 500 мс   
   if( ( ms - ms1 ) > 500 || ms < ms1 ){
       ms1 = ms;
// Инвертируем светодиод       
       digitalWrite(strR, led_stat); // Мигаем правым
       led_stat = !led_stat;
       digitalWrite(strL, LOW);// гасим противоположный поворот
   }
    }
    else if (ppm_str > str_max ){
     ms = millis();
// период мигания стопов 500 мс   
   if( ( ms - ms1 ) > 500 || ms < ms1 ){
       ms1 = ms;
// Инвертируем светодиод       
       digitalWrite(strL, led_stat); // мигаем левым
       led_stat = !led_stat;
       digitalWrite(strR, LOW); // гасим противоположный поворот 
   }
    }
    else if (ppm_str>str_min&&ppm_str<str_max){
      digitalWrite(strL, LOW);   // выключаем повороты
      digitalWrite(strR, LOW);   // 
    }

а вот "аварийка"

/*************Аварийка и габарит ********************/
    
   ppm_aux1 = pulseIn (pinCh5, HIGH, 20000); //read RC channel 4 
    if (ppm_aux1<1300 ) {   ////режим аварийка и габарит
       analogWrite(gabarit,0); //все выключено
       analogWrite(gabaritF,0); //все выключено
       digitalWrite(avaria, LOW);// 
      
    }
    else if (ppm_aux1>1300&&ppm_aux1<1700){
       analogWrite(gabarit, 100); //габарит включен
       analogWrite(gabaritF, 255); //габарит включен
       digitalWrite(avaria, LOW);//
       }
       
    else if(ppm_aux1>1700 ){
      analogWrite(gabarit, 100); //габарит включен
      analogWrite(gabaritF,255); //габарит включен
      ms2 = millis();
       if( ( ms2 - ms3 ) > 500 || ms2 < ms3 ){
       ms3 = ms2;
       digitalWrite(avaria, led_stata); // Мигаем аварийкой
       led_stata = !led_stata;
       }
       }

весь код.

//atmega328,фюз внутр 16МГц, все остальное по дефолту, автоогни с калибровкой нейтрали, изменяемой яркостью фар и звуком "гудка"
// Ch1 - газ
// Ch2 - руль
// Ch3 - свет 0/бл/дал
// Ch4 - 0/габарит/габарит+аварийка
// Ch5 - сигнал
unsigned long ppm_trh,ppm_str,ppm_light,ppm_aux1,ppm_aux2;
  #define pinCh1 12 // вход "руль" 
  #define pinCh2 14 // вход "газ"
  #define pinCh3 15 // вход "свет-бл/дальний"
  #define pinCh4 16 // вход "сигнал"
  #define pinCh5 17 // вход "габарит-аварийка"

  #define avaria  2     //аварийка
  #define gabaritF  3    //габарит передний
  #define gabarit  9    //габарит задний
  #define revers  4     // задний ход
  #define lightstop  5  // стоп
  #define horn  6       // бибикалка
  #define strR  7       // правый поворот
  #define strL  8       // левый поворот
  #define lightG  10    // свет ШИМ
  
  int thrState;        // флаг установки газа
  int trh_min;   //нижняя граница нейтрали газа, 
  int trh_max;   //верхняя граница нейтрали газа
  int str_min;   //нижняя граница нейтрали руля
  int str_max;   //верхняя граница нейтрали руля
  int calibr=0; 
  
void setup()
{  
 
  pinMode (pinCh1, INPUT); //  Rx channel 1
  pinMode (pinCh2, INPUT); //  Rx channel 2
  pinMode (pinCh3, INPUT); //  Rx channel 3
  pinMode (pinCh4, INPUT); //  Rx channel 4
  pinMode (pinCh5, INPUT); //  Rx channel 5
  pinMode(lightstop, OUTPUT); // устанавливаем режим работы вывода, как "выход"
  pinMode(revers, OUTPUT);    // устанавливаем режим работы вывода, как "выход"
  pinMode(strR, OUTPUT);      // устанавливаем режим работы вывода, как "выход"
  pinMode(strL, OUTPUT);      // устанавливаем режим работы вывода, как "выход"
  pinMode(lightG, OUTPUT);    // устанавливаем режим работы вывода, как "выход"
  pinMode(horn, OUTPUT);      // устанавливаем режим работы вывода, как "выход"
  pinMode(avaria, OUTPUT);      // устанавливаем режим работы вывода, как "выход"
  pinMode(gabarit, OUTPUT);      // устанавливаем режим работы вывода, как "выход"
  pinMode(gabaritF, OUTPUT);      // устанавливаем режим работы вывода, как "выход"

  
    
}
    uint32_t ms, ms1 = 0;
    uint32_t ms2, ms3 = 0;
    bool led_stat    = true;
    bool led_stata    = true;
    
    
    
void loop()
{
  
  if(calibr==0){
// калибровка нейтрали при включении или сбросе, 3 сек,индикация светодиодом.кнопка на ресете
    while (millis () < 3000) {
      digitalWrite(gabarit,HIGH);
      ppm_str = pulseIn (pinCh1, HIGH, 20000); //read RC channel 2
        str_min=ppm_str-15;// нижняя граница нейтрали руля
        str_max=ppm_str+15;// верхняя граница нейтрали руля
        
      ppm_trh = pulseIn (pinCh2, HIGH, 20000); //read RC channel 1
        trh_min=ppm_trh-10;// нижняя граница нейтрали газа
        trh_max=ppm_trh+5;// верхняя граница нейтрали газа
    }
   digitalWrite(gabarit,LOW); // выкл свд, калибровка закончена
   calibr=1;
  }
   
 //чтение канала руля, управление поворотами
  ppm_str = pulseIn (pinCh1, HIGH, 20000); //read RC channel 2
    if (ppm_str < str_min ) {
      ms = millis();
// период мигания стопов 500 мс   
   if( ( ms - ms1 ) > 500 || ms < ms1 ){
       ms1 = ms;
// Инвертируем светодиод       
       digitalWrite(strR, led_stat); // Мигаем правым
       led_stat = !led_stat;
       digitalWrite(strL, LOW);// гасим противоположный поворот
   }
    }
    else if (ppm_str > str_max ){
     ms = millis();
// период мигания стопов 500 мс   
   if( ( ms - ms1 ) > 500 || ms < ms1 ){
       ms1 = ms;
// Инвертируем светодиод       
       digitalWrite(strL, led_stat); // мигаем левым
       led_stat = !led_stat;
       digitalWrite(strR, LOW); // гасим противоположный поворот 
   }
    }
    else if (ppm_str>str_min&&ppm_str<str_max){
      digitalWrite(strL, LOW);   // выключаем повороты
      digitalWrite(strR, LOW);   // 
    }

// чтение канала газа, управление стопом и з.х.
   ppm_trh = pulseIn (pinCh2, HIGH, 20000); //read RC channel 1
    
    if (ppm_trh > trh_max ) {
      thrState=1; //   флаг включения газа вперед
    }
    else if (ppm_trh>trh_min&&ppm_trh<trh_max){
      thrState=0; // нейтраль газа 
    }
    if (ppm_trh <trh_min&&thrState==1){
             digitalWrite(lightstop, HIGH);  // если ГАЗ с максимума резко назад, то включается СТОП
        }
    else if (ppm_trh <trh_min&&thrState==0){
          digitalWrite(revers, HIGH);  // если ГАЗ с нейтрали назад, включается ЗАДНИЙ ХОД
            }
      
        else {
      digitalWrite(revers, LOW);  // выключаем светодиоды заднего хода и стопов
      digitalWrite(lightstop, LOW);
        }

// управление фарами(яркостью), пропорционально 4 положения:выключено,габарит,ближний,дальний
  ppm_light = pulseIn (pinCh3, HIGH, 20000); //read RC channel 3
    if (ppm_light<1300) {
    analogWrite(lightG, 0);   // выключаем фары
     }
    else if (ppm_light>1300&&ppm_light<1600) {
    analogWrite(lightG, 100);   // включаем яркость "ближний"
    }
    else if (ppm_light>1600) {
    analogWrite(lightG, 255);   // включаем яркость "дальний"
    }
 
 /*************Аварийка и габарит ********************/
    
   ppm_aux1 = pulseIn (pinCh5, HIGH, 20000); //read RC channel 4 
    if (ppm_aux1<1300 ) {   ////режим аварийка и габарит
       analogWrite(gabarit,0); //все выключено
       analogWrite(gabaritF,0); //все выключено
       digitalWrite(avaria, LOW);// 
      
    }
    else if (ppm_aux1>1300&&ppm_aux1<1700){
       analogWrite(gabarit, 100); //габарит включен
       analogWrite(gabaritF, 255); //габарит включен
       digitalWrite(avaria, LOW);//
       }
       
    else if(ppm_aux1>1700 ){
      analogWrite(gabarit, 100); //габарит включен
      analogWrite(gabaritF,255); //габарит включен
      ms2 = millis();
       if( ( ms2 - ms3 ) > 500 || ms2 < ms3 ){
       ms3 = ms2;
       digitalWrite(avaria, led_stata); // Мигаем аварийкой
       led_stata = !led_stata;
       }
       }
///////// включение сигнала, простой ШИМ,дискретный или проп. канал/////////

  
    ppm_aux2 = pulseIn (pinCh4, HIGH, 20000); //read RC channel 5
    if (ppm_aux2>1700) {
    //analogWrite(horn,180);// сигнал ШИМом, для аттини861, 
    digitalWrite(horn, HIGH);   // включаем "сигнал" , если просто нужен лог.выход
    //tone(horn, 320); // выдаём на "сигнале" сигнал с частотой 320 Гц "гудок", работает на атмега328
  }
    else  {
     //analogWrite(horn,0);
     digitalWrite(horn, LOW);   // выключаем сигнал//
      //noTone(horn); // выключено, работает на атмега328
      }
}


  

 

Logik
Offline
Зарегистрирован: 05.08.2014

Что мешает после стр.162 дописать digitalWrite(strL, led_stat); // мигаем левым и digitalWrite(strR, led_stat); // Мигаем правым? Оба сразу и замигают. Незабыть гасить оба после отключения аваоийки, и как бы все.

olegtur77
Offline
Зарегистрирован: 09.04.2015

Logik пишет:

Что мешает после стр.162 дописать digitalWrite(strL, led_stat); // мигаем левым и digitalWrite(strR, led_stat); // Мигаем правым? Оба сразу и замигают. Незабыть гасить оба после отключения аваоийки, и как бы все.

Я так пробовал. Не получается. Когда нет обращения к выводам от первого канала(газа) , то есть еще паралельное обращение от 5-го..

и вот тут идет постоянное гашение светодиодов

 ppm_aux1 = pulseIn (pinCh5, HIGH, 20000); //read RC channel 4 
    if (ppm_aux1<1300 ) {   ////режим аварийка и габарит
       analogWrite(gabarit,0); //все выключено
       analogWrite(gabaritF,0); //все выключено
       digitalWrite(strL, LOW);// 
       digitalWrite(strR, LOW);
    }
    else if (ppm_aux1>1300&&ppm_aux1<1700){
       analogWrite(gabarit, 100); //габарит включен
       analogWrite(gabaritF, 255); //габарит включен
       digitalWrite(strL, LOW);//
       digitalWrite(strR, LOW);
       }

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

olegtur77, Вам нужно разделить управление миганием и само мигание.

Функции упраления миганием должны просто выставлять нужные флаги.

А функция мигания должна следить за временем и включать либо не включать индикаторы в зависимости от состояния флагов.

Goodawel
Offline
Зарегистрирован: 05.11.2017

Здравствуйеу. 

Есть такая проблемма. Собираю термостат на двух канальном реле. Нужно что бы при достижении определённой темпратуры включилось первое реле, а через 10 секунд второе реле, ну и соответственно также отключались. Сделал скетч.

float temperature = getTemp(); // читаем температуру
 
 {
  if (temperature < tempOUT1) digitalWrite(OUT1, HIGH); 
  else digitalWrite(OUT1, LOW);                                       
  if (millis() - timing > 10000){
  if (temperature < tempOUT1) digitalWrite(OUT2, HIGH);
  else digitalWrite(OUT2, LOW);
  timing = millis();
  
  Serial.println(timing);
 
  }
 }
 
Но ничего не получилось. Промежуток времени между реле хаотично разный так как второе реле работает по своему таймеру а превое по достижения температуры. Таймер начал отсчёт, через к примеру 4 секунды включается первое реле по достижению температуры а через 6 секунд включается второе реле. В итоге получается разница по времени между реле может от1 до 10 секунд. 
Подскажите как решить проблемму.
Есть какая нибудь команда что бы таймер начанал отсчёт после включиния или отключения первого реле?
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Надo timing запоминать только после включения 1 реле

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Скорее всего так

/**/
const byte re1_1Pin =/*пин*/2;
const byte re1_2Pin =/*пин*/3;
const float tempOUT1 =/*температура переключения*/40;
const bool _ON = HIGH;
const bool _OFF = LOW;
bool statON = 0, statOFF = 0;
bool pastON, pastOFF;
unsigned long time_10s = 10000;
/*чтение температуры*/
float getTemp() {
  return 0;
  };
//-----main------------------
void setup() {
  pinMode(re1_1Pin, OUTPUT);
  digitalWrite(re1_1Pin, _OFF);
  pinMode(re1_2Pin, OUTPUT);
  digitalWrite(re1_2Pin, _OFF);
}

void loop() {
  unsigned long mill = millis();
  float temperature = getTemp(); // читаем температуру
  if (temperature < tempOUT1) {
    digitalWrite(re1_1Pin, _ON);
    pastON = mill;
    statON = 1;
  }
  else {
    digitalWrite(re1_1Pin, _OFF);
    pastOFF = mill;
    statOFF = 1;
  }
  if (statON && mill - pastON > time_10s) {
    statON = 0;
    digitalWrite(re1_2Pin, _ON);
  }
  if (statOFF && mill - pastOFF > time_10s) {
    statOFF = 0;
    digitalWrite(re1_2Pin, _OFF);
  }
}
/*Скетч использует 896 байт (2%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 12 байт (0%) динамической памяти, оставляя 2036 байт для локальных переменных. Максимум: 2048 байт.
*/

 

kalapanga
Offline
Зарегистрирован: 23.10.2016

Хорошо бы уточнить, какое реле что делает. А именно, какое реле влияет на температуру и как быстро реагирует система. Если температурой управляет первое реле, а система реагирует быстрее 10 секунд, то первое реле будет щёлкать туда сюда, а до второго и очередь не дойдёт. Вам это подойдёт или нет? Ну а основные идеи Вам qwone показал.

Goodawel
Offline
Зарегистрирован: 05.11.2017

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

Goodawel
Offline
Зарегистрирован: 05.11.2017

Простите за мою тупость, я про arduino знаю третий день и ума пока не хватило как подставить правильно вашу константу в свою. Помогите если не сложно.

 

#include <EEPROM.h>
#include <OneWire.h>
#include <LiquidCrystal.h>

#define OUT1 2 // выходы для реле 
#define OUT2 3

byte tempOUT1, tempOUT2;

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
OneWire  ds(11); // 11 вход датчика 18b20

byte gradus[8] = {
  0b00110,
  0b01001,
  0b01001,
  0b00110,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};


void erorr(){ // останавливает работу программы и сигнализирует ошибку
  digitalWrite(OUT1, LOW); // выключаем реле
  digitalWrite(OUT2, LOW);
    while(1){ // крутим бесконечный цикл
      digitalWrite(13, !digitalRead(13));
      delay(500);
    }  
}
////

byte key(){ //// для кнопок ЛСДшилда
  int val = analogRead(0);
    if (val < 50) return 5;
    else if (val < 150) return 3;
    else if (val < 350) return 4;
    else if (val < 500) return 2;
    else if (val < 800) return 1;
    else return 0;  
}
////

void setMenu(){ // установка температуры 
  byte pos;    
  digitalWrite(OUT1, LOW); // выключаем реле
  digitalWrite(OUT2, LOW);

  lcd.clear(); 
  lcd.setCursor(0, 0); // что нужно отрисовать один раз
  lcd.print("OUT1: ");
  lcd.setCursor(0, 1);
  lcd.print("OUT2: ");
  lcd.blink();
  
  while(1){ // крутим бесконечный цикл      
    byte KEY = key(); // читаем состояние кнопок
    
    lcd.setCursor(6, 0); // выводим на экран
    lcd.print(tempOUT1);
    lcd.write(1);
    lcd.print("C  ");
    lcd.setCursor(6, 1);
    lcd.print(tempOUT2);    
    lcd.write(1);
    lcd.print("C  ");
    
     ////// обработка кнопок 
    if (pos == 0){  // если в первой позиции
      lcd.setCursor(5, 0); // устанавливаем курсор
      if (KEY == 2) { // если нажата кнопка
        tempOUT1--;   // изменяем значение
        EEPROM.write(1, tempOUT1); // сохраняем в еепром
      }
      else if (KEY == 5){
        tempOUT1++;
        EEPROM.write(1, tempOUT1);     
      }    
    }
    if (pos == 1){ 
      lcd.setCursor(5, 1);
      if (KEY == 2) {
        tempOUT2--;
        EEPROM.write(2, tempOUT2);
      }
      else if (KEY == 5){
        tempOUT2++;
        EEPROM.write(2, tempOUT2);     
      }    
    }
    
    if (KEY == 3) pos--; // крутим позицию
    else if (KEY == 4) pos++;    
    if (pos > 1) pos = 0; 
 
   delay(200);
  }
}

float getTemp(){   // возвращает температуру с датчика
  byte data[12];   // и останавливает программу на секунду
  byte addr[8];  
  
  if (!ds.search(addr)) {
    lcd.clear();
    lcd.print("No sensor."); 
    erorr(); 
  }
  
  ds.reset_search(); 
 
  if (OneWire::crc8(addr, 7) != addr[7]) {
    lcd.clear();
    lcd.print("Sensor CRC erorr");
    erorr();   
  }
  
  ds.reset();            
  ds.select(addr);        
  ds.write(0x44);      
  delay(1000);   
  
  ds.reset();
  ds.select(addr);    
  ds.write(0xBE);          

  for (int i = 0; i < 9; i++) data[i] = ds.read(); 
  int raw = (data[1] << 8) | data[0]; // Переводим в температуру   
  if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];  
  
  return raw / 16.0;
}

void setup() {
//  Serial.begin(9600); 
  lcd.createChar(1, gradus);
  lcd.begin(16, 2);
  lcd.clear();
  
  pinMode(13, OUTPUT); 
  pinMode(OUT1, OUTPUT);
  pinMode(OUT2, OUTPUT);
  
  tempOUT1 = EEPROM.read(1); // читаем настройки 
  tempOUT2 = EEPROM.read(2); // из еепром
}

void loop() {  
  if (key() == 1) setMenu(); // если нажата селект, уходим в меню
  else if (key() == 4) analogWrite(10, 20); // если вниз, глушим подсветку
  else if (key() == 3) digitalWrite(10, HIGH);
  
  float temperature = getTemp(); // читаем температуру
 
  if (temperature < tempOUT1) digitalWrite(OUT1, HIGH); // сверяем температуру 
  else digitalWrite(OUT1, LOW);                         // и управляем выходами
  if (temperature < tempOUT2) digitalWrite(OUT2, HIGH);
  else digitalWrite(OUT2, LOW);
      
  lcd.setCursor(0, 0); /// вывод инфы на экран
  lcd.print("1:");
  lcd.print(tempOUT1);
  lcd.write(1);
//  lcd.print("C");
    if (digitalRead(OUT1)) lcd.print(" ON "); // показываем состояние выхода
    else lcd.print(" OFF");
  lcd.setCursor(0, 1);
  lcd.print("2:");
  lcd.print(tempOUT2);
  lcd.write(1);
    if (digitalRead(OUT2)) lcd.print(" ON ");
    else lcd.print(" OFF");    
    
  lcd.setCursor(9, 0); // показываем температуру с датчика
  lcd.print("|"); 
  lcd.print(temperature, 1);
  lcd.write(1);
  lcd.print("C");
  lcd.setCursor(9, 1);     
  lcd.print("|");  
}

 

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

Ну вот ну почему, те, кто знают ардуину третий день, лезут сразу управлять котлом?  А не потренируются сначала на межпланетных зондах? 

Goodawel
Offline
Зарегистрирован: 05.11.2017

Потому что сделал себе котёл, а на носу зима, тренероваться не когда).

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

Посмотрите на таке решение, может Вам будет легче его совместь, он оченьпохож на Ваш Подсказка обратите внимание на строчки в Вашем коде №157-160

uint32_t timing;

void setup(){}

void loop(){
  float temperature = getTemp(); // читаем температуру

  if(temperature < tempOUT1){
    if (!digitalRead(OUT1)){
      digitalWrite(OUT1, HIGH);
      timing = millis();
    }  
    if (!digitalRead(OUT2) && millis() - timing > 10000){
      digitalWrite(OUT2, HIGH);
    }
  }

  if(temperature > tempOUT1 ){
    if (digitalRead(OUT1)){
      digitalWrite(OUT1, LOW);
      timing = millis();
    }  
    if (digitalRead(OUT2) && millis() - timing > 10000){
      digitalWrite(OUT2, LOW);
    }
  }
}

 

Goodawel
Offline
Зарегистрирован: 05.11.2017

Спасибо обльшое, все работает, три дня мучался с этим скетчем. Подскажите можно ли в скетч как то добавить гистерезис ?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
А что Вам мешает на включение поставить температуру (например)60 градусов а на выключение (например) 70 градусов
tempOUT1=60
tempOUT2=70
и сменить в коде tempOUT1 на tempOUT2 при выключении
Goodawel
Offline
Зарегистрирован: 05.11.2017

Ну в принципе верно, но с гистерезисом удобнее будет. 

VOSARA скинь номер телефона на ящик Fedosov111@yandex.ru

 

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

DetSimen пишет:

Ну вот ну почему, те, кто знают ардуину третий день, лезут сразу управлять котлом?  А не потренируются сначала на межпланетных зондах? 

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

Goodawel
Offline
Зарегистрирован: 05.11.2017

sadman41 пишет:

DetSimen пишет:

Ну вот ну почему, те, кто знают ардуину третий день, лезут сразу управлять котлом?  А не потренируются сначала на межпланетных зондах? 

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

Кто знает, кто знает)!

VOSARA огромное спасибо за помощь, и всем кто откликнулся.

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

Goodawel пишет:

Ну в принципе верно, но с гистерезисом удобнее будет. 

а что такое гистерезис. по вашему? :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Goodawel пишет:

Потому что сделал себе котёл, а на носу зима, тренероваться не когда).

Пора взрываться нахрен.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

b707 пишет:

а что такое гистерезис. по вашему? :)

Неприличными словами не выражацца!

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

Ворота пишет:
Неприличными словами не выражацца!

Hysteresis и hysteria - совпадение? Не думаю.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Никак до меня не дойдёт...подскажите...

Serial.read() получает "1" и запускает startDvig();

dvstart становится true и выполняется условие if(dvstart==true){

мне нужно чтобы через 10 секунд 1 раз запустилась функция void stopDvig()

Где у меня косяк?

 

int val;
boolean dvstart=false;
int zazhiganie = 3; 
int star = 4;
long previousMillis = 0;
long interval = 10000;



void setup()
{
  Serial.begin(9600);
   pinMode(zazhiganie, OUTPUT); 
  pinMode(star, OUTPUT); 
}
void startDvig()
{
digitalWrite(zazhiganie, HIGH); 
delay(3000);
digitalWrite(star, HIGH); 
delay(2000);
digitalWrite(star, LOW); 
dvstart=true;
}

void stopDvig()
{
digitalWrite(zazhiganie, LOW); 
digitalWrite(star, LOW); 
}


void loop(){
unsigned long currentMillis = millis();
if(dvstart==true){
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis; 
dvstart=false; 
stopDvig();
} 
}



  
  if (Serial.available())
  {
    val = Serial.read();
    if (val == '1')
    {
startDvig();
    }

    if ( val == '0')
    {
     stopDvig();
    }
  }
}



 

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

10 секунд с какого момента?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Разумеется в delay(2000); А на деле у вас банально неправильный подход к методологии программирования.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

dvstart=true;

вот с этого момента

В этот момент мне нужно previousMillis = currentMillis;

и потом сравнивать с текущим millis?

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

Irinka пишет:

dvstart=true;

вот с этого момента

ну и замечательно.

А теперь вспомните, как вы засекаете время по часам. В момент начала интервала вы смотрите на часы и запоминаете время. А потом поглядываете на них, вычитая запомненное из текущего. Ничего не напоминает? - это же ваш код и есть.

А теперь главный вопрос - где в вашем коде вы запоминаете момент

dvstart=true;

чтобы отсчитывать от него 10 секунд? - нигде

 

Qwone прав - в программах на основе millis команду delay не используют. Даже когда вы исправите ошибку с отсчетом интервала - работать не будет.

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

Irinka пишет:

В этот момент мне нужно previousMillis = currentMillis;

и потом сравнивать с текущим millis?

да.

Но delay(2000) и delay(3000) надо убрать.

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

Irinka пишет:

dvstart=true;

вот с этого момента

Остановить через 10 сек. можно легко. Но это будет как гланды через...

Например: строка #52: delay(10000); val = '0'; }

Конечно в это время МК будет просто пыхтеть.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Корректно*?

int val;
boolean dvstart=false;
int zazhiganie = 3; 
int star = 4;
long previousMillis = 0;
long interval = 10000;



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


void stopDvig()
{
digitalWrite(zazhiganie,LOW ); 
digitalWrite(star, LOW); 
}
void startDvig()
{
dvstart=true;
}

void loop(){
unsigned long currentMillis = millis();
if(dvstart==true){
previousMillis = currentMillis; 
dvstart = !dvstart;  
digitalWrite(zazhiganie, HIGH); 
}
if(dvstart==false){  
if(currentMillis - previousMillis >3000) {
digitalWrite(star, HIGH); 
} 
if(currentMillis - previousMillis >5000) {
digitalWrite(star, LOW); 
} 
if(currentMillis - previousMillis >10000) {
stopDvig();
} 
}



  
  if (Serial.available())
  {
    val = Serial.read();
    if (val == '1')
    {
startDvig();
    }

    if ( val == '0')
    {
     stopDvig();
    }
  }
}





 

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

нет, не корректно.

Условие строки 38 будет срабатывать КАЖДЫЙ ПРОХОД цикла после 3х секунд, а условие строки41 - каждый проход после 5-ти секунд. Особенно интересно это будет выглядеть именно между пятой и десятой секундами - каждый оборот цикла (а это сотни и тысячи раз в секунду) - на выход star будет попеременно подаваться HIGH и LOW

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Я уже поняла, прделываю.Спасибо.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Я уже поняла, прделываю.Спасибо.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Irinka

Методология программирования у вас не развита. Вот и гадаете на пустом месте.

/**/
int led1Pin =/*пин*/ 3;
int led2Pin =/*пин*/ 4;
//-----будильник---------------
boolean flag = false;
unsigned long past = 0;
unsigned long interval = 10000;
void Start() {
  flag = true;
  past = millis();
  digitalWrite(led2Pin, HIGH);
}
void Stop() {
  digitalWrite(led1Pin, LOW );
  digitalWrite(led2Pin, LOW);
  flag = false;
}
//---main()---------------
void setup() {
  Serial.begin(9600);
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  Stop();
}
void loop() {
  //управление
  if (Serial.available()) {
    int val = Serial.read();
    if (val == '1') Start();
    if (val == '0') Stop();
  }
  //  устройство
  unsigned long mill = millis();
  if (flag && mill - past >= interval) {
    flag = false;
    digitalWrite(led1Pin, HIGH);
  }
}
/*Скетч использует 1886 байт (5%) памяти устройства. Всего доступно 32256 байт.
  Глобальные переменные используют 187 байт (9%) динамической памяти, оставляя 1861 байт для локальных переменных. Максимум: 2048 байт.
*/

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017
#define _zazhiganie 3
#define _starter 4
boolean vklZagig=false;
boolean vuklZagig=false;
long previousMillis = 0;


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

void startDvig()
{
Serial.println("Запуск двигателя"); 
vklZagig=true;
vuklZagig=true;
}
void stopDvig()
{
digitalWrite(_zazhiganie,LOW ); 
Serial.println("Остановка двигателя"); 
vklZagig=false;
vuklZagig=false;
}


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

if(vklZagig){
previousMillis = currentMillis; 
vklZagig = !vklZagig;  
digitalWrite(_zazhiganie, HIGH); 
}

if(vuklZagig){  
if(currentMillis - previousMillis >3000) {
digitalWrite(_starter, HIGH); 
} 
if(currentMillis - previousMillis >5000) {
digitalWrite(_starter, LOW); 
} 
if(currentMillis - previousMillis >10000) {
vuklZagig=!vuklZagig;
stopDvig();
} 
}


//Управление
if (Serial.available()) {
int val = Serial.read();
if (val == '1') startDvig();
if (val == '0') stopDvig();
} 
 
}




Вот что получилось

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Не нравится мне то что использую две переменных 

03 boolean vklZagig=false;
04 boolean vuklZagig=false;

 

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

Irinka пишет:

Не нравится мне то что использую две переменных 

03 boolean vklZagig=false;
04 boolean vuklZagig=false;

 

что именно не нравится? (код выше пока не смотрел)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

А кто вам доктор.Почему Вы не можете засунуть это 

33 if(vklZagig){
34 previousMillis = currentMillis;
35 vklZagig = !vklZagig; 
36 digitalWrite(_zazhiganie, HIGH);
37

вот сюда

15 void startDvig()
16 {
17 Serial.println("Запуск двигателя");
18 vklZagig=true;
19 vuklZagig=true;
20 }

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Спасибо всем за ответы, очень приятно что есть люди, готовые оказать помощь и научить!)

#define _zazhiganie 3//Пин зажигания
#define _starter 4//Пин стартера
#define _dopkanal 5//Пин дополнительного канала

boolean flagStarta=false;
unsigned long previousMillis = 0;
unsigned long progrev = 1;//Время прогрева в минутах
unsigned long currentMillis;


//Установки
void setup()
{
Serial.begin(9600);
pinMode(_zazhiganie, OUTPUT); 
pinMode( _starter, OUTPUT); 
pinMode( _dopkanal, OUTPUT); 
stopDvig();
}


//Старт двигателя
void startDvig()
{
previousMillis = currentMillis; 
flagStarta=true;
digitalWrite(_zazhiganie, HIGH); 
Serial.println("Зажигание включено"); 
}

//Остановка двигателя
void stopDvig()
{
Serial.println("Зажигание выключено"); 
digitalWrite(_zazhiganie,LOW ); 
digitalWrite(_starter,LOW ); 
digitalWrite(_dopkanal,LOW ); 
flagStarta=false;
}


void loop(){
currentMillis = millis();

if(flagStarta==true){  
if(currentMillis - previousMillis >5000){
digitalWrite(_starter, HIGH); 
//Serial.println("Стартер запущен");
} 

if(currentMillis - previousMillis >7000){
digitalWrite(_starter, LOW);
//Serial.println("Стартер остановлен"); 
} 

if(currentMillis - previousMillis >progrev*60*1000){
stopDvig();
} 
}


//Управление
if (Serial.available()) {
int val = Serial.read();
if (val == '1') startDvig();
if (val == '0') stopDvig();
} 
}

Почему, если раскомментировать строки

//Serial.println("Стартер запущен");
//Serial.println("Стартер остановлен"); 

начинается бред такого плана:

Зажигание выключено
Зажигание включено
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен
Стартер остановлен
Стартер запущен

PS Как делать спойлер?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Я же говорю. Вы не программируете, а играете"угадала- не угадала".

45 if(flagStarta==true){ 
46 if(currentMillis - previousMillis >5000){
47 digitalWrite(_starter, HIGH);
48 //Serial.println("Стартер запущен");
49 }
if (flagStarta && currentMillis - previousMillis > 5000) {
  digitalWrite(_starter, HIGH);
  flagStarta = false;//<-- вы провтыкали эту строчку
  Serial.println("Стартер запущен");
}

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Вот так правильно?

if (flagStarta && currentMillis - previousMillis > 5000) {
  digitalWrite(_starter, HIGH);
  flagStarta = false;
   flagStarta1 = true;
  Serial.println("Стартер запущен");
}

if (flagStarta1 && currentMillis - previousMillis > 7000) {
  digitalWrite(_starter, LOW);
  flagStarta1 = false;
  flagStarta2 = true;
  Serial.println("Стартер остановлен");
}


if (flagStarta2 && currentMillis - previousMillis > 10000) {
  digitalWrite(_starter, LOW);
  flagStarta2 = false;
stopDvig();
}

 

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

Irinka, правильно. Я так делаю отложенные процессы, только в последующих условиях (здесь в строках 8, 16) ставлю не if а else if, чтобы избежать неоднозначности, если будет допущена ошибка/опечатка в метках времени (5000, 7000, 10000). А так то же самое.

btw, мне это позволяет избавиться от флагов.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Спасибо

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Irinka.А вот вы опять налажали. Похоже вам надо нучиться писать комментарии в программах. Иначе этот ваш пробел не даст вам развиться.И это серьезно,без шуток.

/*первая отложеная функция*/
if (flagStarta && currentMillis - previousMillis >= 5000) {// <- лучше >= чем >
  flagStarta = false; // это сброс флага для препятсвия нового вызова
  /*вызов другой отлаженной функции*/
  previousMillis = currentMillis;
  flagStarta1 = true;
  /*исполнительные команды*/
  digitalWrite(_starter, HIGH); // исполнительные команды лучше ставить в конце
  Serial.println("Стартер запущен");
}
/*вторая  отложеная функция по очереди*/
if (flagStarta1 && currentMillis - previousMillis >= 7000) {
  flagStarta1 = false; // это сброс флага для препятсвия нового вызова
  /*вызов третьей отлаженной функции*/
  previousMillis = currentMillis;
  flagStarta2 = true;
  /*исполнительные команды*/
  digitalWrite(_starter, LOW);
  Serial.println("Стартер остановлен");
}
/*третья  отложеная функция по очереди*/
if (flagStarta2 && currentMillis - previousMillis >= 10000) {
  flagStarta2 = false; // это сброс флага для препятсвия нового вызова
  /*больше отложенных функций вызывать не надо*/
  /*исполнительные команды*/
  digitalWrite(_starter, LOW);
  stopDvig();
}

 

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Это получится что первая функция запустится через 5 секунд, вторая через 7 секунд после 5, т.е 7+5=12 Так?

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну да. А третья через 7+5+10. Если не повесить блокирующий код в loop.

Irinka
Irinka аватар
Offline
Зарегистрирован: 28.06.2017

Суть то немного другая

Включается зажигание

Проходит 5 секунд

Включается стартер

Проходит 2 секунды

Выключается стартер

Вот. )

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

И что. Так и пишите.  А то задача у вас одна, а пишите другое. Ну напишу вам код и что?! Вы все равно ничего не прочитаете.

/*Включается зажигание*/
// включает флаг1

/*первая отложеная функция*/
//Проходит 5 секунд
// выключает флаг1
// включает флаг2
/*Включается стартер*/

/*вторая отложеная функция*/
//Проходит 2 секунды
// выключает флаг2
/*Выключается стартер*/

ПС: Если я чего то понимаю, то сначало вкл стартер и цилинды мотора набиваюся газообразным топливом, а потом идет искра (зажигание). А у вас почему-то иначе.