Черные ящики появляются во второй строке моего ЖК-дисплея

lcd

черные квадратики на ЖКИ есть только в обоих рядах и появляются только когда я прикрепляю датчик ЧСС к телу и моргаю с задержкой около 2 секунд и у меня контраст и проводка идеальные, подсветка моего ЖКИ на...

но когда я прикрепляю датчик сердечного ритма, они повторяются в течение четырех или пяти секунд, и черные ящики тоже исчезают, остается только подсветка... исчезновение черных ящиков но тогда почему черные ящики появляются??? пожалуйста, помогите мне это код, схемы и изображение того, как это выглядит.

    #include <LiquidCrystal.h>
#define IN1  8
#define IN2  9
#define IN3  10
#define IN4  7                                        
int Steps = 4096; //4096 или 768
int cstep = 10;
const int rs = 7, en = 8, d4 = 3, d5 = 4, d6 = 5, d7 = 6;
const int buzzer = 2;
LiquidCrystal lcd(7, 8, 3, 4, 5, 6);

int pulsePin = A3;                 // Фиолетовый провод датчика пульса, подключенный к аналоговому контакту A0
int blinkPin = 13;                // вывод для мигания светодиода при каждом ударе
// Изменчивые переменные, используемые в подпрограмме обслуживания прерывания!
volatile int BPM;                   // целое число, которое содержит необработанный аналог в 0. обновляется каждые 2 мс
volatile int Signal;                // содержит входящие необработанные данные
volatile int IBI = 600;             // int, который содержит временной интервал между ударами! Сеять надо!
volatile boolean Pulse = false;     // «Истинно», когда обнаружено живое сердцебиение пользователя. «Ложь», если это не «живой бит».
volatile boolean QS = false;        // становится истинным, когда Arduoino находит бит.

static boolean serialVisual = true;   // По умолчанию установлено значение «false». Снова установите значение «true», чтобы увидеть визуальный пульс Arduino Serial Monitor ASCII.

volatile int rate[10];                      // массив для хранения последних десяти значений IBI
volatile unsigned long sampleCounter = 0;          // используется для определения времени импульса
volatile unsigned long lastBeatTime = 0;           // используется для поиска IBI
volatile int P = 512;                      // используется для нахождения пика в пульсовой волне, с затравкой
volatile int T = 512;                     // используется для поиска впадины в пульсовой волне, засеянной
volatile int thresh = 525;                // используется для нахождения мгновенного момента сердцебиения, засеяно
volatile int amp = 100;                   // используется для хранения амплитуды импульсного сигнала, заполненного
volatile boolean firstBeat = true;        // используется для заполнения массива скорости, поэтому мы запускаем с разумным BPM
volatile boolean secondBeat = false;      // используется для заполнения массива скорости, поэтому мы запускаем с разумным BPM

void setup()
{
   pinMode(IN1, OUTPUT); 
  pinMode(IN2, OUTPUT); 
  pinMode(IN3, OUTPUT); 
  pinMode(IN4, OUTPUT); 
   pinMode(buzzer,OUTPUT);
  pinMode(blinkPin,OUTPUT);         // вывод, который будет мигать в такт вашему сердцу!
  Serial.begin(115200);             // мы согласны говорить быстро!
  interruptSetup();                 // настраивает чтение сигнала датчика пульса каждые 2 мс
                                    // ЕСЛИ ВЫ ПОДАЕТЕ ПИТАНИЕ НА ДАТЧИК ИМПУЛЬСОВ ПРИ НАПРЯЖЕНИИ МЕНЬШЕ, ЧЕМ НАПРЯЖЕНИЕ НА ПЛАТЕ,
                                    // ОТКОММЕНТИРУЕМ СЛЕДУЮЩУЮ СТРОКУ И ПОДАЕМ ЭТО НАПРЯЖЕНИЕ НА ВЫВОД A-REF
                                    // аналоговая ссылка (ВНЕШНЯЯ);
 lcd.begin(16, 2);
 lcd.clear();
}


// Где происходят чудеса
void loop()
{
   serialOutput();  
    lcd.print("DEVICE-STATE");
     lcd.setCursor(1,1);
     lcd.print("UPDATING... ");
     lcd.setCursor(5,1);
     delay(3000);
     lcd.clear();
  if (QS == true) // Было найдено сердцебиение
    {     
      // BPM и IBI определены
      // Quantified Self "QS" true, когда arduino находит сердцебиение
      serialOutputWhenBeatHappens(); // Случился бит, выведите его в последовательный порт.
      QS = false; // сброс флага Quantified Self для следующего раза
      state(); 
      buzer();
      inject(); 
    }

  delay(20); // сделать перерыв
}


void interruptSetup()
{     
  // Инициализирует Timer2 для создания прерывания каждые 2 мс.
  TCCR2A = 0x02;     // ОТКЛЮЧИТЬ ШИМ НА ЦИФРОВЫХ ВЫВОДАХ 3 И 11 И ПЕРЕХОДИТЬ В РЕЖИМ CTC
  TCCR2B = 0x06;     // НЕ ПРИНИМАТЬ СРАВНЕНИЕ, 256 PRESCALER
  OCR2A = 0X7C;      // УСТАНОВИМ НАЧАЛЬНУЮ ЧАСТЬ СЧЁТЧИКА НА 124 ДЛЯ ЧАСТОТЫ ВЫБОРКИ 500 Гц
  TIMSK2 = 0x02;     // ВКЛЮЧАЕМ ПРЕРЫВАНИЕ ПРИ СОВПАДЕНИИ МЕЖДУ TIMER2 И OCR2A
  sei();             // УБЕДИТЕСЬ, ЧТО ГЛОБАЛЬНЫЕ ПРЕРЫВАНИЯ РАЗРЕШЕНЫ
} 

void serialOutput()
{   // Решаем, как выводить серийный номер.
 if (serialVisual == true)
  {  
     arduinoSerialMonitorVisual('-', Signal);   // переходит к функции, которая делает Serial Monitor Visualizer
  } 
 else
  {
      sendDataToSerial('S', Signal);     // переходит к функции sendDataToSerial
   }        
}

//Профилактика сердечных приступов

void serialOutputWhenBeatHappens()
{    
 if (serialVisual == true) // Код для работы визуализатора последовательного монитора
   {            
     Serial.print(" Heart-Beat Found ");  // Безумие искусства ASCII
     Serial.print("BPM: ");
     Serial.println(BPM);
     lcd.print("Heart-Beat Found ");
     lcd.setCursor(1,1);
     lcd.print("BPM: ");
     lcd.setCursor(5,1);
     lcd.print(BPM);
     delay(3000);
     lcd.clear();
   }
 else
   {
     sendDataToSerial('B',BPM);   // отправляем частоту сердечных сокращений с префиксом «B»
     sendDataToSerial('Q',IBI);   // отправляем время между ударами с префиксом 'Q'
   }   
}

void arduinoSerialMonitorVisual(char symbol, int data )
{    
  const int sensorMin = 0;      // минимум сенсора, обнаруженный экспериментально
  const int sensorMax = 1024;    // максимум сенсора, обнаруженный экспериментально
  int sensorReading = data; // сопоставляем диапазон датчика с диапазоном из 12 вариантов:
  int range = map(sensorReading, sensorMin, sensorMax, 0, 11);
  // делаем что-то другое в зависимости от
  // значение диапазона:
}


void sendDataToSerial(char symbol, int data )
{
   Serial.print(symbol);
   Serial.println(data);                
}

ISR(TIMER2_COMPA_vect) // срабатывает, когда Timer2 считает до 124
{  
  cli();                                      // отключаем прерывания, пока делаем это
  Signal = analogRead(pulsePin);              // чтение датчика пульса
  sampleCounter += 2;                         // отслеживать время в миллисекундах с помощью этой переменной
  int N = sampleCounter - lastBeatTime;       // отслеживаем время с момента последнего удара, чтобы избежать шума
                                              // найти пик и впадину пульсовой волны
  if(Signal < thresh && N > (IBI/5)*3) // избегаем дихротического шума, ожидая 3/5 последнего IBI
    {      
      if (Signal < T) // T - впадина
      {                        
        T = Signal; // отслеживаем самую низкую точку пульсовой волны
      }
    }

  if(Signal > thresh && Signal > P)
    {          // условие thresh помогает избежать шума
      P = Signal;                             // P — пик
    }                                        // отслеживаем наивысшую точку пульсовой волны

  // ТЕПЕРЬ ПРИШЛО ВРЕМЯ УЗНАТЬ БИЕНИЕ СЕРДЦА
  // значение сигнала возрастает каждый раз, когда есть импульс
  if (N > 250)
  {                                   // избегаем высокочастотного шума
    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) )
      {        
        Pulse = true;                               // устанавливаем флаг Pulse, когда мы думаем, что есть пульс
        digitalWrite(blinkPin,HIGH);                // включить светодиод на контакте 13
        IBI = sampleCounter - lastBeatTime;         // измеряем время между ударами в мс
        lastBeatTime = sampleCounter;               // отслеживать время следующего импульса

        if(secondBeat)
        {                        // если это вторая доля, if secondBeat == TRUE
          secondBeat = false;                  // очистить флаг secondBeat
          for(int i=0; i<=9; i++) // начальное значение промежуточной суммы для получения реалистичного BPM при запуске
          {             
            rate[i] = IBI;                      
          }
        }

        if(firstBeat) // если бит найден впервые, if firstBeat == TRUE
        {                         
          firstBeat = false;                   // очистить флаг firstBeat
          secondBeat = true;                   // устанавливаем второй флаг долей
          sei();                               // снова разрешаем прерывания
          return;                              // Значение IBI ненадежно, поэтому отбрасываем его
        }   
      // сохраняем промежуточный итог последних 10 значений IBI
      word runningTotal = 0;                  // очищаем переменную runningTotal

      for(int i=0; i<=8; i++)
        {                // сдвигаем данные в массиве ставок
          rate[i] = rate[i+1];                  // и удалить самое старое значение IBI
          runningTotal += rate[i];              // суммируем 9 самых старых значений IBI
        }

//Профилактика сердечных приступов
rate[9] = IBI;                          // добавляем последний IBI в массив ставок
      runningTotal += rate[9];                // добавить последний IBI в runningTotal
      runningTotal /= 10;                     // среднее значение последних 10 значений IBI
      BPM = 60000/runningTotal;               // сколько ударов может уместиться в минуту? это БПМ!
      QS = true;                              // установить флаг Quantified Self
      // ФЛАГ QS НЕ СНЯТ ВНУТРИ ЭТОЙ ISR
    }                       
  }

  if (Signal < thresh && Pulse == true)
    {   // когда значения уменьшаются, бит закончен
      digitalWrite(blinkPin,LOW);            // выключаем светодиод на контакте 13
      Pulse = false;                         // сбрасываем флаг Pulse, чтобы мы могли сделать это снова
      amp = P - T;                           // получаем амплитуду пульсовой волны
      thresh = amp/2 + T;                    // устанавливаем порог на 50% от амплитуды
      P = thresh;                            // сбросить их для следующего раза
      T = thresh;
    }

  if (N > 2500)
    {                           // если 2,5 секунды проходят без такта
      thresh = 512;                          // устанавливаем порог по умолчанию
      P = 512;                               // установить P по умолчанию
      T = 512;                               // устанавливаем Т по умолчанию
      lastBeatTime = sampleCounter;          // обновить lastBeatTime
      firstBeat = true;                      // установите их, чтобы избежать шума
      secondBeat = false;                    // когда мы получим сердцебиение
    }

  sei();                                   // разрешить прерывания, когда закончите!
}// конец isr
void buzer(){
  // опасная ситуация или нажата кнопка
  if (BPM < 60 )
   {
     lcd.print("hypotension");
     lcd.setCursor(1,1);
     lcd.print("BPM: ");
     lcd.setCursor(5,1);
     lcd.print(BPM);
     delay(3000);
     lcd.clear();
   digitalWrite(buzzer,HIGH);
    delay(500);             
   digitalWrite(buzzer,LOW); 
    delay(500);  

}

}
void inject()
{
   if (BPM>60)
   {
     lcd.print("Hypertention");
     lcd.setCursor(1,1);
     lcd.print("BPM: ");
     lcd.setCursor(5,1);
     lcd.print(BPM);
     delay(5000);
     lcd.clear();
  for(int x=0;x<Steps;x++)
  {
   switch(cstep)
  {
   case 0:
     digitalWrite(IN1, LOW); 
     digitalWrite(IN2, LOW);
     digitalWrite(IN3, LOW);
     digitalWrite(IN4, HIGH);
   break; 
   case 1:
     digitalWrite(IN1, LOW); 
     digitalWrite(IN2, LOW);
     digitalWrite(IN3, HIGH);
     digitalWrite(IN4, HIGH);
   break; 
   case 2:
     digitalWrite(IN1, LOW); 
     digitalWrite(IN2, LOW);
     digitalWrite(IN3, HIGH);
     digitalWrite(IN4, LOW);
   break; 
   case 3:
     digitalWrite(IN1, LOW); 
     digitalWrite(IN2, HIGH);
     digitalWrite(IN3, HIGH);
     digitalWrite(IN4, LOW);
   break; 
   case 4:
     digitalWrite(IN1, LOW); 
     digitalWrite(IN2, HIGH);
     digitalWrite(IN3, LOW);
     digitalWrite(IN4, LOW);
   break; 
   case 5:
     digitalWrite(IN1, HIGH); 
     digitalWrite(IN2, HIGH);
     digitalWrite(IN3, LOW);
     digitalWrite(IN4, LOW);
   break; 
     case 6:
     digitalWrite(IN1, HIGH); 
     digitalWrite(IN2, LOW);
     digitalWrite(IN3, LOW);
     digitalWrite(IN4, LOW);
   break; 
   case 7:
     digitalWrite(IN1, HIGH); 
     digitalWrite(IN2, LOW);
     digitalWrite(IN3, LOW);
     digitalWrite(IN4, HIGH);
   break; 
   default:
     digitalWrite(IN1, LOW); 
     digitalWrite(IN2, LOW);
     digitalWrite(IN3, LOW);
     digitalWrite(IN4, LOW);
   break; 
  }

   cstep=cstep+1;
   if(cstep==8)
     {cstep=0;}

  delayMicroseconds(2500);

   }
}
}
void state()
{
  if (BPM > 60 & BPM < 74){
   lcd.print("VERY-GOOD");
     lcd.setCursor(1,1);
     lcd.print("BPM: ");
     lcd.setCursor(5,1);
     lcd.print(BPM);
     delay(3000);
     lcd.clear();
  }
}

это схема моего проекта

, 👍-1

Обсуждение

Вращайте банк 10K, пока ящики не исчезнут., @Dougie

Начните с комментирования кода, связанного с датчиком сердцебиения, и замените его тривиальной функцией, которая возвращает постоянный результат — в пределах диапазона, за пределами диапазона, независимо от того, что требуется для проверки частей вашего кода ЖК-дисплея. Тогда попробуйте, с прикрепленным к вам датчиком и без него. Это поможет выяснить, видите ли вы проблемы с электричеством или с программным обеспечением., @JRobert

Являются ли эти черные ящики настоящими персонажами со всеми включенными пикселями? Не могли бы вы добавить изображение? Ваш исходный код слишком велик для поиска ошибок, пожалуйста, уменьшите его до минимально воспроизводимого примера., @the busybee

@thebusybee Я добавил картинку того, как это выглядит...., @NaveenVelusamy

Хороший. Теперь уменьшите свой код, пожалуйста. Тогда не забудь опубликовать., @the busybee

@thebusybee Я не знаю, как минимизировать код, поскольку я не эксперт в этом ... На самом деле я воспользовался помощью внешнего источника, который помог мне написать код ..., @NaveenVelusamy

Это довольно просто: удалите все строки, которые не нужны для воспроизведения проблемы. ;-), @the busybee

@thebusybee это может занять много времени, поэтому, пожалуйста, подождите... А пока тот, кто может ответить, может помочь мне., @NaveenVelusamy

Обеспечьте правильные соединения в вашей установке. Клей НЕ является хорошим проводником, а макетные платы известны тем, что они периодически дают сбои. Проверьте, что движется, когда вы подаете давление на датчик, возможно, используйте другие макеты/прямые соединения. «Коробки» из-за неправильной настройки горшка. Настройте горшок и проверьте результаты., @smajli

Это был плохой припой, @NaveenVelusamy


1 ответ


Лучший ответ:

0

Я думаю, это было из-за того, что заряд батареи был меньше, и, следовательно, его контрастность была меньше, и поэтому я не мог видеть отображаемые символы...

Спасибо всем, кто помог мне с этой проблемой, и благодаря переполнению стека

Теперь он работает, так как я использовал другой аккумулятор

,