Необходимо привести скетч в порядок.
- Войдите на сайт для отправки комментариев
Сб, 20/07/2019 - 09:19
Программа написана и в принципе работает. Но есть неприятные траблы - нечеткое срабатывание энкодеров. Схема "железа" исправна: в "чистом виде" (просто считывание энкодеров) проходит нормально. Понимаю, что в полном скетче имеется какой-то конфликт. По причине слабой подготовки выудить проблему не смог. Необходимо привести программу в порядок. Лучше общение в почту: 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 () //Отключаем-подключаем клапан { }
Проблема в строках 170-171, пмсм: search достаточно медленная операция, зачем искать датчики на линии каждый проход loop - тайна сия великая есть. Да и энкодер - лучше на прерывание, пмсм; вместо прерывания кнопки или клапана, если не хотите возиться с PCINT.
Да и каждый проход loop посылать датчикам запрос на измерение (строки 173-179) - совершенно точно не надо: достаточно это сделать перед считыванием с них, один раз в секунду, например). Команда 0x44 (запустить конвертацию) - просто запустит конвертацию, и через N миллисекунд (зависит от настроенной разрядности) в регистре данных у датчика будет сконвертированная температура. Считывание с датчика - просто считывает этот регистр. Посему конвертацию запускать очень часто - смысла нет, достаточно это делать просто перед считыванием температуры с датчика.
Коллега! Ты бы не мог объяснить, собственно, сам алгоритм? Ибо плохо просматривается, что именно ты хотел сделать.
Пока я понял, что ты хочешь установить температуру прекращения отбора по датчику на (кубе/колонне/середине колонны - я не уяснил)?
И еще ты хочешь выставлять скорость отбора (ШИМ клапана), которая будет действовать до достижения "отсечки"?
Я всё правильно понял? Или ты имел ввиду отбор по схеме "старт/стоп" ?
Р е а л и з у е м о - maslachenko767@mail.ru , консультации, подбор компонентов бесплатно, гарантии имеются
наверное проще (если автор распишет полное техзадание) с нуля написать, чем разбираться в чужом коде.
Чет автор крылья опустил, и про PCINT ему говорили, и про Далласы, сломался. То ТС, такую портянку накатали, осталось ведь уже чуть чуть. А в этом разделе, самое верное мнение, постом выше. ИМХО.
Коллега! Ты бы не мог объяснить, собственно, сам алгоритм?
Смотри как это должно работать...
1 - "разгоняемся" на максимальной мощности и как только верхний датчик температуры достиг первой уставки - уменьшаем мощность до тех пор, пока температура не упадёт до второй уставки, затем прибавляем мощность опять до первой уставки и тд и тп ДО появления ровной температурной полки и иже с ним - расчётной мощности нагрева. Т.е. мощность нагрева нужно ВЫЧИСЛИТЬ !!!
2 - Далее, собственно, на расчётной мощности "отбираем" через клапан и смотрим за температурой. Как только пошла "раскачка" по температуре - заканчиваем первый отбор.
Переходим к п.1 но уже с другими уставками по температуре и вычисляем уже "новую" мощность.
Отбираем уже на вновь вычисленных мощность и ШИМ клапан-а.
Ну и так далее до конечной уставки. Их там штук 6 - 8.
Ваащпе я нипайму, на форуме, где он это "подсмотрел" уже давно валяется вполне готовый и рабочий скетч, где всё это уже написано и проверено и не один год совершенствуется... правда там скутч тышш на 8 строк, разобрацца с ним это ещё тот гемор )))
Смотри как это должно работать...
Спасибо, конечно, что поделился своими наблюдениями. ;))))
1. Наш коллега что-то свое имел ввиду, это видно из представленного кода.
2. То, что ты описал и "давно лежит" лишь один из возможных и не самый оптимальный вариант. Просто к нему привыкли. Но (к примеру) технической необходимости менять мощность вообще нет. Это используется исключительно для увеличения скорости процесса, но никто не мешает разогревать сырец на той же мощности, что и рабочая у колонны. И это только самый простой пример.
Но (к примеру) технической необходимости менять мощность вообще нет.
Это тебе так кажется. Возьми колонну и на максимуме нагрева попробуй с ней "совладать"
Запиши видео, запость сЮдой. Уотт тогда я буду задавать тебе более конкретные вопросы... а пока, ты, как и ТС мягко говоря "ниФтеме" !!!