отключение питания портит всю картину
- Войдите на сайт для отправки комментариев
Имеется код для управления масляным котлом, как бы основное работает и устраивает но есть несколько проблем которые возможно решить только с вашей помощью:
1) Самое гнустное то что показания шагового двигателя берутся с епром, но и по другому мне нельзя (надо чтоб после отключения я знал где находится вентиль) Здесь как раз и "зарыта собака" при каждот включении вентиль прокручивается на те обороты которые считывает с епром. Да, конечно можно убрать запись с епром и взять переменную int и использовать с минусовым значением (закрутить, открутить) , но хотелось бы отсчет от ноля как сейчас.
2) ну и remotexy ? но здесь наверное никто не поможет.. не могу управлть с телефона, в телефон приходят а ноборот никак...
/* ВСЕ для Андроида*/
#define REMOTEXY_MODE__HARDSERIAL
#include <RemoteXY.h>
/* настройки соединения */
#define REMOTEXY_SERIAL Serial3
#define REMOTEXY_SERIAL_SPEED 9600
/* конфигурация интерфейса */
#pragma pack(push, 1)
uint8_t RemoteXY_CONF[] =
{ 4,33,41,0,6,15,1,5,32,6
,47,51,51,2,7,21,19,25,22,6
,2,67,1,18,35,24,6,6,11,67
,1,30,10,28,13,1,11,67,1,3
,10,23,13,1,11 };
/* структура определяет все переменные вашего интерфейса управления */
struct {
/* input variable */
int8_t podachaM_x; /* =-100..100 координата x положения джойстика */
int8_t podachaM_y; /* =-100..100 координата y положения джойстика */
int16_t edit_step; /* −32767.. +32767 */
/* output variable */
char Maslo[11]; /* =строка UTF8 оканчивающаяся нулем */
char ULICA[11]; /* =строка UTF8 оканчивающаяся нулем */
char KOTEL[11]; /* =строка UTF8 оканчивающаяся нулем */
/* other variable */
uint8_t connect_flag; /* =1 if wire connected, else =0 */
} RemoteXY;
#pragma pack(pop)
#include <EEPROM.h>
#define ENCODER_DO_NOT_USE_INTERRUPTS // без прерываний.
#include <Encoder.h>
///////для датчиков температуры
#include <OneWire.h>// для датчиков температуры
#define dallas_1 3 //пин для датчика котла (X_MIN_PIN 3)
#define dallas_2 2 //пин для датчика улицы (X_MAX_PIN 2)
OneWire ds_1 (dallas_1);
OneWire ds_2 (dallas_2);
unsigned long time=0; // тоже для измерения температуры
boolean flag=0; // для измерения температуры
byte data[12]; // массив
float temp_1; // переменная температуры котла
float temp_2; // переменная температуры улицы
int raw; // переменная для арифметичесского вычитания в расчетах температуры
#include <AccelStepper.h>// библиотека шаговиков
AccelStepper Stepper1(1,54,55); //название движка и 1=по умолчанию (для драйвера 4488). 54=STEP . 55=DIR
#define dirPin 55 //#define X_STEP_PIN54 ,#define X_DIR_PIN55, #define X_ENABLE_PIN38
#define stepPin 54
// здесь экран
#include <LiquidCrystal.h> //Библиотека LCD
LiquidCrystal lcd(16, 17, 23, 25, 27, 29);
// переменные
int dir = 1; //используется для смены направления ШД
int podazh = EEPROM.read(0); // извлечь данные из памяти для шагов подачи Шд
boolean alarm = true; // переменная для включения аварии
int stroka = 0;// переменная номера строчек меню
long previousMillis = 0; // время последнего задействования
long previousMillis2 = 0; // время последнего задействования
long previousMillis3 = 0; // время последнего задействования
long previousMillis4 = 0; // время последнего задействования
long intervalKnopok = 700; // интервал для обработки кнопок
long signalSHD = 2000; // интервал после изменения переменной от энкодера ШД и до его вращения
boolean state_nasos = 0; // состояние насоса типа флага что насос либо работает либо нет
long nasos_Onn = 180000; // сколько минут насос работает при минусе на улице 3мин
long nasos_Off = 900000; // сколько минут насос выключен при минусе на улице 15мин
unsigned long new_millis_nasos = millis(); // Переменная для хранения времени
//объявление входов-выходов
Encoder knobEnkoder(31, 33); //кнопки энкодера
int sign = 37; //бузер аварии, динамик (100 гц нормально пищит)
int nasos = 10; // выход на твердотелое реле управление насосом
int enter = 41; // кнопка стопа на плате
int enterEnk = 35; //!!!!!!!!!!!!!!!!! кнопка на энкодере
void setup() {
izm_temp();
RemoteXY_Init ();
Stepper1.setMaxSpeed(100000); //устанавливаем максимальную скорость вращения ротора двигателя масла(шагов/секунду)
Stepper1.setAcceleration(12000); //устанавливаем ускорение (шагов/секунду^2)
//Настройка пинов
pinMode(enterEnk, INPUT_PULLUP);
pinMode(enter, INPUT_PULLUP);
pinMode(sign, OUTPUT);
pinMode(nasos, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(stepPin, OUTPUT);
pinMode(38, OUTPUT); // 38 как выход енейбл для ШД
pinMode(10, OUTPUT); // А10 как выход для включения насоса
//Настройка дисплея
//Установка количества столбцов и строк дисплея
lcd.begin(20, 4);
// Вывод приветствия при включении питания если нужно
lcd.setCursor(6, 1);
lcd.print("BUYANKA");
delay (2000);//Задержка приветствия
lcd.clear();
}
long positionLeft = -999; // позиция для энкодера в лево
void loop() {
RemoteXY_Handler (); // для блютуз
izm_temp();
{
//ОТОБРАЖЕНИЯ ТЕМПЕРАТУРЫ ВОДЫ НА ВЫХОДЕ КОТЛА
lcd.setCursor(0, 0);
lcd.print("KOTEL=");
lcd.print(temp_1);
lcd.print(" ");
//отображение температуры улицы
lcd.setCursor(0, 1);
lcd.print("ULICA=");
lcd.print(temp_2);
lcd.print(" ");
//подача масла
lcd.setCursor(0, 2);
lcd.print("PODAZHA=");
lcd.print(podazh);
lcd.print(" ");
// сигнализация
if (alarm == true )
{
lcd.setCursor(0, 3);
lcd.print("SIGNAL=DA ");
}
else if (alarm == false)
{
lcd.setCursor(0, 3);
lcd.print("SIGNAL=NET");
}
}
////////////ОБРАБОТКА БЛЮТУЗ ДЖОЙСТИКА
/*if (RemoteXY.podachaM_y > 5 <10)
{
podazh ++ ;
}
*/
if (RemoteXY.podachaM_y >= 10 <25)
{
podazh + 5 ;
}
if (RemoteXY.podachaM_y >= 25 <50)
{
podazh + 10;
}
if (RemoteXY.podachaM_y >= 50 <75)
{
podazh + 50;
}
if (RemoteXY.podachaM_y >= 75 <=100)
{
podazh + 100;
}
if (RemoteXY.podachaM_y > -5 < -10)
{
podazh --;
}
if (RemoteXY.podachaM_y >= -10 < -25)
{
podazh - 5;
}
if (RemoteXY.podachaM_y >= -25 < -50)
{
podazh - 10;
}
if (RemoteXY.podachaM_y >= -50 < -75)
{
podazh - 50;
}
if (RemoteXY.podachaM_y >= -75 < -100)
{
podazh - 100;
}
long newLeft; /// новая локальная переменная для энкодера
/////////////////////тоже самое но для подачи шагов для вентиля
newLeft = knobEnkoder.read()/4; // она равна /4 сигналам так как это приемливый делитель для моего энкодера.
if (newLeft > positionLeft ){ //здесь определяется направление вращения и если строка равна 2
lcd.setCursor(8, 2);
lcd.print(" ");
podazh ++ ; // и увеличиваю переменную для показаний на экране
positionLeft = newLeft; // запоминаю текущую позицию энкодера
}
if (newLeft < positionLeft){ // здесь все аналогично только уменьшаю значение на 1
lcd.setCursor(8, 2);
lcd.print(" ");
podazh -- ;
podazh = max(podazh, 1); // ограничиваю нижний предел, не меньше 1.
positionLeft = newLeft;
}
if (RemoteXY.edit_step > 0);
{
int podazh = RemoteXY.edit_step;
}
/////////////ПЕРЕМЕЩЕНИЕ ВЕНТИЛЯ
unsigned long currentMillis = millis(); // стартовая строка для осчета времени. задержка специальная чтоб шд крутился не сразу иначе экран мигает и полная белеберда
if(currentMillis - previousMillis2 > signalSHD){ // прошло время больше заданого в signalSHD
previousMillis2 = currentMillis; // команда для счетчика
digitalWrite(38, LOW); // отпускаю енейбле чтоб двигатель крутился ENABLE_PIN38
Stepper1.runToNewPosition(podazh * 25); // мотор движется столько сколько сейчас в переменной и * на 25
EEPROM.write(0, podazh);
digitalWrite(38, HIGH); // подаю высокий чтоб двиг освободился ENABLE_PIN38
}
itoa (podazh, RemoteXY.Maslo, 10); // вывожу показания шагов на экран андроида
if (RemoteXY.edit_step > 0);
{
int podazh = RemoteXY.edit_step;
}
/////////////// команда для сигнализации
if (digitalRead(enter) == LOW){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis3 > intervalKnopok){
previousMillis3 = currentMillis;
alarm = !alarm;
}
}
////////// управление насосом
if (temp_1 > 40) //если температура котла больше 40гр насос включается
{
analogWrite(10, 180); // вкл насос
}
if (temp_1 < 35) //если температура котла меньше 35гр насос выключается
{
analogWrite(10, 0); // выкл насос
}
if (temp_2 < -2 && temp_1 < 1) //если температура на улице меньше -2 вкл импульсы на насос
{
if(millis() > new_millis_nasos)
{
state_nasos = !state_nasos;// инвертирую 1 на 0 и наоборот
digitalWrite(10, state_nasos);//устанавливаем вывод в соответствующее состояние
if(state_nasos) // если state_nasos равен 1 (больше нуля, истина,..), то
{
new_millis_nasos = millis() + nasos_Onn; //присваиваем переменной сумму текущего состояния счетчика и заданного времени
}
else
{
new_millis_nasos = millis() + nasos_Off; //присваиваем переменной сумму текущего состояния счетчика и заданного времени
}
}
}
//////////включаю сигнализацию если в котле больше 90 или меньше -3
if (temp_1 > 90 || temp_1 < -3)
{
unsigned long currentMillis = millis(); //запускаю отсчет
if(currentMillis - previousMillis4 > 1000)// отсчитываю время 1сек
{
previousMillis4 = currentMillis; //сохраняю сразу время последнего включения
tone (sign, 100); //пищит 100 герц
}
}
else if (temp_1 < 87 || temp_1 > 0)// а если в котле стало ниже 87 или выше 0 то сигналка офф
{
noTone (sign);
}
}
void izm_temp(){
if(!flag){
start_izm();
time=millis();
flag=1;
}
if(flag && (millis()-time)>750){
calc_izm();
flag=0;
}
}
void start_izm(){
//запускаем измерение всех датчиков
ds_1.reset();
ds_1.write(0xCC);
ds_1.write(0x44);
ds_2.reset();
ds_2.write(0xCC);
ds_2.write(0x44);
}
void calc_izm(){
// Считываем и пересчитываем 1 датчик
ds_1.reset();
ds_1.write(0xCC);
ds_1.write(0xBE); // Read Scratchpad
for (byte i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds_1.read ();
}
raw = (data[1] << 8) | data[0];//=======Пересчитываем в температуру
temp_1 = (float)raw / 16.0;
dtostrf(temp_1, 0, 1, RemoteXY.KOTEL);
// Считываем и пересчитываем 2 датчик
ds_2.reset();
ds_2.write(0xCC);
ds_2.write(0xBE); // Read Scratchpad
for (byte i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds_2.read ();
}
raw = (data[1] << 8) | data[0];//=======Пересчитываем в температуру
temp_2 = (float)raw / 16.0;
dtostrf(temp_2, 0, 1, RemoteXY.ULICA);
}
решил пока тем что в сетапе прогоняю в "холостую" с отключеним енейбле пином.
// прокручу двигатель здесь в холостую из епром чтоб в реале он простоял digitalWrite(38, HIGH); // подаю высокий чтоб двиг освободился ENABLE_PIN38 Stepper1.runToNewPosition(podazh * 25); // мотор движется програмно но в реале стоит так как ENABLE HIGHну и с remotexy поступил иначе, изначально неправильно описал арифметику, потом пригляделся в компилятор, тот подсказал что нет смысла делать двойное сравненине типа: x<y<z а так же вместо
if (RemoteXY.podachaM_y >= 75 && RemoteXY.podachaM_y < 100) { podazh + 100 ; } вот так if (RemoteXY.podachaM_y >= 75 && RemoteXY.podachaM_y < 100) { podazh = podazh + 100 ; }здесь я вобще не понл почему так.. но изменил и компилятор промолчал.