Необходимо привести скетч в порядок.

Sonologist
Sonologist аватар
Offline
Зарегистрирован: 08.06.2018

Программа написана и в принципе работает. Но есть неприятные траблы - нечеткое срабатывание энкодеров. Схема "железа" исправна: в "чистом виде" (просто считывание энкодеров) проходит нормально. Понимаю, что в полном скетче имеется какой-то конфликт. По причине слабой подготовки выудить проблему не смог.  Необходимо привести программу в порядок. Лучше общение в почту: bma280156@mail.ru (возможно ли, стоимость, сроки...)

Программа (прошу не пинать, слаб я еще в программировании ардуино):

       //АРДУИНО УНО Управление клапаном отбора
    
       //________Подключение библиотеки термометров 
#include <OneWire.h>
       //________Объявление пинов температурных датчиков
OneWire ds_col(9); // Датчик колонны на нпине 9
OneWire ds_add(8); // Дополнительный датчик на пине 8
       //________Подвязывание переменных к библиотеке датчиков
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr_col[8];
byte addr_add[8];
long reading_time;

#include "LedControl.h" //Библиотека индикаторов
      /* Рацветка шлейфов на индикацию:
      GND                 -  фиолетовый 
      Din (dout) - пин 11 -  желтый
      CS (load) -  пин 12 -  зеленый   
      CLK -        пин 13 -  синий
      четвертая цифра "X" - количество модулей */
LedControl lc = LedControl(10, 12, 11, 4);  //создаём объект класса LedControl (din,clk,cs,X)
      //ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
      // Массив с закодированными символами для надписей.
byte bukvy[37] = 
              {
                B01110111,    //A-0
                B01111111,    //B-1
                B01001110,    //C-2
                B01001111,    //E-3
                B01000111,    //F-4
                B01011110,    //G-5
                B00110111,    //H-6
                B00111000,    //J-7
                B00001110,    //L-8
                B01111110,    //O-9
                B01100111,    //P-10
                B01011011,    //S-11
                B00111110,    //U-12
                B00111011,    //Y-13
                B01101101,    //Z-14
                B01011111,    //Б-15
                B01000110,    //Г-16
                B01111001,    //З-17
                B01110110,    //П-18
                B00110011,    //Ч-19
                B00011111,    //Ь-20
                B00011111,    //b-21
                B00001101,    //c-22
                B00111101,    //d-23
                B00010111,    //h-24
                B00010000,    //i-25
                B00011000,    //j-26
                B00001100,    //l-27
                B00010101,    //n-28
                B00011101,    //o-29
                B00011100,    //u-30
                B00000101,    //г-31
                B01100011,    //°-32
                B00001000,    //_-33
                B00000001,    //--34
                B00001001,    //:-36
                B00000000,    //пусто-37
              };

//Переменные кнопок
volatile int but_delta_val=0;    //Значения кнопки дельты
volatile int but_valve_val=0;   //Значения кнопки клапана

// Переменные значения и времени считывания энкодера дельты
unsigned char enc_delta_a;    //Значение вывода А энкодера дельты
unsigned char enc_delta_b;    //Значение вывода В энкодера дельты
unsigned char enc_delta_a_prev=0;   //Предыдущее значение вывода А энкодера дельты 
unsigned long enc_delta_curr_time;  //Текущая временная переменная энкодера дельты
unsigned long enc_delta_loop_time;  //Предыдущая временная переменная энкодера дельты
int enc_delta_val;      //Значение энкодера дельты

// Переменные значения и времени считывания энкодера клапана
unsigned char enc_valve_a;    //Значение вывода А энкодера клапана
unsigned char enc_valve_b;    //Значение вывода В энкодера клапана
unsigned char enc_valve_a_prev=0;  //Предыдущее значение вывода А энкодера клапана 
unsigned long enc_valve_curr_time;  //Текущая временная переменная энкодера клапана
unsigned long enc_valve_loop_time;  //Предыдущая временная переменная энкодера клапана
int enc_valve_val;      //Значение энкодера клапана

//Переменные температуры
volatile int temperature_colonna=0;   //Температура колонны
volatile int temperature_addition=0;  //Температура дополнительного датчика
volatile int temperature_delta=0;   //Температура отсечки
unsigned long temperature_time; //Переменная задержки времени для считывания датчиков температуры
unsigned long temperature_loop_time; //Переменная задержки времени для считывания датчиков температуры предыдущая

//Переменные клапана
int valve_n=0;          //Количество опросов клапана
unsigned long valve_time=0;    //Текущая временная переменная работы клапана
unsigned long valve_time_prev=0;  //Предыдущая временная переменная работы клапана
volatile int valve;     //Скважность клапана с шагом 1/100 от 0 до 1.00
volatile int valve_on;      //Время открытого клапана (мсек)
volatile int valve_off;     //Время закрытого клапана (мсек)
volatile int encoder_valve_position; //Статус энкодера клапана
volatile int encoder_valve_position_new; //Значение энкодера клапана
// Переменные для индикации
volatile int tys; //Тысячи 
volatile int sot; //Сотни
volatile int des; //Десятки
volatile int edi; //Единицы


void setup()
{
  Serial.begin(115200);
  //Назначаем пины
  for (int pin=2; pin<10;pin++) //На вход
  {
    pinMode(pin, INPUT);
  }
  for (int pin=10; pin<14;pin++) //На выход 
  {
    pinMode(pin, OUTPUT);  
  }
  //Инициализация модуля индикаторов
  for (int ind=0;ind<4;ind++)
    {
      lc.shutdown(ind, false); //Выводим из спящего режима
      lc.setIntensity(ind,3);  //Яркость дисплеев на 3. Всего возможных режимов яркости от 0 до 15
      lc.clearDisplay(ind);    //Очистить дисплей       
    }   
  //Прописываем "Col    °" (температура колонны)
  lc.setRow(0, 7, bukvy[2]);//Индикация C"
  lc.setRow(0, 6, bukvy[29]);//Индикация "o"
  lc.setRow(0, 5, bukvy[27]);//Индикация "l"
  lc.setRow(0, 0, bukvy[32]);//Индикация "°"
  lc.setDigit(0, 3, 0, false);
  lc.setDigit(0, 2, 0, true);
  lc.setDigit(0, 1, 0, false);
  //Прописываем "Add    °" (второй датчик температуры) 
  lc.setRow(3, 7, bukvy[0]);//Индикация "A"
  lc.setRow(3, 6, bukvy[23]);//Индикация "d"
  lc.setRow(3, 5, bukvy[23]);//Индикация "d"
  lc.setRow(3, 0, bukvy[32]);//Индикация "°"
  lc.setDigit(3, 3, 0, false);
  lc.setDigit(3, 2, 0, true);
  lc.setDigit(3, 1, 0, false);
  //Прописываем "Adj    °" (настройка дельты)
  lc.setRow(1, 7, bukvy[0]);//Индикация "A"
  lc.setRow(1, 6, bukvy[23]);//Индикация "d"
  lc.setRow(1, 5, bukvy[26]);//Индикация "j"
  lc.setRow(1, 0, bukvy[32]);//Индикация "°"
  lc.setDigit(1, 3, 0, false);
  lc.setDigit(1, 2, 0, true);
  lc.setDigit(1, 1, 0, false);
  //Прописываем "Pro" (скважность клапана)
  lc.setRow(2, 7, bukvy[10]);//Индикация "P"
  lc.setRow(2, 6, bukvy[31]);//Индикация "r"
  lc.setRow(2, 5, bukvy[29]);//Индикация "o"
  lc.setDigit(2, 2, 0, true);
  lc.setDigit(2, 1, 0, false);
  lc.setDigit(2, 0, 0, false);

  //Назначение прерываний  
  attachInterrupt(0, BUTTON_DELTA, RISING);  //Прерывание дельты
  attachInterrupt(1, BUTTON_VALVE, RISING); //Прерывание клапана

}
void loop()
{
  //________Запрос датчикам на измерение температуры
  if ( !ds_col.search(addr_col)) {}
  if ( !ds_add.search(addr_add)) {}
  //Инициируем датчик колонны
  ds_col.reset();
  ds_col.select(addr_col);
  ds_col.write(0x44); 
  //Инициируем дополнительный датчик
  ds_add.reset();
  ds_add.select(addr_add);
  ds_add.write(0x44); 
  
  // Опрос энкодера клапана
  enc_valve_curr_time = millis();
  if(enc_valve_curr_time >= (enc_valve_loop_time + 5)) // проверяем каждые 5 мсек
  { 
    enc_valve_a = digitalRead(5);     // считываем состояние выхода А энкодера 
    enc_valve_b = digitalRead(4);     // считываем состояние выхода B энкодера 
     if((!enc_valve_a) && (enc_valve_a_prev))// если состояние изменилось с положительного к нулю
    {    
      if(enc_valve_b) 
      {
        // выход В в полож. сост., значит вращение по часовой стрелке
        valve++;
        if(valve>100) {valve=100;}
      }   
      else 
      {
        // выход В в 0 сост., значит вращение против часовой стрелки     
        valve--;
        if(valve<0) {valve=0;}
      }   
     }   
    enc_valve_a_prev = enc_valve_a;     // сохраняем значение А для следующего цикла 
    enc_valve_loop_time = enc_valve_curr_time;
    VALVE_SETUP();
  }

  // Опрос энкодера дельты 
  enc_delta_curr_time = millis();
  if(enc_delta_curr_time >= (enc_delta_loop_time + 5)) // проверяем каждые 5 мсек
  { 
    enc_delta_a = digitalRead(7);     // считываем состояние выхода А энкодера 
    enc_delta_b = digitalRead(6);     // считываем состояние выхода B энкодера 
     if((!enc_delta_a) && (enc_delta_a_prev))// если состояние изменилось с положительного к нулю
    {    
      if(enc_delta_b) 
      {
        // выход В в полож. сост., значит вращение по часовой стрелке
        temperature_delta++;
        if(temperature_delta>999) {temperature_delta=999;}
      }   
      else 
      {
        // выход В в 0 сост., значит вращение против часовой стрелки     
        temperature_delta--;
        if(temperature_delta<0) {temperature_delta=0;}
      }   
     }   
    enc_delta_a_prev = enc_delta_a;     // сохраняем значение А для следующего цикла 
    enc_delta_loop_time = enc_delta_curr_time;
    DEGREE_DELTA();
  }
  
 // Работа клапана 
  valve_time=millis();
  if (valve_time - valve_time_prev > 100) //Опрос каждые 100 мсек
  {
    valve_n++;
    if((valve_n<=valve)&&(temperature_colonna<temperature_delta)) {digitalWrite (13,HIGH);}
    else {digitalWrite (13,LOW);}
    if(valve_n==100) {valve_n=0;}
    valve_time_prev=valve_time;
  }
 
   
  //Опрос показаний датчиков температуры 1 раз в 850 мсек
  if (millis()-reading_time>850)
  {
    //Опрашиваем датчик колонны
    present = ds_col.reset();
    ds_col.select(addr_col);
    ds_col.write(0xBE);
    for ( i = 0; i < 9; i++)  // нам необходимо 9 байт
    {
      data[i] = ds_col.read();
    }
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) 
    {
      raw = raw << 3; // разрешение 9 бит по умолчанию
      if (data[7] == 0x10) 
      {
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    } 
    else 
    {
      byte cfg = (data[4] & 0x60);
    }
    temperature_colonna=raw / 1.6;

    //Опрашиваем дополнительный датчик
    present = ds_add.reset();
    ds_add.select(addr_add);
    ds_add.write(0xBE);
    for ( i = 0; i < 9; i++)  // нам необходимо 9 байт
    {
      data[i] = ds_add.read();
    }
    //int16_t raw = (data[1] << 8) | data[0];
    raw = (data[1] << 8) | data[0];
    if (type_s) 
    {
      raw = raw << 3; // разрешение 9 бит по умолчанию
      if (data[7] == 0x10) 
      {
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    } 
    else 
    {
      byte cfg = (data[4] & 0x60);
    }
    temperature_addition=raw / 1.6;    
    reading_time=millis();
    DEGREE_COLONNA();
    DEGREE_ADDITION();
    }
}

void DEGREE_COLONNA()  //Прописываем текущую температуру колонны
{
        //Расчленение переменной температуры колонны  
        sot=temperature_colonna/100;
        des=temperature_colonna% 100 / 10;
        edi=temperature_colonna% 10;    
        // Индикация 
        lc.setDigit(0, 3, sot, false);
        lc.setDigit(0, 2, des, true);
        lc.setDigit(0, 1, edi, false);
}

void DEGREE_ADDITION()  //Прописываем текущую температуру дополнительного датчика
{
        //Расчленение переменной температуры дополнительного датчика
        sot=temperature_addition/100;
        des=temperature_addition% 100 / 10;
        edi=temperature_addition% 10;    
        // Индикация 
        lc.setDigit(3, 3, sot, false);
        lc.setDigit(3, 2, des, true);
        lc.setDigit(3, 1, edi, false);
}

void DEGREE_DELTA() //Прописываем температуру отсечки
{
        //Расчленение переменной температуры отсечки
        sot=temperature_delta/100;
        des=temperature_delta% 100 / 10;
        edi=temperature_delta% 10;   
        // Индикация 
        lc.setDigit(1, 3, sot, false);
        lc.setDigit(1, 2, des, true);
        lc.setDigit(1, 1, edi, false);
}

void VALVE_SETUP()  //Прописываем скважность клапана
{

        //Расчленение переменной скважности клапана
        sot=valve%1000/100;
        des=valve%100/10;
        edi=valve%10;   
        // Индикация 
        lc.setDigit(2, 2, sot, true);
        lc.setDigit(2, 1, des, false);
        lc.setDigit(2, 0, edi, false);  
}

void BUTTON_DELTA ()  //Приравниваем температуру отсечки к температуре колонны
{
  temperature_delta=temperature_colonna;
  DEGREE_DELTA();
}

void BUTTON_VALVE ()  //Отключаем-подключаем клапан
{
 
}

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Проблема в строках 170-171, пмсм: search достаточно медленная операция, зачем искать датчики на линии каждый проход loop - тайна сия великая есть. Да и энкодер - лучше на прерывание, пмсм; вместо прерывания кнопки или клапана, если не хотите возиться с PCINT.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Да и каждый проход loop посылать датчикам запрос на измерение (строки 173-179) - совершенно точно не надо: достаточно это сделать перед считыванием с них, один раз в секунду, например). Команда 0x44 (запустить конвертацию) - просто запустит конвертацию, и через N миллисекунд (зависит от настроенной разрядности) в регистре данных у датчика будет сконвертированная температура. Считывание с датчика - просто считывает этот регистр. Посему конвертацию запускать очень часто - смысла нет, достаточно это делать просто перед считыванием температуры с датчика.

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

Коллега! Ты бы не мог объяснить, собственно, сам алгоритм? Ибо плохо просматривается, что именно ты хотел сделать.

Пока я понял, что ты хочешь установить температуру прекращения отбора по датчику на (кубе/колонне/середине колонны - я не уяснил)?

И еще ты хочешь выставлять скорость отбора (ШИМ клапана), которая будет действовать до достижения "отсечки"?

Я всё правильно понял? Или ты имел ввиду отбор по схеме "старт/стоп" ?

karamzin01
Offline
Зарегистрирован: 08.03.2018

Р е а л и з у е м о - maslachenko767@mail.ru , консультации, подбор компонентов бесплатно, гарантии имеются

vvadim
Offline
Зарегистрирован: 23.05.2012

наверное проще (если автор распишет полное техзадание) с нуля написать, чем разбираться в чужом коде.

bwn
Offline
Зарегистрирован: 25.08.2014

Чет автор крылья опустил, и про PCINT ему говорили, и про Далласы, сломался. То ТС, такую портянку накатали, осталось ведь уже чуть чуть. А в этом разделе, самое верное мнение, постом выше. ИМХО.

-NMi-
Offline
Зарегистрирован: 20.08.2018

wdrakula пишет:

Коллега! Ты бы не мог объяснить, собственно, сам алгоритм?

Смотри как это должно работать...

1 - "разгоняемся" на максимальной мощности и как только верхний датчик температуры достиг первой уставки - уменьшаем мощность до тех пор, пока температура не упадёт до второй уставки, затем прибавляем мощность опять до первой уставки и тд и тп ДО появления ровной температурной полки и иже с ним - расчётной мощности нагрева. Т.е. мощность нагрева нужно ВЫЧИСЛИТЬ !!!

2 - Далее, собственно, на расчётной мощности "отбираем" через клапан и смотрим за температурой. Как только пошла "раскачка" по температуре - заканчиваем первый отбор.

Переходим к п.1 но уже с другими уставками по температуре и вычисляем уже "новую" мощность.

Отбираем уже на вновь вычисленных мощность и ШИМ клапан-а.

Ну и так далее до конечной уставки. Их там штук 6 - 8.

 

Ваащпе я нипайму, на форуме, где он это "подсмотрел" уже давно валяется вполне готовый и рабочий скетч, где всё это уже написано и проверено и не один год совершенствуется... правда там скутч тышш на 8 строк, разобрацца с ним это ещё тот гемор )))

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

-NMi- пишет:

Смотри как это должно работать...

Спасибо, конечно, что поделился своими наблюдениями. ;))))

1. Наш коллега что-то свое имел ввиду, это видно из представленного кода.

2. То, что ты описал и "давно лежит" лишь один из возможных и не самый оптимальный вариант. Просто к нему привыкли. Но (к примеру) технической необходимости менять мощность  вообще нет. Это используется исключительно для увеличения скорости процесса, но никто не мешает разогревать сырец на той же мощности, что и рабочая у колонны. И это только самый простой пример.

-NMi-
Offline
Зарегистрирован: 20.08.2018

wdrakula пишет:

Но (к примеру) технической необходимости менять мощность  вообще нет.

Это тебе так кажется. Возьми колонну и на максимуме нагрева попробуй с ней "совладать"

Запиши видео, запость сЮдой. Уотт тогда я буду задавать тебе более конкретные вопросы... а пока, ты, как и ТС мягко говоря "ниФтеме"  !!!