ARDUINO Некорректная работа датчиков препятствий

DimonKh

✩✩✩✩✩✩✩
29 Янв 2022
5
0
Всем добрый вечер. Я сделал сортировщик монет, а для их фиксации использовал датчики препятствий. На lcd экран должно выводить:
1. Сумма;
2. Всего монет;
3. Номинал монеты и его количество.
Еще есть кнопка для сброса данных. Проблема в том, что монеты фиксируются датчиками в лучшем случае 1 из 3. Скетч писал сам и в первый раз.
C++:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <LCD_1602_RUS.h>

LCD_1602_RUS lcd(0x27, 20, 4);

float deneg = 0;
int monet = 0;
int programma = 0;
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;
int flag4 = 0;
int flag5 = 0;
int flag6 = 0;

void setup() {
  Serial.begin(9600);
  delay(80);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(10, INPUT);

  digitalWrite(2, HIGH);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(10, HIGH);

 
  String str1;
  str1 = "Кто-то";
 
  lcd.init();                     
  lcd.backlight();
  lcd.setCursor(6, 1);
  lcd.print("Привет");
  lcd.setCursor(10, 2);
  lcd.print(str1);
  delay(3000);
  lcd.clear();
    
}
void loop() {
  if (digitalRead(2) == 0) {
    Serial.println("It was a 10k");
    deneg = deneg + 0.10;
    monet = monet + 1;
    flag1 = flag1 + 1;
  delay(80);
}
  if (digitalRead(3) == 0) {
    Serial.println("It was a 1s");
    deneg = deneg + 1;
    monet = monet + 1;
    flag2 = flag2 + 1;
  delay(80);
}
  if (digitalRead(4) == 0) {
    Serial.println("It was a 2grn");
    deneg = deneg + 2;
    monet = monet + 1;
    flag3 = flag3 + 1;
  delay(80);
}
  if (digitalRead(5) == 0) {
    Serial.println("It was a 5grn");
    deneg = deneg + 5;
    monet = monet + 1;
    flag4 = flag4 + 1;
  delay(80);
}
  if (digitalRead(6) == 0) {
    Serial.println("It was a 50k");
    deneg = deneg + 0.50;
    monet = monet + 1;
    flag5 = flag5 + 1;
  delay(80);
}
  if (digitalRead(7) == 0) {
    Serial.println("It was a 10grn");
    deneg = deneg + 10;
    monet = monet + 1;
    flag6 = flag6 + 1;
  delay(80);
}
  if (digitalRead(8) == 0) {
    Serial.println("It was a 1g");
    deneg = deneg + 1;
    monet = monet + 1;
    flag2 = flag2 + 1;
  delay(80);
}
 
  String str2;
  str2 = "Всего монет:";
  lcd.setCursor(0, 0);
  lcd.print("Сумма= ");
  lcd.setCursor(8, 0);
  lcd.print(deneg);
  lcd.setCursor(0, 1);
  lcd.print(str2);
  lcd.setCursor(14, 1);
  lcd.print(monet);

  lcd.setCursor(0,2);
  lcd.print("0.1 0.5  1  2  5  10");
  lcd.setCursor(1, 3);
  lcd.print(flag1);
  lcd.setCursor(9, 3);
  lcd.print(flag2);
  lcd.setCursor(12, 3);
  lcd.print(flag3);
  lcd.setCursor(15, 3);
  lcd.print(flag4);
  lcd.setCursor(5, 3);
  lcd.print(flag5);
  lcd.setCursor(18, 3);
  lcd.print(flag6);


  if (digitalRead(10) == 0) {
    Serial.println("Sbros");
    programma = 1;
    deneg = 0;
    monet = 0;
    flag1 = 0;
    flag2 = 0;
    flag3 = 0;
    flag4 = 0;
    flag5 = 0;
    flag6 = 0;
    
    String str3;
    str3 = "Сброс данных";
    
    lcd.clear();
    lcd.setCursor(4, 1);
    lcd.print(str3);
    delay(1000);
    lcd.clear();
    programma = 0;
  }

  if (programma == 0) {
    String str2;
    str2 = "Всего монет:";

    lcd.setCursor(0, 0);
  lcd.print("Сумма= ");
  lcd.setCursor(8, 0);
  lcd.print(deneg);
  lcd.setCursor(0, 1);
  lcd.print(str2);
  lcd.setCursor(14, 1);
  lcd.print(monet);

  lcd.setCursor(0,2);
  lcd.print("0.1 0.5  1  2  5  10");
  lcd.setCursor(1, 3);
  lcd.print(flag1);
  lcd.setCursor(9, 3);
  lcd.print(flag2);
  lcd.setCursor(12, 3);
  lcd.print(flag3);
  lcd.setCursor(15, 3);
  lcd.print(flag4);
  lcd.setCursor(5, 3);
  lcd.print(flag5);
  lcd.setCursor(18, 3);
  lcd.print(flag6);
  }
}
Но если загрузить этот скетч (без вывода на lcd экран, подсчета суммы и количества монет), и наблюдать через монитор порта, то все монеты фиксируются идеально.
C++:
void setup() {
  Serial.begin(9600);
  delay(80);
}
void loop() {
  if (digitalRead(2) == 0) {
    Serial.println("It was a 10k");
  delay(80);
}
  if (digitalRead(3) == 0) {
    Serial.println("It was a 1s");
  delay(80);
}
  if (digitalRead(4) == 0) {
    Serial.println("It was a 2grn");
  delay(80);
}
  if (digitalRead(5) == 0) {
    Serial.println("It was a 5grn");
  delay(80);
}
  if (digitalRead(6) == 0) {
    Serial.println("It was a 50k");
  delay(80);
}
  if (digitalRead(7) == 0) {
    Serial.println("It was a 10grn");
  delay(80);
}
  if (digitalRead(8) == 0) {
    Serial.println("It was a 1g");
  delay(80);
}
Буду очень признателен помощи в решении этой проблемы.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Изучайте прерывания. Очевидно, что пока ардуина занята выводом на экран какой то информации монета и проскакивает. Значит надо уменьшить время вывода. Еще что плохо. постоянные повторы
lcd.setCursor(..
lcd.print(flag..
За один раз сформируйте строку и выводите целиком.
Ну и подумайте как избавиться от delay(80). Они для чего ?
 

DimonKh

✩✩✩✩✩✩✩
29 Янв 2022
5
0
Спасибо за ответ. Если я не использовал delay(80), то одна монета при проходе над датчиком могла зафиксироваться 2 или 3 раза.
А как в одной строке реализовать вывод?
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Получается так: если digitalRead( ) == 0 - то значит монета есть. есди digitalRead(..) == 1 то монеты нет. Следует ловить не 0, а момент перехода с 1 на 0
Для новичка самое просто использовать строки, что то типа
String s1=String(flag1)+" "+String(flag2)+" "+String(flag3);
И далее
lcd.setCursor(1, 3);
lcd.print(s1);

Но можно еще объявить массив символов и формировать его с нужными данным. У Алекса есть урок по этой теме - найдите уж сами. Способ с массивом быстрее чем со строками, используется функция cformat
 

Normalek

★✩✩✩✩✩✩
6 Авг 2021
140
39
так же можно юзать snprintf, strcat, они еще быстрей, отталкиваться от с++ это относится к работы со строками(просто не видел что там Александр рассказывал)
 

DimonKh

✩✩✩✩✩✩✩
29 Янв 2022
5
0
Сделал прерывания, теперь все делается быстро: и фиксация, и вывод на экран. Только теперь одна монета может фиксироваться 10-15 раз за проход. В предыдущей версии с этим помог delay. Сейчас попробовал использовать таймер GyverTimer, но результата нет. Я видать не разобрался как им пользоваться.
C++:
#include <PinChangeInterrupt.h>
#include <PinChangeInterruptBoards.h>
#include <PinChangeInterruptPins.h>
#include <PinChangeInterruptSettings.h>

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <LCD_1602_RUS.h>

LCD_1602_RUS lcd(0x27, 20, 4);


float deneg = 0;
int monet = 0;
int programma = 0;
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;
int flag4 = 0;
int flag5 = 0;
int flag6 = 0;

void setup() {
  Serial.begin(9600);

 
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(10, INPUT);

  digitalWrite(2, HIGH);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(10, HIGH);

  attachInterrupt(0, function1, FALLING);
  attachInterrupt(1, function2, FALLING);
  attachPCINT(20, function3, FALLING);
  attachPCINT(21, function4, FALLING);
  attachPCINT(22, function5, FALLING);
  attachPCINT(23, function6, FALLING);
  attachPCINT(0, function7, FALLING);
 
  String str1;
  str1 = "Кто-то";
  lcd.init();                     
  lcd.backlight();
  lcd.setCursor(6, 1); lcd.print("Привет");
  lcd.setCursor(10, 2); lcd.print(str1);
  delay(3000);
  lcd.clear();
    
}
void loop() {
 
  String str2;
  str2 = "Всего монет:";
  lcd.setCursor(0, 0); lcd.print("Сумма= ");
  lcd.setCursor(8, 0); lcd.print(deneg);
  lcd.setCursor(0, 1); lcd.print(str2);
  lcd.setCursor(14, 1); lcd.print(monet);

  lcd.setCursor(0,2); lcd.print("0.1 0.5  1  2  5  10");
  lcd.setCursor(1, 3); lcd.print(flag1);
  lcd.setCursor(9, 3); lcd.print(flag2);
  lcd.setCursor(12, 3); lcd.print(flag3);
  lcd.setCursor(15, 3); lcd.print(flag4);
  lcd.setCursor(5, 3); lcd.print(flag5);
  lcd.setCursor(18, 3); lcd.print(flag6);


  if (digitalRead(10) == 0) {
    Serial.println("Sbros");
    programma = 1;
    deneg = 0;
    monet = 0;
    flag1 = 0;
    flag2 = 0;
    flag3 = 0;
    flag4 = 0;
    flag5 = 0;
    flag6 = 0;
    
    String str3;
    str3 = "Сброс данных";
    lcd.clear();
    lcd.setCursor(4, 1); lcd.print(str3);
    delay(1000);
    lcd.clear();
    programma = 0;
  }

  if (programma == 0) {
    String str2;
    str2 = "Всего монет:";

  lcd.setCursor(0, 0); lcd.print("Сумма= ");
  lcd.setCursor(8, 0); lcd.print(deneg);
  lcd.setCursor(0, 1); lcd.print(str2);
  lcd.setCursor(14, 1); lcd.print(monet);

  lcd.setCursor(0,2); lcd.print("0.1 0.5  1  2  5  10");
  lcd.setCursor(1, 3); lcd.print(flag1);
  lcd.setCursor(9, 3); lcd.print(flag2);
  lcd.setCursor(12, 3); lcd.print(flag3);
  lcd.setCursor(15, 3); lcd.print(flag4);
  lcd.setCursor(5, 3); lcd.print(flag5);
  lcd.setCursor(18, 3); lcd.print(flag6);
  }
}

void function1() {
    Serial.println("It was a 10k");
    deneg = deneg + 0.10;
    monet = monet + 1;
    flag1 = flag1 + 1;
    
  }

void function2() {
    Serial.println("It was a 1s");
    deneg = deneg + 1;
    monet = monet + 1;
    flag2 = flag2 + 1;
    
  }

void function3() {
    Serial.println("It was a 2grn");
    deneg = deneg + 2;
    monet = monet + 1;
    flag3 = flag3 + 1;
    
  }

void function4() {
    Serial.println("It was a 5grn");
    deneg = deneg + 5;
    monet = monet + 1;
    flag4 = flag4 + 1;
    
  }

void function5() {
    Serial.println("It was a 50k");
    deneg = deneg + 0.50;
    monet = monet + 1;
    flag5 = flag5 + 1;
    
  }

void function6() {
    Serial.println("It was a 10grn");
    deneg = deneg + 10;
    monet = monet + 1;
    flag6 = flag6 + 1;
  
  }

void function7() {
    Serial.println("It was a 1g");
    deneg = deneg + 1;
    monet = monet + 1;
    flag2 = flag2 + 1;
  
  }
Может кто знает как исправить фиксацию?
 

DimonKh

✩✩✩✩✩✩✩
29 Янв 2022
5
0
Serial могу удалить, он не важен.
А есть какой-то образец таймера?
 

bort707

★★★★★★✩
21 Сен 2020
3,066
914
А есть какой-то образец таймера?
в начале периода запомнить микрос, в конце прочитать новое значение и посчитать разницу...
Миллисом пользоваться умеете? - микрос точно так же, только в 1000 раз быстрее
 

DimonKh

✩✩✩✩✩✩✩
29 Янв 2022
5
0
C++:
// переменная хранения времени (unsigned long)
uint32_t myTimer1;
int period = 500;
void setup() {}
void loop() {
  if (micros() - myTimer1 >= period) {   // ищем разницу (500 мс)
    myTimer1 += period;                  // сброс таймера
    // выполнить действие
  }
}
Вот такой таймер мне нужен?
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
476
137
Сделал прерывания... Только теперь одна монета может фиксироваться 10-15 раз за проход.
При прерываниях в случае отсутствия дребезга сигнала и корректной работы библиотеки 10 - 15 раз за проход быть не может.Сначала убедитесь в отсутствии дребезга. И в целом, по хорошему, надо расписать допустимые временные параметры (мин - мах). Длительность присутствия монеты, пауза между монетами, могут ли монеты одновременно быть монеты разных номиналов.
Как вы определяете 10 -15 раз? Вы получаете 10 - 15 сообщений типа Serial.println("It was a 10grn");