Ещё один богомпроклятый дозатор воды...
- Войдите на сайт для отправки комментариев
Чт, 02/11/2017 - 21:01
Добрый день уважаемые, представляю Вашему благочестивому вниманию скетч на дозатор жидкости...
3 Месяца я пытался понять в чём проблема этого диавольского устройства, в итоге после подключения генератора сигналов (и осциллографа для надёжности) я выяснил что после того как значения с датчика превышает 50 герц, программа перестаёт правильно сопоставлять количества входящих импульсов с количеством налитой воды... т.е. до 50 импульсов в секунду программа считает к примеру 9 импульсов за 0.1 литра, когда частота подачи импульсов (со счетчика) превышает 50 импульсов то программа как бы не успевает подсчитывать их и переводить в литры, т.е. скорость набора переменной отвечающей за 0.1 литра после 50-70 герц (импульсов в секунду со счётчика) не меняется от количества этих импульсов... Если у кого есть мысли об этом предлагаю поделиться.
========================================================================*/ #include <TM74HC595Display.h> // Библиотека Семисегментного дисплея "НОВАЯ" #include "TimerOne.h" // Библиотека таймера #include "sav_button.h" // Библиотека опроса кнопок SButton button1(2,50,0,0,500); // Пуск (пин 2, задержка 50) SButton button2(3,50,1000,0,500); // Больше (пин 3, задержка 50, время удержания 1сек для перехода в быстрый режим SButton button3(4,50,1000,0,500); SBUTTON_CLICK button_state1 = SB_NONE; // Обнуление данных по кнопкам SBUTTON_CLICK button_state2 = SB_NONE; SBUTTON_CLICK button_state3 = SB_NONE; // ------------------------------------ int Rele = 13; // выход на реле пуска воды int Datchik = 8; // Датчик воды int SCLK = 5; // Дисплей int RCLK = 6; // Дисплей int DIO = 7; // Дисплей int valBut = 0; // Задаем переменную, для счетчика int valBut_Min = 0; // Задаем переменную, для счетчика float n = 0; // Рабочие int m = 0; // переменные float Water_P = 1; // Переменная наполнения насосом float Water_R = 10; // Переменная наполнения оператором float Water_Rv = 1; // Переменная выставленного значения long previousMillis = 0; // Зададим начальное значение для счетчика millis long TimePush = 500; // Время нажатия на кнопку int LedVal = LOW; // устанавливаем начальное состояние светодиода int nm = 0; // переменная для команды STOP //------------------------------------- TM74HC595Display disp(SCLK, RCLK, DIO); // Подключение дисплея unsigned char LED_0F[29]; //-------------------------------------------------------------------------------------------------- // Callback функция по таймеру void timerIsr() { disp.timerIsr(); button_state1 = button1.Loop(); button_state2 = button2.Loop(); button_state3 = button3.Loop(); } void setup() { //------------------------------------------------------------------------------------------------- LED_0F[0] = 0xC0; //0 LED_0F[1] = 0xF9; //1 LED_0F[2] = 0xA4; //2 LED_0F[3] = 0xB0; //3 LED_0F[4] = 0x99; //4 LED_0F[5] = 0x92; //5 LED_0F[6] = 0x82; //6 LED_0F[7] = 0xF8; //7 LED_0F[8] = 0x80; //8 LED_0F[9] = 0x90; //9 LED_0F[10] = 0x88; //A LED_0F[11] = 0x83; //b LED_0F[12] = 0xC6; //C LED_0F[13] = 0xA1; //d LED_0F[14] = 0x86; //E LED_0F[15] = 0x8E; //F LED_0F[16] = 0xC2; //G LED_0F[17] = 0x89; //H LED_0F[18] = 0xF9; //I LED_0F[19] = 0xF1; //J LED_0F[20] = 0xC3; //L LED_0F[21] = 0xA9; //n LED_0F[22] = 0xC0; //O LED_0F[23] = 0x8C; //P LED_0F[24] = 0x98; //q LED_0F[25] = 0x92; //S LED_0F[26] = 0xC1; //U LED_0F[27] = 0x91; //Y LED_0F[28] = 0xBF; //Минус или 191 в десятичной системе LED_0F[29] = 0x7F;// Точка или 127 //-------------------------------------------- Serial.begin(115200); Serial.println("Test smart button ..."); //-------------------------------------------- // Инициация кнопок button1.begin(); button2.begin(); button3.begin(); // Инициализация таймера Timer1.initialize(1500); Timer1.attachInterrupt( timerIsr ); //----------------------------------------- // Проверка дисплея //----------------------------------------- disp.clear(); delay(1500); for (int i = 1111; i <= 9999; ) { disp.digit4(i); delay(200); disp.clear(); delay(200); i = i + 1111; } delay(1000); disp.set(LED_0F[22], 0); delay(2); disp.set(LED_0F[20], 1); delay(2); disp.set(LED_0F[14], 2); delay(2); disp.set(LED_0F[17], 3); //------------------------------------------- delay(2000); // очистка дисплея disp.clear(); delay(1000); disp.dispFloat((Water_R/10), 1); // Индикация установленных литров } //========================================== void loop(){ if( button_state1 != SB_NONE ){ //Serial.print("Press button 1 mode "); //Serial.println(button_state1); Water_Rv = Water_R; // Присваение значения "установлено набрать" button_state1 = SB_NONE; digitalWrite(Rele, HIGH); // Включить реле n = 0; // Обнуление рабочей переменной Water_P = 0; // Установка начального значения счетчика Pusk(); // Пуск digitalWrite(Rele, LOW); // отключение реле по окончанию налива } //-------------------------------------------- if( button_state2 != SB_NONE ){ //Serial.print("Press button 2 mode "); //Serial.println(button_state2); if (button_state2 == 1) // если нажата кнопка "больше" (короткое нажатие) { Water_R = Water_R + 1; // Увеличиваем на 0.1 литра disp.clear(); // очистка дисплея disp.dispFloat((Water_R/10), 1); // Индикация набранных литров delay(20); if ( Water_R >= 1000) // Ограничение по максимуму { Water_R = 1000; } } else { nabor_Max(); // если длинное нажатие. Перейти на у скоренный набор } button_state2 = SB_NONE; // сброст переменной опроса кнопки } //------------------------------------------ if( button_state3 != SB_NONE ){ //Serial.print("Press button 3 mode "); //Serial.println(button_state3); if (button_state3 == 1) // если нажата кнопка "меньше" { if ( Water_R >= 1) // Избавляемся от мерцания "минуса" { Water_R = Water_R - 1; // уменьшаем на 0.1 литра disp.clear(); // очистка дисплея disp.dispFloat((Water_R/10), 1); // Индикация набранных литров delay(20); if ( Water_R <= 0) // Ограничение по минимуму { Water_R = 0; } } } else { Nabor_Min(); // при длительном нажатии перейти в ускоренный набор } button_state3 = SB_NONE; // сброс переменной опроса кнопки } } //=========================== //=========================== void nabor_Max() { while(digitalRead(3) == LOW) // если кнопка еще нажата { Water_R = Water_R + 1; Water_R = abs( Water_R); // Увеличение на 1 литр (временная строка - заменить переменную) if ( Water_R >= 1000) // Ограничение по максимуму { Water_R = 1000; } disp.clear(); // очистка дисплея disp.dispFloat((Water_R/10), 1); // Индикация набранных литров delay(40); // скорость набора } } //=========================== void Nabor_Min() { while(digitalRead(4) == LOW) // если кнопка еще нажата { Water_R = Water_R - 1; // Уменьшение на 1 литр (временная строка - заменить переменную) Water_R = abs( Water_R); if (Water_R <= 1) // ограничение по минимуму { Water_R = 1; } disp.clear(); // очистка дисплея disp.dispFloat((Water_R/10), 1); // Индикация набранных литров delay(40); // скорость набора } } //=========================== void Pusk() { nm = 0; // Обнуление счетчика STOP float n = 0; disp.clear(); // очистка дисплея disp.dispFloat((Water_P/10), 1); // Индикация набранных литров (Старт) delay(20); int flag = 0; while(Water_P < Water_Rv) { //================================================= // Модуль установки и регулировки колличества //================================================= if (digitalRead(Datchik) == HIGH && flag == 0) { flag=1; n = n + 1; // Увеличение рабочей переменной Serial.println(n); if (n == 40) // Провека набранного 0.1 литра { Water_P = Water_P + 1; // Увеличение "набрано" Serial.println(Water_P/10); disp.clear(); // очистка дисплея disp.dispFloat((Water_P/10), 1); // Индикация набранных литров delay(1); // Serial.println(n); n = 0; // Сброс рабочей переменной nm = 0; // Счетчик аварийного отключения } } //---------------------------- if (nm == 6000) // модуль аварийного отключения { // (установка паузы до выхода в аварийный режим) STOP(); // аварийное отключение } nm = nm + 1; delay(5); //------------------------------ if (digitalRead(Datchik) == LOW && flag == 1) { flag=0; } //================================================== //================================================== } } //=================================================== void STOP() { digitalWrite(Rele, LOW); // отключение реле int Stop = 0; while(Stop <= 20) { // индикация аварии disp.set(LED_0F[23], 0); delay(2); disp.set(LED_0F[20], 1); delay(2); disp.set(LED_0F[14], 2); delay(2); disp.set(LED_0F[17], 3); delay(1000); disp.clear(); delay(500); } }
Мысль простая: не заниматься онанизмом, а посадить вход с датчика на пины с внешними прерываниями (2 и 3), и по смене фронта считать импульсы. Смотреть attachInterrupt, и после просветления окажется, что никакой проблемы 50 Герц для подсчёта кол-ва импульсов в секунду - не существует, проблема только в неправильно выбранном текущем подходе.
Может датчик на прерывание посадить?
godForgottenBe посмотри исходники тахометров, и тут и в интернете хватает