таймер с 2-мя условиями
- Войдите на сайт для отправки комментариев
Сб, 26/09/2015 - 22:48
Здраствуйте,я переделываю скеч , и на столе пока всё работает.Хочу добавить 2-е условие в таймер(от 458 строки) turnPeriodMin ,чтоб при выходе outMax и outMin (502-508 строки) отсчитывал разное время.Изначально было одно условие(от 531-закоментировал).Я переписал команды,и всё заработало .Но ........только без histeresis. Если задаю histeresis ,в том интервале (+- от Setpoint) таймер застревает.И уже незнаю где копать.Поделитесь советами пожалуйста.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM2.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <Bounce.h>
int del = 50; // переменная ожидания между выборами меню
unsigned int interval = 100; // интервал сколько будет длиться цикл while, после чего перейдёт к следующему меню.(кол-во итераций)
unsigned long currentMillis = millis ();
#define heater_pin 11 // нагреватель10
#define alarm_pin 13 // пин аварии
#define beeper_pin 14 //пищалка по аварии
#define ledPin 9 // управление поворотом
#define button_minus_pin 5 //пин кнопки "минус"
#define button_plus_pin 6 //пин кнопки "плюс"
#define button_enter_pin 7 //пин кнопки "enter"
#define DS18B20_Pin A1 //пин термометра
#define BUTTON 8 //limit switch
Bounce bouncer = Bounce(BUTTON, 8); // limit switch
boolean button_minus;
boolean button_plus;
boolean button_enter;
float temp1Ink; // Температура DS18B20
unsigned long trhMillis = 0; // период опроса датчиков
byte measActive = false;
const unsigned long TRHSTEP = 3000UL; // Sensor query period
long previousMillis = 0;
LiquidCrystal_I2C lcd(0x27, 16, 2); // инициализация библиотеки дисплея
OneWire oneWire(DS18B20_Pin);
DallasTemperature sensors(&oneWire);
//Setup PID
double outMin , outMax ;
double Setpoint, Input; //Output; //I/O for PID
/* EEPROM1 - tempInk (float)
EEPROM5 - +-alarmTemp (float)
EEPROM9 - fanTemp (int)
EEPROM11 - turnPeriod (int)
EEPROM20 - turnPeriodMin (int)
EEPROM12 - hysteresis (float)
EEPROM -9 FanMax (int)
EEPROM -8 FanMin (int)
*/
void setup() {
Serial.begin(9600);
lcd.init(); // Старт дисплея
lcd.backlight(); // Включаем подсветку дисплея
byte stat;
byte error = 0;
pinMode(BUTTON, INPUT_PULLUP);// limit switch
pinMode(heater_pin, OUTPUT);
digitalWrite(heater_pin, LOW);
pinMode(alarm_pin, OUTPUT);
digitalWrite(alarm_pin, LOW);
pinMode(button_minus_pin, INPUT_PULLUP); //подтягиваем входы кнопок к плюсу встроенными резисторами
pinMode(button_plus_pin, INPUT_PULLUP);
pinMode(button_enter_pin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
sensors.begin();
sensors.setResolution(12); // установить разрешение (точность)
sensors.setWaitForConversion(false); // отключить ожидание
}
void loop() {
TCCR2B = TCCR2B & 0b11111000 | 0x01; // 32 kHz PWM
button_read();
if (!button_enter) {
delay(del);
lcd.clear();
menu();
}
if (!button_minus) {
delay(del);
lcd.clear();
//действие по нажатии кнопки "-"
}
if (!button_plus) {
delay(del);
lcd.clear();
//действие по нажатии кнопки "+"
}
getSensors();
thermostat();
// turn();
alarm();
}
void button_read() {//функция проверки нажатия кнопки
button_minus = digitalRead(button_minus_pin); //запоминаем значение кнопки
button_plus = digitalRead(button_plus_pin); //запоминаем значение кнопки
button_enter = digitalRead(button_enter_pin); //запоминаем значение кнопки
if (!button_minus || !button_plus || !button_enter) beeper(50);
}
//меню////////////////////////////////////////////////////////////
void menu() {
temp_setup();
hysteresis_setup();
turn_setup();
turnMin_setup();
alarm_setup();
ventMax_setup();
ventMin_setup();
}
//устанавливаем температуру в меню////////////////////////////////////
void temp_setup() {
float tempInk;
lcd.clear();
delay(del);
button_read();
lcd.setCursor(0, 0);
lcd.print("TEMPERATURE ");
delay(1000);
int x = 0;
while (1) {
x++;
if (x > interval) {
break;
}
button_read();
EEPROM_read(1, tempInk);
if (!button_enter) {
delay(del);
lcd.clear(); //очищаем экран
break;
}
if (!button_minus) {
EEPROM_write(1, tempInk + 0.5);
if (tempInk > 40) { //проверяем, если выше 40,
EEPROM_write(1, 40); //пишем в память 40
}
lcd.clear();
}
if (!button_plus) {
EEPROM_write(1, tempInk - 0.5);
if (tempInk < 20.0) { //проверяем, если выше 30,
EEPROM_write(1, 20.0); //пишем в память 30
}
lcd.clear();
}
lcd.setCursor(0, 0);
lcd.print("TEMP.K = ");
lcd.print(tempInk, 1);
lcd.print((char)223);
lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("minus NEXT plus");
delay(del);
}
}
//устанавливаем Hysteresis////////////////////////////////////////////////////////////////
void hysteresis_setup() {
float hysteresisTemp;
lcd.clear();
delay(del);
button_read();
lcd.setCursor(0, 0);
lcd.print("HYSTERESIS SET");
delay(1000);
int x = 0;
while (1) {
x++;
if (x > interval) {
break;
}
button_read();
EEPROM_read(12, hysteresisTemp );
if (!button_enter) {
delay(del);
lcd.clear(); //очищаем экран
break;
}
if (!button_minus) {
EEPROM_write(12, hysteresisTemp + 0.5);
if (hysteresisTemp > 10.0) { //проверяем, если выше 40,
EEPROM_write(12, 10.0); //пишем в память 40
}
lcd.clear();
}
if (!button_plus) {
EEPROM_write(12, hysteresisTemp - 0.5);
if (hysteresisTemp < 0.0) { //проверяем, если выше 40,
EEPROM_write(12, 0.0); //пишем в память 40
}
lcd.clear();
}
lcd.setCursor(0, 0);
lcd.print("Hysteresis=");
lcd.print(hysteresisTemp, 1);
//lcd.print((char)223);
//lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("minus NEXT plus");
delay(del);
}
}
//устанавливаем поворот///////////////////////////////////////////////////
void turn_setup() {
int turnPeriod;
lcd.clear();
delay(del);
button_read();
lcd.setCursor(0, 0);
lcd.print("TURN SETUP MAX");
delay(1000);
int x = 0;
while (1) {
x++;
if (x > interval) {
break;
}
button_read();
EEPROM_read(11, turnPeriod);
if (!button_enter) {
delay(del);
lcd.clear(); //очищаем экран
break;
}
if (!button_minus) {
EEPROM_write(11, turnPeriod + 1);
if (turnPeriod > 200) { //проверяем, если выше 40,
EEPROM_write(11, 200); //пишем в память 40
}
lcd.clear();
}
if (!button_plus) {
EEPROM_write(11, turnPeriod - 1);
if (turnPeriod < 0) { //проверяем, если выше 40,
EEPROM_write(11, 0); //пишем в память 40
}
lcd.clear();
}
EEPROM_read(11, turnPeriod);
lcd.setCursor(0, 0);
lcd.print("PAUSE MAX = ");
lcd.print(turnPeriod);
lcd.print(" s");
lcd.setCursor(0, 1);
lcd.print("minus NEXT plus");
delay(del);
}
}
//устанавливаем поворот_MIN
void turnMin_setup() {
int turnPeriodMin;
lcd.clear();
delay(del);
button_read();
lcd.setCursor(0, 0);
lcd.print("TURN SETUP MIN");
delay(1000);
int x = 0;
while (1) {
x++;
if (x > interval) {
break;
}
button_read();
EEPROM_read(20, turnPeriodMin);
if (!button_enter) {
delay(del);
lcd.clear(); //очищаем экран
break;
}
if (!button_minus) {
EEPROM_write(20, turnPeriodMin + 1);
if (turnPeriodMin > 100) { //проверяем, если выше 40,
EEPROM_write(20, 100); //пишем в память 40
}
lcd.clear();
}
if (!button_plus) {
EEPROM_write(20, turnPeriodMin - 1);
if (turnPeriodMin < 0) { //проверяем, если выше 40,
EEPROM_write(20, 0); //пишем в память 40
}
lcd.clear();
}
EEPROM_read(20, turnPeriodMin);
lcd.setCursor(0, 0);
lcd.print("PAUSE MIN= ");
lcd.print(turnPeriodMin);
lcd.print(" s");
lcd.setCursor(0, 1);
lcd.print("minus NEXT plus");
delay(del);
}
}
//устанавливаем сигнализацию/////////////////////////////////////////////////////////////
void alarm_setup() {
int alarmTemp;
lcd.clear();
delay(del);
button_read();
lcd.setCursor(0, 0);
lcd.print("ALARM SETUP");
delay(1000);
int x = 0;
while (1) {
x++;
if (x > interval) {
break;
}
button_read();
EEPROM_read(5, alarmTemp);
if (!button_enter) {
delay(del);
lcd.clear(); //очищаем экран
break;
}
if (!button_minus) {
EEPROM_write(5, alarmTemp + 1);
if (alarmTemp > 40) { //проверяем, если выше 40,
EEPROM_write(5, 40); //пишем в память 40
}
lcd.clear();
}
if (!button_plus) {
EEPROM_write(5, alarmTemp - 1);
if (alarmTemp < 1) { //проверяем, если выше 40,
EEPROM_write(5, 1); //пишем в память 40
}
lcd.clear();
}
lcd.setCursor(0, 0);
lcd.print("T.Alarm + - ");
lcd.print(alarmTemp);
lcd.print((char)223);
lcd.print("C");
lcd.setCursor(0, 1);
lcd.print("minus NEXT plus");
delay(del);
}
}
//устанавливаем вентиляцию/////////////////////////////////////////////////////////////////
void ventMax_setup() {
int fanMax;
lcd.clear();
delay(del);
button_read();
lcd.setCursor(0, 0);
lcd.print("FAN MAX SETUP");
delay(1000);
int x = 0;
while (1) {
x++;
if (x > interval) {
break;
}
button_read();
EEPROM_read(9, fanMax);
if (!button_enter) {
delay(del);
lcd.clear(); //очищаем экран
break;
}
if (!button_minus) {
x = 0;
EEPROM_write(9, fanMax + 1);
if (fanMax > 255) { //проверяем, если выше 40,
EEPROM_write(9, 255); //пишем в память 40
}
lcd.clear();
}
if (!button_plus) {
x = 0;
EEPROM_write(9, fanMax - 1);
if (fanMax < 150) { //проверяем, если выше 40,
EEPROM_write(9, 150); //пишем в память 40
}
lcd.clear();
}
lcd.setCursor(0, 0);
lcd.print("FAN MAX = ");
lcd.print(fanMax);
//lcd.print((char)223);
lcd.print("");
lcd.setCursor(0, 1);
lcd.print("minus NEXT plus");
delay(del);
}
}
void ventMin_setup() {
int fanMin;
lcd.clear();
delay(del);
button_read();
lcd.setCursor(0, 0);
lcd.print("FAN MIN SETUP");
delay(1000);
int x = 0;
while (1) {
x++;
if (x > interval) {
break;
}
button_read();
EEPROM_read(16, fanMin);
if (!button_enter) {
delay(del);
lcd.clear(); //очищаем экран
break;
}
if (!button_minus) {
x = 0;
EEPROM_write(16, fanMin + 1);
if (fanMin > 50) { //проверяем, если выше 40,
EEPROM_write(16, 50); //пишем в память 40
}
lcd.clear();
}
if (!button_plus) {
x = 0;
EEPROM_write(16, fanMin - 1);
if (fanMin < 5) { //проверяем, если выше 40,
EEPROM_write(16, 5); //пишем в память 40
}
lcd.clear();
}
lcd.setCursor(0, 0);
lcd.print("FAN MIN = ");
lcd.print(fanMin);
//lcd.print((char)223);
//lcd.print("");
lcd.setCursor(0, 1);
lcd.print("minus NEXT plus");
delay(del);
}
}
void getSensors() //////////////////////////////////////////////////////////////////////
{
unsigned long curMillis = millis(); // Получаем текущее время работы
sensors.requestTemperatures();
// Demonstrate non-blocking calls
if (currentMillis - trhMillis >= TRHSTEP) { // время для нового измерения?
measActive = true;
trhMillis = curMillis;
}
temp1Ink = sensors.getTempCByIndex(0);
}
//используем терморегулятор//////////////////////////////////////////
void thermostat() {
unsigned long currentMillis = millis ();
int fanMax;
int fanMin;
float tempPoint;
float hysteresisTemp ;
int turnPeriod; //период поворота лотков в часах
int turnPeriodMin;
int turnCommand;
int ledState = LOW;
EEPROM_read_mem(1, &tempPoint, sizeof(tempPoint));
EEPROM_read(1, tempPoint);
EEPROM_read(12, hysteresisTemp);
EEPROM_read(9, fanMax);
EEPROM_read(16, fanMin);
EEPROM_read(11, turnPeriod);
EEPROM_read(20, turnPeriodMin);
outMax = fanMax;
outMin = fanMin;
Setpoint = tempPoint;
Input = temp1Ink;
lcd.setCursor(0, 0); // устанавливаем курсор в 0-ом столбце, 0 строка (начинается с 0)
lcd.print("T1=");
lcd.print(temp1Ink, 1); // печать температуры на дисплей
lcd.print((char)223);
lcd.print(" (");
lcd.print(Setpoint, 1);
lcd.print(")");
lcd.setCursor(9, 1);
lcd.print("s");
lcd.print(turnPeriod);
lcd.setCursor(13, 1);
lcd.print("s");
lcd.print(turnPeriodMin);
// if (temp1Ink < (Setpoint - hysteresisTemp)) analogWrite(heater_pin, outMax);
// if (temp1Ink > (Setpoint + hysteresisTemp))analogWrite(heater_pin, outMin);
if (temp1Ink < (Setpoint - hysteresisTemp))
{
analogWrite(heater_pin, outMax); turnCommand = turnPeriod;
}
else if
(temp1Ink > (Setpoint + hysteresisTemp))
{
analogWrite(heater_pin, outMin);turnCommand = turnPeriodMin;
}
if (ledState == LOW) {
if (currentMillis - previousMillis > turnCommand * 1000 && ledState == LOW) {
ledState = HIGH;//включаем светодиод
digitalWrite(ledPin, ledState);
}
}
if ( bouncer.update() ) {
if (currentMillis - previousMillis > ( bouncer.read() == LOW ) && ledState == HIGH) {
if ( bouncer.read() == LOW ) {
previousMillis = currentMillis; // сохраняем время последнего выключения
ledState = LOW;//выключаем светодиод
digitalWrite(ledPin, ledState);
}
}
}
}
/*
//управляем поворотом////////////////////////////////////////////////////////////////
void turn() {
unsigned long currentMillis = millis ();
int turnPeriod; //период поворота лотков в часах
int turnPeriodMin;
int turnCommand;
int ledState = LOW; // этой переменной устанавливаем состояние светодиода
EEPROM_read(11, turnPeriod);
lcd.setCursor(9, 1);
lcd.print("s");
lcd.print(turnPeriod);
EEPROM_read(20, turnPeriodMin);
lcd.setCursor(13, 1);
lcd.print("s");
lcd.print(turnPeriodMin);
if (turnPeriod == 0) return; //если нулевой период поворота, то не поворачиваем .
if (turnPeriod < 13) turnCommand = turnPeriod;
if (ledState == LOW) {
if (currentMillis - previousMillis > turnCommand * 1000 && ledState == LOW) {
ledState = HIGH;//включаем светодиод
digitalWrite(ledPin, ledState);
}
}
if ( bouncer.update() ) {
if (currentMillis - previousMillis > ( bouncer.read() == LOW ) && ledState == HIGH) {
if ( bouncer.read() == LOW ) {
previousMillis = currentMillis; // сохраняем время последнего выключения
ledState = LOW;//выключаем светодиод
digitalWrite(ledPin, ledState);
}
}
}
}
*/
//управляем авариями///////////////////////////////////////////////////////////////////////
void alarm() {
float tempInk = sensors.getTempCByIndex(0);
int alarmTemp;
float setTemp;
EEPROM_read(5, alarmTemp);
EEPROM_read_mem(1, &setTemp, sizeof(setTemp));
EEPROM_read(1, setTemp);
lcd.setCursor(0, 3);
lcd.print("A");
lcd.print(setTemp + alarmTemp, 1);
if (millis() > 5000) {
if (tempInk > (setTemp + alarmTemp) || tempInk < (setTemp - alarmTemp)) {
//beeper(10);
digitalWrite(alarm_pin, HIGH); //если измеренная температура выше заданной на величину аварии
}
else digitalWrite(alarm_pin, LOW); //то включаем аварийный сигнал.
}
}
void beeper(int duration) {
tone(beeper_pin, 2000, duration);
}
Господа гуру, моя первая попытка была весьма неудачная. Написал укороченный скеч.Но рабоает криво: когда температуа нарастает-порядок.А вот при падении таймер переключаетса обратно от верхчей температуры.С ШИМом всё ок.Чего то не хватает,но...?
#include <Wire.h> #include <LiquidCrystal_I2C.h> #include <EEPROM2.h> #include <DallasTemperature.h> #include <OneWire.h> #include <Bounce.h> #define heater_pin 11 // нагреватель10 #define ledPin 9 // управление поворотом #define DS18B20_Pin A1 //пин термометра #define BUTTON 8 //limit switch Bounce bouncer = Bounce(BUTTON, 20); // limit switch float tempTank; // Температура DS18B20 unsigned long trhMillis = 0; // период опроса датчиков const unsigned long TRHSTEP = 3000UL; // Sensor query period byte measActive = false; LiquidCrystal_I2C lcd(0x27, 16, 2); // инициализация библиотеки дисплея OneWire oneWire(DS18B20_Pin); DallasTemperature sensors(&oneWire); double outMin , outMax ;//PWM void setup() { TCCR2B = TCCR2B & 0b11111000 | 0x01; // 32 kHz PWM Serial.begin(9600); lcd.init(); // Старт дисплея lcd.backlight(); // Включаем подсветку дисплея pinMode(BUTTON, INPUT_PULLUP);// limit switch pinMode(heater_pin, OUTPUT); pinMode(ledPin, OUTPUT); sensors.begin(); sensors.setResolution(12); // установить разрешение (точность) sensors.setWaitForConversion(false); // отключить ожидание } void loop() { getSensors(); Temperature(); } void Temperature(){ static uint32_t millis_start = 0; int val ; int turnMin=2; //будет братса из меню int turnMax=5; //будет братса из меню int ledState = LOW; val=turnMin,turnMax; outMax = 200; //будет братса из меню outMin = 20; //будет братса из меню if (tempTank <=28) { analogWrite(heater_pin, outMax); val = turnMin; } if (tempTank >=30){ analogWrite(heater_pin, outMin); val = turnMax; } if ( bouncer.update() ) { //это лимит кнопка if ( bouncer.read() == LOW ) {//это лимит кнопка ledState = LOW;//выключаем светодиод digitalWrite(ledPin,LOW); millis_start = millis(); } } if(millis_start && millis()-millis_start >= val*1000) { digitalWrite(ledPin,HIGH); millis_start = 0; } lcd.setCursor(0, 0); lcd.print("T="); lcd.print(tempTank, 1); lcd.print((char)223); } void getSensors() {////////////////////////////////////////////////////////////////////// unsigned long curMillis = millis(); // Получаем текущее время работы sensors.requestTemperatures(); if (curMillis - trhMillis >= TRHSTEP) { // время для нового измерения? measActive = true; trhMillis = curMillis; } tempTank = sensors.getTempCByIndex(0); }и как мне до вас достучатся?
А Вы правда расчитывали что кто-то будет вникать и разбираться с Вашими 600(!) строками кода? Это Вам в "ищу исполнителя".
Подсказка - используйте вывод условий/переменных для тестирования, тогда увидите что и где.
спасибо ,JollyBiber,я в serial вывожу val значение и она недаёт повода для размышления.я урезал неважное в #1 посту ,и пока не нахожу инфо ,што надо дописать вот здесь:
if (tempTank <=28) { analogWrite(heater_pin, outMax); val = turnMin; } if (tempTank >=30){ analogWrite(heater_pin, outMin); val = turnMax; }штоб таймер переключался вместе с ШИМом
Вот если честно - 3 раза перечитал Ваши сообщения и так и не понял что Вы хотите :)
Подробно:
когда температура <30 - outMax(pwm),turnMin(таймер)
когда температура >30 - outMin,turnMax
когда температура падает до 28 - outMin,turnMin?(переключаетса из turnMax==30)
когда температура ниже 28 - outMax,turnMin.
почему таймер НЕСИНХРОННО работает с analogWrite
(pvm),вот чего я не поймуЯ не знаю. Данные есть только у Вас, что в них знаете только Вы и делиться этим не хотите.
JollyBiber,данные есть в #1 ,но проблема решилась разделив условие.
if (tempTank <=28) { analogWrite(heater_pin, outMax); digitalWrite(Led,HIGH); } if(tempTank >=30) { analogWrite(heater_pin, outMin); digitalWrite(Led,LOW); } if(digitalRead(Led)==HIGH) { val = turnMin; } else { val = turnMax; }я дописал лед, как контрольную лампу,и от неё задал таймер
Спасибо всем!
Я продвигаюсь далше.Подключил дачик дыма(temp_c).Он работает как задумал.Хочю сделать ,что пока температура( Temperature) недостигла заданной(TstatTemp),arduino игнорировало заданную температуру дыма(smoke).Может кто помилует.
if ( Temperature <= ( TstatTemp - Hysteresis ) && temp_c <= smoke) //------------------- { и т.д,,,... это из скеча,што и как
и в чем проблема?
Просто не знаю как написать-"что пока температура( Temperature) недостигла заданной(TstatTemp),arduino игнорировало заданную температуру дыма(smoke).''тоесть,пока ненагрелось,дыма не проверять
тоесть,пока ненагрелось,дыма не проверять
ну у Вас так и написано
если (температура больше заданной)
да,это одна строка для понятия терминов.Мне надо добавить в скеч условие ,чтоб не проверял дыма до нагревания.
То Maverik,если оставить контроль дыма с начало топки,то дом и ненагреть,потому что ардуино будет уводить к снижению температуры.
это и есть условие.
Опять же,спасибо,JollyBiber,я кажется не о том думал!Просто почти повторил главное условие ,и дачик дыма заработал как задумалось.Я прикрепил весь цикл провеки температур,и хочу спросить-правильно эт всё написанно?(он рабочий).
// термостатирование////////////////////////////// static uint32_t millis_start = 0; int ledState = LOW; val = turnMin,turnMax; if( Temperature <= ( TstatTemp - 3 )) { analogWrite(Fan, outMax); digitalWrite(Led,HIGH); } else if ( Temperature <= ( TstatTemp - Hysteresis )&& temp_c <= smoke) { analogWrite(Fan, outMax); digitalWrite(Led,HIGH); } else{ analogWrite(Fan, outMin); digitalWrite(Led,LOW); } if (Temperature >= (TstatTemp + Hysteresis )) { analogWrite(Fan, outMin); digitalWrite(Led,LOW); } if(digitalRead(Led)==HIGH) { val = turnMin; } else { val = turnMax; } if ( bouncer.update() ) { if ( bouncer.read() == LOW ) { ledState = LOW;//выключаем светодиод digitalWrite(ledPin,LOW); millis_start = millis(); } } if(millis_start && millis()-millis_start >= val*1000) { digitalWrite(ledPin,HIGH); millis_start = 0; } //~~~~~~~~~MAX6675~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~```` static unsigned long prevMillis=0; if( (millis()-prevMillis)>2000){ prevMillis=millis(); temp_c = thermocouple.measure(TEMPC); }