отключение питания портит всю картину

maxvalin
Offline
Зарегистрирован: 22.02.2016

Имеется код для управления масляным котлом, как бы основное работает и устраивает но есть несколько проблем которые возможно решить только с вашей помощью:

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);
}


  

   

 

maxvalin
Offline
Зарегистрирован: 22.02.2016

решил пока тем что в сетапе прогоняю в "холостую" с отключеним енейбле пином.

// прокручу двигатель здесь в холостую из епром чтоб в реале он простоял  
     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 ;
    }

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