Проблема прерываний с датчиком потока

 #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. Но я вижу выходные данные в последовательном мониторе, но не вижу их на ЖК-дисплее. Не могли бы вы помочь мне решить проблему?

, 👍2

Обсуждение

Что происходит в lcd_control()? Вы забыли включить эту функцию., @Majenko

Я думал, что могу закодировать все команды lcd в функцию. Но код, который я добавил, функция не активна. Я забыл удалить ее., @sapphire


1 ответ


3

Многие библиотеки периферии требуют включения прерываний, особенно когда они используют синхронизацию или выводы 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