Проблема прерываний с датчиком потока
#include <Wire.h> //Библиотека I2C
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
// Библиотека ЖК-дисплеев
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
const int pot_pin = A0;
const int pump_pwm= 3;
int press_pin =A1;
//параметры расходомера
int flowPin = 2; // входной контакт на arduino D2
double flowRate; // значение, предназначенное для расчета
double flowR; // значение потока в lt
double totalFlow; // общий выход потока из системы
byte sensorInterrupt = 0; // прерывание 0 на выводе D2 Arduino Nano
volatile int count; ////integer необходимо установить как volatile, чтобы обеспечить его корректное обновление во время процесса прерывания.
int pot_init= 0;
int pump_init= 0;
int percentValue =0;
void setup() {
lcd.begin(20,4); // A4 - A5 соединение SDA - SCL
lcd.backlight();
Serial.begin(9600);
pinMode( flowPin,INPUT); // Установить вывод D2 как вход
attachInterrupt(sensorInterrupt,Flow,RISING); // Настраивает прерывание 0 (контакт D2 на Arduino Nano) для запуска функции "Flow"
}
void flow_control(void) {
count = 0; // сбрасываем счетчик, чтобы он мог начать отсчет с 0
interrupts(); // включает прерывания на arduino nano
delay(1000); // ждем 1000 мсек
noInterrupts(); // отключаем прерывания на arduino nano
//расчет для расходомера
flowR = (count*8.93); // 112 импульсов/л 423.84 импульсов/галлон
flowRate= flowR*60; // преобразуем секунды в минуты, новая единица измерения — мл/минуты
flowRate= flowRate/1000; // конвертируем мл в литры, новая единица измерения — л/минуты
totalFlow += flowR;
// Распечатать расход в эту секунду в литрах/минуту
Serial.print("Flow rate: ");
Serial.print(int(flowRate)); // Распечатать целую часть переменной
Serial.print("L/min");
Serial.print("\t"); // Печать пространства табуляции
// Распечатать общее количество литров, прошедших с момента начала
Serial.print("Output Liquid Quantity: ");
Serial.print(totalFlow/1000);
Serial.println("L");
lcd.setCursor(0,2);
lcd.print("Flow: ");
lcd.setCursor(8,2);
lcd.print(flowRate);
lcd.print("lt/min");
lcd.setCursor(0,3);
lcd.print("Total: ");
lcd.setCursor(8,2);
lcd.print(totalFlow/1000);
lcd.print("lt");
}
void Flow(void)
{
count++; // каждый раз, когда эта функция вызывается, увеличиваем "count" на 1
}
void loop() {
pressure_cal();
pump_control();
flow_control();
lcd_control();
}
void pressure_cal(void) {
float sensorVoltage = analogRead(press_pin); // напряжение датчика A0
float psi = ((sensorVoltage-102)/204)*25; // Смещение 0 PSI= 0,5 В=102 единиц, 50 PSI= 2,5, 100 PSI= 4,5 В, 1 PSI= 0,04 В
// калибровка
float bar = psi*(0.0689475729); // Преобразование PSI в BAR
lcd.setCursor (0,1);
lcd.print (psi);
lcd.print (" PSI");
lcd.setCursor ( 10,1);
lcd.print(bar);
lcd.print( " BAR");
//lcd.setCursor(17,1);
//lcd.print(sensorVoltage);
Serial.println (sensorVoltage);
Serial.println(bar);
Serial.println (psi);
delay (100);
}
void pump_control(void)
{
// считываем аналоговое значение:
pot_init = analogRead(pot_pin);
// сопоставляем его с диапазоном аналогового выхода:
pump_init = map(pot_init, 0, 1023, 50, 230); // рабочий цикл между %20 - %90: управление скоростью, рабочий цикл между %0 - %20: выключено, рабочий цикл между %90 - %100: полная скорость
// отображать процент скорости насоса от полной шкалы
percentValue = map (pump_init, 50, 230,0,100);
// изменяем значение аналогового выхода:
analogWrite(pump_pwm, pump_init);
// выводим результаты на последовательный монитор:
Serial.print("\t Speed Input = ");
Serial.print(pot_init);
Serial.print("\t Speed Output = ");
Serial.print(pump_init);
Serial.print("\t Pump Speed Percentage = ");
Serial.println(percentValue);
lcd.setCursor(2,0);
lcd.print("Speed: ");
lcd.setCursor(8,0);
lcd.print("%");
lcd.setCursor(9,0);
lcd.print(percentValue);
lcd.print(" ");
// задержка после последнего считывания:
delay(2);
}
Я пытаюсь написать код, включающий датчик расхода, датчик давления и насос. Я написал код. Но когда я использую прерывание, код останавливается. Я использовал функции в "void loop()". Я переместил код прерывания (flow_control) между void setup и void loop. Но я вижу выходные данные в последовательном мониторе, но не вижу их на ЖК-дисплее. Не могли бы вы помочь мне решить проблему?
@sapphire, 👍2
Обсуждение1 ответ
Многие библиотеки периферии требуют включения прерываний, особенно когда они используют синхронизацию или выводы I2C/SPI. Вместо того, чтобы отключать прерывания для большей части скетча, вам нужно изолировать отключение прерываний, чтобы просто считывать и сбрасывать переменную счетчика:
noInterrupts(); // отключаем прерывания на arduino nano
local_count = count;
count=0;
interrupts(); // включает прерывания на arduino nano
Кроме того, вся эта обработка занимает некоторое время, что искажает синхронизацию, поэтому лучше использовать временную метку и миллисекунды:
беззнаковый длинный предыдущий_read;
if(millis() - previous_read > 1000){
noInterrupts(); // отключаем прерывания на arduino nano
int local_count = count;
count=0;
interrupts(); // включает прерывания на arduino nano
previous_read += 1000;
//скорость потока процесса на основе local_count
}
Мне заменить count*8.93 на local_count*8.93? Когда я это делаю, Arduino говорит, что local_count не был объявлен в этой области? Что мне делать? flowR = (count*8.93); // 112 импульсов/л 423.84 импульсов/галлон flowRate= flowR*60; // преобразуем секунды в минуты, новая единица измерения — мл/минуты flowRate= flowRate/1000; // конвертируем мл в литры, новая единица измерения — л/минуты, @sapphire
этот расчет должен быть внутри if (там, где находится комментарий), вам нужно запустить его только при обработке нового подсчета., @ratchet freak
Большое спасибо ratchet. Хочу добавить кнопку сброса только общего потока на ЖК-дисплее void flow_control(void) { если (digitalRead(resetButtonA) == LOW) { totalMilliLitresA = 0; lcd.setCursor(0, 1); lcd.print("0L"); }, @sapphire
Спасибо большое. Хочу добавить кнопку сброса, чтобы сбросить только общий поток на ЖК-дисплее. Этот код верен внутри void flow(void)? void flow_control(void) { если (digitalRead(resetButton) == LOW) { общий поток = 0; lcd.setCursor(0, 3); lcd.print("0L"); }, @sapphire
- Подключение двух Arduino через I2C, когда контакты I2C A4/A5 уже используются.
- Два датчика расхода, один ESP32, ЖК-дисплей и/или Arduino
- Управление двумя ультразвуковыми датчиками без блокировки другого
- Проблема стабильности кода прерываний, связанного с датчиком расхода
- Измерительный датчик HG-C 1100
- Проверка прерываний
- Как узнать, когда фильтр кофемашины закончен, используя любой датчик?
- Arduino Uno/Nano + ML
Что происходит в
lcd_control()
? Вы забыли включить эту функцию., @MajenkoЯ думал, что могу закодировать все команды lcd в функцию. Но код, который я добавил, функция не активна. Я забыл удалить ее., @sapphire