Кто подскажет решение?
есть схемка мигалки(автомодель), в ней повротники, мигают в зависимости от положения ручки(канального импульса), светодиоды на разных портах соответсвенно. работает. Есть вторая функция - включается отдельным каналом -"аварий" ка, при этом оба выхода (светодиоды) должны мигать синхронно. Но вот вторую функцию, кроме как на отдельный выход и включение через диоды не получилось реализовать.
Как правильно сделать одновременый вывод на оба светодиода.
Вот часть управления "поворотами"
//чтение канала руля, управление поворотами
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); //
}
Что мешает после стр.162 дописать digitalWrite(strL, led_stat); // мигаем левым и digitalWrite(strR, led_stat); // Мигаем правым? Оба сразу и замигают. Незабыть гасить оба после отключения аваоийки, и как бы все.
Что мешает после стр.162 дописать digitalWrite(strL, led_stat); // мигаем левым и digitalWrite(strR, led_stat); // Мигаем правым? Оба сразу и замигают. Незабыть гасить оба после отключения аваоийки, и как бы все.
Я так пробовал. Не получается. Когда нет обращения к выводам от первого канала(газа) , то есть еще паралельное обращение от 5-го..
я уже подумал вынести саму функцию мигания в отдельную подпрограмму и по мере необходимости обращаться к ней, но пока не придумал как это правильно сделать.
Есть такая проблемма. Собираю термостат на двух канальном реле. Нужно что бы при достижении определённой темпратуры включилось первое реле, а через 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 секунд.
Подскажите как решить проблемму.
Есть какая нибудь команда что бы таймер начанал отсчёт после включиния или отключения первого реле?
Хорошо бы уточнить, какое реле что делает. А именно, какое реле влияет на температуру и как быстро реагирует система. Если температурой управляет первое реле, а система реагирует быстрее 10 секунд, то первое реле будет щёлкать туда сюда, а до второго и очередь не дойдёт. Вам это подойдёт или нет? Ну а основные идеи Вам qwone показал.
А теперь вспомните, как вы засекаете время по часам. В момент начала интервала вы смотрите на часы и запоминаете время. А потом поглядываете на них, вычитая запомненное из текущего. Ничего не напоминает? - это же ваш код и есть.
А теперь главный вопрос - где в вашем коде вы запоминаете момент
dvstart=true;
чтобы отсчитывать от него 10 секунд? - нигде
Qwone прав - в программах на основе millis команду delay не используют. Даже когда вы исправите ошибку с отсчетом интервала - работать не будет.
Условие строки 38 будет срабатывать КАЖДЫЙ ПРОХОД цикла после 3х секунд, а условие строки41 - каждый проход после 5-ти секунд. Особенно интересно это будет выглядеть именно между пятой и десятой секундами - каждый оборот цикла (а это сотни и тысячи раз в секунду) - на выход star будет попеременно подаваться HIGH и LOW
Irinka, правильно. Я так делаю отложенные процессы, только в последующих условиях (здесь в строках 8, 16) ставлю не if а else if, чтобы избежать неоднозначности, если будет допущена ошибка/опечатка в метках времени (5000, 7000, 10000). А так то же самое.
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();
}
ПС: Если я чего то понимаю, то сначало вкл стартер и цилинды мотора набиваюся газообразным топливом, а потом идет искра (зажигание). А у вас почему-то иначе.
Вот мой скетч Полный здесь 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() нет. Но внутри класса он очень нужен. И без него эта конструкция не работала бы.
Получить +2кб в прошивку ради сомнительной выгоды получения количества секунд невовремя? Если ваша задача в этом, то применяйте.
Кто подскажет решение?
есть схемка мигалки(автомодель), в ней повротники, мигают в зависимости от положения ручки(канального импульса), светодиоды на разных портах соответсвенно. работает. Есть вторая функция - включается отдельным каналом -"аварий" ка, при этом оба выхода (светодиоды) должны мигать синхронно. Но вот вторую функцию, кроме как на отдельный выход и включение через диоды не получилось реализовать.
Как правильно сделать одновременый вывод на оба светодиода.
Вот часть управления "поворотами"
//чтение канала руля, управление поворотами 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 } }Что мешает после стр.162 дописать
digitalWrite(strL, led_stat);// мигаем левымиdigitalWrite(strR, led_stat);// Мигаем правым? Оба сразу и замигают. Незабыть гасить оба после отключения аваоийки, и как бы все.Что мешает после стр.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); }я уже подумал вынести саму функцию мигания в отдельную подпрограмму и по мере необходимости обращаться к ней, но пока не придумал как это правильно сделать.
olegtur77, Вам нужно разделить управление миганием и само мигание.
Функции упраления миганием должны просто выставлять нужные флаги.
А функция мигания должна следить за временем и включать либо не включать индикаторы в зависимости от состояния флагов.
Здравствуйеу.
Есть такая проблемма. Собираю термостат на двух канальном реле. Нужно что бы при достижении определённой темпратуры включилось первое реле, а через 10 секунд второе реле, ну и соответственно также отключались. Сделал скетч.
Надo timing запоминать только после включения 1 реле
Скорее всего так
/**/ 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 байт. */Хорошо бы уточнить, какое реле что делает. А именно, какое реле влияет на температуру и как быстро реагирует система. Если температурой управляет первое реле, а система реагирует быстрее 10 секунд, то первое реле будет щёлкать туда сюда, а до второго и очередь не дойдёт. Вам это подойдёт или нет? Ну а основные идеи Вам qwone показал.
Подойдёт. Температура быстро в катле не сможет изменятся, а вообще хотелосьбы добавить гистерезис.
Простите за мою тупость, я про 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("|"); }Ну вот ну почему, те, кто знают ардуину третий день, лезут сразу управлять котлом? А не потренируются сначала на межпланетных зондах?
Потому что сделал себе котёл, а на носу зима, тренероваться не когда).
Посмотрите на таке решение, может Вам будет легче его совместь, он оченьпохож на Ваш Подсказка обратите внимание на строчки в Вашем коде №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); } } }Спасибо обльшое, все работает, три дня мучался с этим скетчем. Подскажите можно ли в скетч как то добавить гистерезис ?
Ну в принципе верно, но с гистерезисом удобнее будет.
VOSARA скинь номер телефона на ящик Fedosov111@yandex.ru
Ну вот ну почему, те, кто знают ардуину третий день, лезут сразу управлять котлом? А не потренируются сначала на межпланетных зондах?
Так он, судя по всему, как раз собирается превратить котел в межпланетный зонд. Заодно со всей дачей.
Ну вот ну почему, те, кто знают ардуину третий день, лезут сразу управлять котлом? А не потренируются сначала на межпланетных зондах?
Так он, судя по всему, как раз собирается превратить котел в межпланетный зонд. Заодно со всей дачей.
Кто знает, кто знает)!
VOSARA огромное спасибо за помощь, и всем кто откликнулся.
Ну в принципе верно, но с гистерезисом удобнее будет.
а что такое гистерезис. по вашему? :)
Потому что сделал себе котёл, а на носу зима, тренероваться не когда).
Пора взрываться нахрен.
а что такое гистерезис. по вашему? :)
Неприличными словами не выражацца!
Hysteresis и hysteria - совпадение? Не думаю.
Никак до меня не дойдёт...подскажите...
Serial.read() получает "1" и запускаетstartDvig();dvstart становитсяtrue и выполняется условиеif(dvstart==true){мне нужно чтобы через 10 секунд 1 раз запустилась функцияvoidstopDvig()Где у меня косяк?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(); } } }10 секунд с какого момента?
Разумеется в delay(2000); А на деле у вас банально неправильный подход к методологии программирования.
dvstart=true;вот с этого моментаВ этот момент мне нужноpreviousMillis = currentMillis;и потом сравнивать с текущим millis?
dvstart=true;вот с этого моментану и замечательно.
А теперь вспомните, как вы засекаете время по часам. В момент начала интервала вы смотрите на часы и запоминаете время. А потом поглядываете на них, вычитая запомненное из текущего. Ничего не напоминает? - это же ваш код и есть.
А теперь главный вопрос - где в вашем коде вы запоминаете момент
dvstart=true;чтобы отсчитывать от него 10 секунд? - нигде
Qwone прав - в программах на основе millis команду delay не используют. Даже когда вы исправите ошибку с отсчетом интервала - работать не будет.
В этот момент мне нужноpreviousMillis = currentMillis;и потом сравнивать с текущим millis?
да.
Но delay(2000) и delay(3000) надо убрать.
dvstart=true;вот с этого моментаОстановить через 10 сек. можно легко. Но это будет как гланды через...
Например: строка #52: delay(10000); val = '0'; }
Конечно в это время МК будет просто пыхтеть.
Корректно*?
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(); } } }нет, не корректно.
Условие строки 38 будет срабатывать КАЖДЫЙ ПРОХОД цикла после 3х секунд, а условие строки41 - каждый проход после 5-ти секунд. Особенно интересно это будет выглядеть именно между пятой и десятой секундами - каждый оборот цикла (а это сотни и тысячи раз в секунду) - на выход star будет попеременно подаваться HIGH и LOW
Я уже поняла, прделываю.Спасибо.
Я уже поняла, прделываю.Спасибо.
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 байт. */#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(); } } Вот что получилосьНе нравится мне то что использую две переменных
03boolean vklZagig=false;04boolean vuklZagig=false;Не нравится мне то что использую две переменных
03boolean vklZagig=false;04boolean vuklZagig=false;что именно не нравится? (код выше пока не смотрел)
А кто вам доктор.Почему Вы не можете засунуть это
33if(vklZagig){34previousMillis = currentMillis;35vklZagig = !vklZagig;36digitalWrite(_zazhiganie, HIGH);37}вот сюда
15voidstartDvig()16{17Serial.println("Запуск двигателя");18vklZagig=true;19vuklZagig=true;20}Спасибо всем за ответы, очень приятно что есть люди, готовые оказать помощь и научить!)
#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 Как делать спойлер?
Я же говорю. Вы не программируете, а играете"угадала- не угадала".
45if(flagStarta==true){46if(currentMillis - previousMillis >5000){47digitalWrite(_starter, HIGH);48//Serial.println("Стартер запущен");49}if (flagStarta && currentMillis - previousMillis > 5000) { digitalWrite(_starter, HIGH); flagStarta = false;//<-- вы провтыкали эту строчку Serial.println("Стартер запущен"); }Вот так правильно?
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(); }Irinka, правильно. Я так делаю отложенные процессы, только в последующих условиях (здесь в строках 8, 16) ставлю не if а else if, чтобы избежать неоднозначности, если будет допущена ошибка/опечатка в метках времени (5000, 7000, 10000). А так то же самое.
btw, мне это позволяет избавиться от флагов.
Спасибо
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(); }Это получится что первая функция запустится через 5 секунд, вторая через 7 секунд после 5, т.е 7+5=12 Так?
Ну да. А третья через 7+5+10. Если не повесить блокирующий код в loop.
Суть то немного другая
Включается зажигание
Проходит 5 секунд
Включается стартер
Проходит 2 секунды
Выключается стартер
Вот. )
И что. Так и пишите. А то задача у вас одна, а пишите другое. Ну напишу вам код и что?! Вы все равно ничего не прочитаете.
ПС: Если я чего то понимаю, то сначало вкл стартер и цилинды мотора набиваюся газообразным топливом, а потом идет искра (зажигание). А у вас почему-то иначе.