Виснет выполнение программы

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019
[code]
//********  библиотеки
#include <util/atomic.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x38, 16, 2);
//******** константы
#define TIME1 6 // стоимость 1 пульса - сек
// пины подключения
#define PIN_RELAY 8
#define PIN_MONEY 7
#define RELAY_ON 1
#define RELAY_OFF 0
#define netVoda 10
int knopka = 9;
int knopkaOn;
volatile int counter1 = 0;// для подсчета количества пульсов
volatile int counter_copy;
volatile unsigned int  time_run_copy;
volatile unsigned int time_run_start;
unsigned long timeAllPulse1 = 1200.; // макс. время приема монеты
unsigned long timeCount1 = 0;

boolean run_cleaner = false;// включение пылесоса

volatile unsigned int time_run = 0;// для подсчета времени работы насоса
volatile
unsigned long millis1 = 0;// для подсчета времени работы насоса

void setup()
{
  lcd.init();// инициализируем экран
  lcd.backlight();// включаем подсветку
  Serial.begin(9600);
  pinMode(netVoda, INPUT);// реле уровня воды // настройка пинов
  pinMode(knopka, INPUT); // кнопка // настройка пинов
  pinMode(PIN_RELAY, OUTPUT);    // реле  // настройка пинов
  digitalWrite(PIN_RELAY, RELAY_OFF); // выключить  // настройка пинов
  attachInterrupt(4, count_pulse1, FALLING);  // запуск обработчика прерываний монетоприемника

}

void loop()
{
  if (counter1 > 0 && (millis() - timeCount1) > timeAllPulse1)
  {
    lcd.setCursor(2, 0);
    lcd.print("BHECEHO=");
    lcd.print(counter_copy);
    lcd.print("P");
  }
  atomicTime_run();
  // Выполнение атомарного блока присваивания
  atomicInterrupt();
  // Выполняем слежение кнопки
  knopkaPUSK();
  // истекло время приема монеты?

  if (knopkaOn == HIGH && counter1 > 0 && (millis() - timeCount1) > timeAllPulse1)
  {
    counter1 = 0;
    run_cleaner = true;
    millis1 = millis();
    cleaner_start();

  }

  // отсчет времени работы насоса

  if (run_cleaner)
  {
    if (millis() - millis1 >= 100)
    {
      millis1 = millis();
      time_run_start = time_run_copy - 1;
      lcd.setCursor(2, 0);
      lcd.print("BHECEHO=");
      lcd.print(time_run_start);
      lcd.print("P");

      if (time_run < 1) // выключить
      {

        cleaner_stop();
        run_cleaner = false;

      }

    }

  }

}

// обработка прерывания монетоприемника - получить кол-во импульсов

void count_pulse1()

{

  detachInterrupt(4);
  counter1++;
  if (counter1 == 1)
    timeCount1 = millis();
  delay(5);
  attachInterrupt(4, count_pulse1, FALLING);

}

// включить насос

void cleaner_start()
{

  digitalWrite(PIN_RELAY, RELAY_ON); // включить
}
void knopkaPUSK() // считываем состояние кнопки пуск
{
  knopkaOn = digitalRead(knopka);
  delay(200);
}

void atomicInterrupt()  // выполнение атомарного блока
{
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  {
    // Атомарный доступ к переменной counter1:
    counter_copy = counter1;
  }
}
void atomicTime_run()
{
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  {
    time_run_copy = time_run + counter_copy * TIME1;
  }
}


// выключить насос

void cleaner_stop()
{

  digitalWrite(PIN_RELAY, RELAY_OFF); // выключить
  delay(1000);
  counter1 = 0;
  time_run = 0;

}

[/code]

 

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

Помогите советом знающие принцип прерывания. У меня атомарная переменная time_run_copy при попытке вывести значение

 time_run_start на I2C ЖК дисплей.Значение виснет после вычита 1.То-есть counter_copy = 2 следовательно time_run_start = 12.
Так вот после нажатия кнопки пуск на дисплее замирает 11..голова уже пухнет
sadman41
Offline
Зарегистрирован: 19.10.2016

time_run всегда равно 0, стало быть всегда выполняется if (time_run < 1) и выключение насоса (или чего там) происходит на первом же вычете.

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019
void atomicTime_run()
132 {
133   ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
134   {
135     time_run_copy = time_run + counter_copy * TIME1;
136   }
137 }

Убрал вот это

Использовал только void atomicInterrupt()

Все заработало как нужно показывает вычет до 0 и отключает реле

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

sadman41 пишет:

time_run всегда равно 0, стало быть всегда выполняется if (time_run < 1) и выключение насоса (или чего там) происходит на первом же вычете.

я думал приравнял к 0 что бы при каждой итерации у меня значение в о выходило.Отключилось реле time_run в ноль

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

Теперь проблема такая.При уменьшении суммы на дисплее на месте ушедших разрядов появляются символы какие то.

sadman41
Offline
Зарегистрирован: 19.10.2016

Символы инопланетные что ли? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Символы инопланетные что ли? 

Каббалистические 

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

Символы старших разрядов.Вместо Руб появляется РРРуб)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ВСЕГДА печатайте строку ОДИНАКОВОЙ длины. Если сумма короткая, добавляйте пробелы слева или справа, как надо. И всего делов. Всё лишнее будет затираться

b707
Offline
Зарегистрирован: 26.05.2017

Сергей Данилов пишет:
Символы старших разрядов.Вместо Руб появляется РРРуб)

все логично, строчка двигается вправо, первый символ остается. Выводите на это место пробел

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019
[code]
//********  библиотеки
#include <util/atomic.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x38, 16, 2);
//******** константы
#define TIME1 6 // стоимость 1 пульса - сек
// пины подключения
#define PIN_RELAY 8
#define PIN_MONEY 7
#define RELAY_ON 1
#define RELAY_OFF 0
#define netVoda 10
int knopka = 9;
int knopkaOn;
int vodaNET;
volatile int counter1 = 0;// для подсчета количества пульсов
volatile int counter_copy;
unsigned long timeAllPulse1 = 1200.; // макс. время приема монеты
unsigned long timeCount1 = 0;

boolean run_cleaner = false;// включение насоса

volatile unsigned int time_run = 0;// для подсчета времени работы насоса
volatile
unsigned long millis1 = 0;// для подсчета времени работы насоса

void setup()
{
  lcd.init();// инициализируем экран
  lcd.backlight();// включаем подсветку
  Serial.begin(9600);
  pinMode(netVoda, INPUT);// реле уровня воды // настройка пинов
  pinMode(knopka, INPUT); // кнопка // настройка пинов
  pinMode(PIN_RELAY, OUTPUT);    // реле  // настройка пинов
  digitalWrite(PIN_RELAY, RELAY_OFF); // выключить  // настройка пинов
  attachInterrupt(4, count_pulse1, FALLING);  // запуск обработчика прерываний монетоприемника

}

void loop()
{
  if (vodaNET == LOW) // если нет воды в баке
  {
    digitalWrite(PIN_RELAY, RELAY_OFF);
    delay(500);
    lcd.clear();
    lcd.setCursor(4, 0);
    lcd.print("HET BO""\xE0\xAE");


  }
  if (counter_copy > 0 && (millis() - timeCount1) > timeAllPulse1) // ПЕЧАТАЕМ СКОЛЬКО ВНЕСЕНО
  {
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("BHECEHO=");
    lcd.print(counter_copy);
    lcd.print("P");
   }

  BEZVODY();// следим за  кнопки
  // Выполнение атомарного блока присваивания
  atomicInterrupt();
  // Выполняем слежение кнопки
  knopkaPUSK();
  // истекло время приема монеты?

  if (knopkaOn == HIGH && counter_copy > 0 && (millis() - timeCount1) > timeAllPulse1)
  {
    time_run = time_run + counter_copy * TIME1;
    run_cleaner = true;
    millis1 = millis();
    cleaner_start();

  }

  // отсчет времени работы насоса

  if (run_cleaner)
  {
    if (millis() - millis1 >= 100)
    {
      millis1 = millis();
       counter1 = 0;
      time_run = time_run - 1;
      lcd.setCursor(0, 0);
      lcd.print("BHECEHO = ");
      lcd.print(time_run);
      lcd.print(" P\xA9\xA0\x20"  );

      if (time_run < 1) // выключить
      {

        cleaner_stop();
        run_cleaner = false;

      }

    }

  }

}

// обработка прерывания монетоприемника - получить кол-во импульсов

void count_pulse1()

{

  detachInterrupt(4);
  counter1++;
  if (counter1 == 1)
    timeCount1 = millis();
  delay(5);
  attachInterrupt(4, count_pulse1, FALLING);

}

void MENU()
{
  lcd.setCursor(0, 0);// устанавливаем курсор в колонку 0, строку 0
  lcd.print("\xE0""o\xB2""po \xA8""o\xB6""a\xBB""o\xB3""a\xBF\xC4"); // печатаем первую строку
  lcd.setCursor(0, 1);// устанавливаем курсор в колонку 0, строку 1
  lcd.print("BHEC\xA5""TE \xE0""E\xA8""O\xA4\xA5""T"); // печатаем вторую строку
}

// включить насос

void cleaner_start()
{

  digitalWrite(PIN_RELAY, RELAY_ON); // включить
}
void BEZVODY() // считываем 10 вход датчик сухого хода
{
  vodaNET = digitalRead(netVoda);
  delay(200);
}
void knopkaPUSK() // считываем состояние кнопки пуск
{
  knopkaOn = digitalRead(knopka);
  delay(200);
}

void atomicInterrupt()  // выполнение атомарного блока
{
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  {
    // Атомарный доступ к переменной counter1:
    counter_copy = counter1;
 
  }
}

// выключить насос

void cleaner_stop()
{

  digitalWrite(PIN_RELAY, RELAY_OFF); // выключить
  delay(1000);
  counter1 = 0;
  time_run = 0;
  return MENU();
}
[/code]

 

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

Вот так сказать ищущим страждущим в помощь.Может чем поможет данный скетч)))

У меня вопрос к знатокам.Как мне сделать вывод на дисплей вывод в рублевом эквиваленте вот тут то-есть из переменной

counter_copy к примеру с вычислением дестых долей.Переменную с плавающей точкой создавал туда запихивал counter_copy и полученное пробовал арифметически вычислить с последующим выводом на ЖК  ну не получается  пишет внесено и 0.00 до тех пор пока реле не отключится 

090 lcd.print(time_run);

if (run_cleaner)
082   {
083     if (millis() - millis1 >= 100)
084     {
085       millis1 = millis();
086        counter1 = 0;
087       time_run = time_run - 1;
088       lcd.setCursor(0, 0);
089       lcd.print("BHECEHO = ");
090       lcd.print(time_run);
091       lcd.print(" P\xA9\xA0\x20"  );
092  

 

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

И как убрать это противное мерцание экрана которое дает команда очистка дисплея вот тут

054   if (counter_copy > 0 && (millis() - timeCount1) > timeAllPulse1) // ПЕЧАТАЕМ СКОЛЬКО ВНЕСЕНО
055   {
056     lcd.clear();
057     lcd.setCursor(2, 0);
058     lcd.print("BHECEHO=");
059     lcd.print(counter_copy);
060     lcd.print("P");

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Уберите lcd.clear();

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

andriano пишет:

Уберите lcd.clear();


Тогда при следующей итерации накладывается два изображения из menu и это

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

andriano пишет:

Уберите lcd.clear();


Можно же затереть пробелами

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

забавно.  Внесено рублей 

087       time_run = time_run - 1;
088       lcd.setCursor(0, 0);
089       lcd.print("BHECEHO = ");
090       lcd.print(time_run);
091       lcd.print(" P\xA9\xA0\x20"  );

и вывод времени работы насоса (time_run). 

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

Эта часть скетча была из чужого кода.Но хочу вывести именно уменьшение рублей.А время работы считалось фоново доля работы насоса.А уменьшение рублей не получается изображение на дисплее зависает

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

081 if (run_cleaner). Зачем мне в этом условном переходе присваивать к 0 значение получение в обработчике прерывания.Без присваивания counter1 всегда остаётся на с количеством внесённых рублей.Но почему у меня counter1 не хочет сбрасываться в 160 void cleaner_stop()

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Сергей Данилов пишет:
andriano пишет:

Уберите lcd.clear();

Тогда при следующей итерации накладывается два изображения из menu и это

ну так стирайте только то, что нужно, а не весь экран целиком.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну или так #84

Сергей Данилов
Offline
Зарегистрирован: 19.09.2019

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