Программирую модуль климат-контроля. Есть вопрос.
- Войдите на сайт для отправки комментариев
Здравствуйте.
Затеял первый "серьезный" проект и столкнулся с некоторыми непонятками.
На данный момент код такой:
#include "Servo.h"
#include "DHT.h"
#include "PID_v1.h"
#include "PCD8544.h"
#include "EEPROM.h"
// Digital pins & PWM
#define POWER_RELAY 22 //реле поддержки питания
#define POWER_IN 23 //включение зажигания
#define INNER_SENSOR 24 //датчик температуры и влажности внутреннего воздуха цифровой (DHT11)
#define HEATER_MOTOR 2 //нога по которой управляется скорость вращения вентилятора отопителя
#define HEATER_VALVE 3 //сервопривод управления клапаном ОЖ
#define OUTER_AIR_SERVO 4 //сервопривод управления заслонкой воздуха
#define STATE_LED 13 //встроенный светодиод для индикации работы и имитации бурной деятельности
//Analog in pins
#define OUTER_TEMP A0 //датчик температуры наружнего воздуха аналоговый
#define COOLANT_TEMP A1 //датчик температуры теплоносителя
//настройки кнопочной станции
#define KEYTEMPUP 30 // |
#define KEYTEMPDOWN 31 // | регулировка температуры
#define KEYMODEAUTO 32 // режим автоматического регулирования скорости вентилятора
#define KEYONOFF 33 // включение\выключение модуля
#define KEYFANUP 34 // |
#define KEYFANDOWN 35 // | регулировка скорости вращения вентилятора
#define OUTER_AIRIN 36 // закрытие забора воздуха с улицы
//разметка EEPROM
#define FAN_SPEED 1 //
#define SETPOINT 2 // Адреса EEPROM для чтения значений при загрузке
#define MODE_AUTO 3 //
//тип датчика DHT
#define DHTTYPE DHT11 // у меня такой, если нужен другой тип - раскоментируй соответствующую строку
//#define DHTTYPE DHT21
//#define DHTTYPE DHT22
Servo heaterValve;
Servo outerAir;
static int heaterSpeed = 0;
static double outerTemp;
static double innerTemp;
static double innerHum;
static boolean modeAuto;
static double Setpoint, Input, Output; // создаем переменные для ПИД
//задаем коэффициенты ПИД
static double aggKp = 4, aggKi = 0.2, aggKd = 1; // агрессивные
static double consKp = 1, consKi = 0.05, consKd = 0.25; // консервативные
static double histeresis = 1; // коэффициент петли гистерезиса. пока не используется.
unsigned long beginTime; // переменная начала работы таймера выключения
void setup()
{
//первым делом взведем реле
digitalWrite(POWER_RELAY, HIGH);
// запуск порта отладки
Serial.begin(9600);
Serial.println("Climatic module v 0.1"); // Красивости...
Serial.print("Initialising");
delay(500);
Serial.print(".");
delay(500);
Serial.print(".");
delay(500);
Serial.print(".");
delay(500);
Serial.print(".");
delay(500);
Serial.print(".");
delay(500); //В принципе не мешают, пусть будут. Время работы в данной части не критично
// конфигурируем выходы
pinMode(POWER_RELAY, OUTPUT); // Выход "Реле "Камикадзе" (Поддерживает питание системы некоторое время после выключения зажигания, затем отключается)
pinMode(HEATER_MOTOR, OUTPUT); // Выход "Вентилятор"
pinMode(HEATER_VALVE, OUTPUT); // Выход "Клапан"
pinMode(STATE_LED, OUTPUT); // Встроенный светодиод
Serial.println();
Serial.println("Outputs configured");
// конфигурируем входы
pinMode(OUTER_TEMP, INPUT); // Вход "Температура снаружи"
pinMode(COOLANT_TEMP, INPUT); // Вход "Температура теплоноситель"
pinMode(KEYTEMPUP, INPUT); // |
pinMode(KEYTEMPDOWN, INPUT); // |
pinMode(KEYFANUP, INPUT); // |Входы кнопок
pinMode(KEYFANDOWN, INPUT); // |
pinMode(KEYONOFF, INPUT); // |
pinMode(KEYMODEAUTO, INPUT); // |
pinMode(OUTER_AIRIN, INPUT); // |
Serial.println();
Serial.println("Inputs configured");
//добавляем приводы
heaterValve.attach(HEATER_VALVE);
outerAir.attach(OUTER_AIR_SERVO);
Serial.println();
Serial.println("Servos attached");
//создаем вызов внутреннего датчика температуры-влажности
DHT inTemp(INNER_SENSOR, DHTTYPE);
inTemp.begin();
Serial.println();
Serial.println("Inner temperature sensor is ready");
//запускаем ПИД
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
Serial.println();
Serial.println("PID started");
//считываем значения предыдущего запуска
heaterSpeed = EEPROM.read(FAN_SPEED);
Setpoint = EEPROM.read(SETPOINT);
modeAuto = EEPROM.read(MODE_AUTO);
Serial.println();
Serial.println("Previvous start data:");
Serial.print("Fan speed: ");
Serial.println(heaterSpeed);
Serial.print("Temperature set: ");
Serial.println(Setpoint);
Serial.print("Fan mode: ");
if (modeAuto == 0) {
Serial.println("Manual");
}
else {
Serial.println("Auto");
}
Serial.println(modeAuto);
//приводим систему в стартовое состояние
analogWrite(HEATER_MOTOR, heaterSpeed); //да, 0=0, но пусть пока будет для страховки
outerTemp = analogRead(OUTER_TEMP);
innerHum = inTemp.readHumidity();
innerTemp = inTemp.readTemperature();
Serial.println();
if (innerTemp >= -50)
{
if (innerTemp <= 60) {
Serial.print("Current temperature: ");
Serial.print(innerTemp);
Serial.println(" ᵒC");
}
else
{
Serial.println("It's too HOT here! Or temperature sensor fail.");
}
}
else
{
Serial.println("It's too COLD here! Or temperature sensor fail.");
}
if (innerHum > 0 && innerHum < 100)
{
Serial.print("Current humidity: ");
Serial.print(innerHum);
Serial.println(" %");
}
else
{
Serial.println("Something wrong with humidity sensor!");
}
if (outerTemp > -50)
{
if (outerTemp < 50) {
Serial.print("Current temperature: ");
Serial.print(outerTemp);
Serial.println(" ᵒC");
}
else
{
Serial.println("It's too HOT here! Or temperature sensor fail.");
}
}
else
{
Serial.println("It's too COLD here! Or overboard temperature sensor fail.");
}
Serial.println("Thanks for flying our airline!");
}
void loop()
{
Serial.println("Starting!");
//код вызова завершающей функции
if (digitalRead(POWER_IN) == LOW)
{
beginTime = millis();
ending();
}
delay(1000);
}
void ending()
{
/*эта часть нужна для задержки выключения питания платы при запитке через реле "Камикадзе" но она пока нихрена не работает как задумано.*/
Serial.println("Ignition OFF");
Serial.println(beginTime);
Serial.println(millis());
scanIgnition();
Serial.println("Turning system OFF");
digitalWrite(POWER_RELAY, LOW);
}
void scanIgnition ()
{
do {
if (digitalRead(POWER_IN) == HIGH)
{
Serial.println("Ignition ON");
loop();
}
}
while (beginTime > (millis() - 100000));
}
Проблема заключается в следующем. в секции loop() пытался реализовать проверку наличия внешнего питания через проверку состояния цифрового входа. Проверка происходит (строки 192-196). При пропадании сигнала вызывается соответствующая (ending()) функция. А дальше начинаются странности.
Как я предполагал выполнение основной функции должно останавливаться и обработка передается в "дочернюю" функцию. Но почему-то loop() продолжает выполняться.
Воторой вопрос, с которым столкнулся - как остановить полностью выполнение программы? По идее после того, как будет отключено реле (строка 208), питание с платы пропадет. Но в случае работы "на столе" программа продолжает выполняться.
Программа расчитана на МЕГУ.
Попробуйте функции в коде "void ending(), scanIgnition ()" перенести выше
voidloop() или обьявить доvoidloop()К сожалению не помогло.
Нет тут никаких станностей, что пишите, то и получаете. Что должно препятствовать продолжению выполнения основного цикла? Что вы пытаетесь сделать в строке 220? Попробуйте посчитать, что у вас получится в этой строке если например beginTime = 100, а millis() возвращает 101.
Я пытался задать интервал времени для того чтобы система ждала появления сигнала на входе POWER_RELAY.
Переписал скетч так, чтобы к переменной beginTime сразу же прибавлялся этот интервал и объеденил обе процедуры в одну. Этот кусок кода заработал как надо. Спасибо!
А что можете посоветовать для остановки выполнения кода программы?
Если ваша система не будет работать месяцами, то такое решение прокатит, если же нет, то примерно через 40 дней ждите глюка. http://arduino.ru/forum/programmirovanie/eshche-raz-migaem-svetodiodom-b...
Спасибо! while(1) - то, что надо. Про переполнение значения я в курсе. Блок проектируется для авто. Аптайм 40 суток не реален.
Канонический таймер (например 3 сек):
unsigned long time; void setup(){ } void loop(){ if ((millis()-time) >3000){ // команды по таймеру time = millis(); } }А остановить скечь: for (;;){}