Как исправить нажатия кнопок, которые больше не записываются после 10-15 нажатий кнопок?

У меня есть Arduino Uno с 5 кнопками (со светодиодами), включенными параллельно друг другу. Моя цель состоит в том, чтобы они загорались при нажатии, а также записывали и отмечали время, какая кнопка нажата как таковая:

Blue,2023/2/28,18:29:5

Это отображается на последовательном мониторе и сохраняется в файле CSV на SD-карте (32 ГБ без свободного места на нем, так что это не проблема хранения). Моя проблема в том, что когда я запускаю это, он работает отлично, пока я не нажму примерно 10-12 кнопок. В этот момент кнопки все еще будут светиться, но нажатия кнопок не записываются на последовательный монитор Arduino или на SD-карту. Я понятия не имею, почему это так.

Есть ли что-то в моем коде, что вызывает это? Как это исправить? Будем признательны за любую помощь!

#include <Wire.h>
#include "RTClib.h"
#include <SPI.h>
#include <SD.h>

RTC_DS3231 rtc; // Модуль часов реального времени
File dataFile;

// Значения светодиодов
int LEDValuesL[] = {LOW, LOW, LOW, LOW, LOW}; //
int LEDValues[] = {0,0,0,0,0}; //

// Состояние светодиодов и кнопок
int LEDStates[] = {LOW,LOW,LOW,LOW,LOW}; //
int ButtonStates[] = {0, 0, 0, 0, 0}; //
int lastButtonStates[] = {LOW, LOW, LOW, LOW, LOW}; //

// Контакты светодиода и кнопки
int buttonPins[] = {4, 2, A2, 8, 6}; // Кнопки чтения: Зеленая, Синяя, Белая, Желтая, Красная
int LEDPins[] = {5, 3, A3, 9, 7}; // Светодиоды управления: зеленый, синий, белый, желтый, красный

char *Colors_Array[] = {"Green,", "Blue,", "White,", "Yellow,", "Red,"} ; 
int CS = 10; // Контакт модуля карты MicroSD

unsigned long lastDebounceTime = 0;  // последний раз, когда выходной пин был переключен
unsigned long debounceDelay = 20;    // время устранения дребезга; увеличить, если выход мерцает

void setup() { 
  Serial.begin(9600); // 9600 бит в секунду
  Wire.begin();
  rtc.begin(); 
  SD.begin(CS);
  
  if(!SD.begin(CS)){ // Инициализация SD-карты
    Serial.print ("Could Not Initialize SD Card "); 
    // если возвращаемое значение ложно, что-то пошло не так
  } 

  if (SD.exists("datafile.csv")) { // Если этот файл существует на SD-карте, удалите его
    Serial.println("File exists.");
  if (SD.remove("datafile.csv") == true ) {
    Serial.println("Successfully removed file.");
  } else{
    Serial.println("Could not remove file"); 
  }}
 
  for (int i = 0; i<5 ; i++) { 
    pinMode(buttonPins[i], INPUT); // кнопки - это входы
    pinMode(LEDPins[i], OUTPUT); // светодиоды - это выходы
  }  
    dataFile.close(); 
  for (int i = 0; i<5 ; i++) {
    digitalWrite(LEDPins[i], LEDStates[i]); // Все светодиоды установлены на НИЗКИЙ уровень
  } 

    dataFile = SD.open("datafile.csv", FILE_WRITE); 
    if (dataFile){ 
      dataFile.println("Stress,Date,Time"); 
      dataFile.close();
    }
 }  

void loop() {  

  for (int i = 0; i<5 ; i++) { 
  int reading = digitalRead(buttonPins[i]); // чтение пинов
  
  if (reading != lastButtonStates[i]) {  
    lastDebounceTime = millis();
  } 

  if ((millis() - lastDebounceTime) > debounceDelay) {  
    if (reading != ButtonStates[i]) {
      ButtonStates[i] = reading;   
      LEDStates[i] = reading;
    }
  } 

  digitalWrite(LEDPins[i], LEDStates[i]);
  lastButtonStates[i] = reading;

  String dataString = ""; // Инициализируем строку, которая будет использоваться в качестве вывода
  DateTime now = rtc.now(); LEDValues[i] = digitalRead(LEDPins[i]); 

  if (LEDValues[i] != LEDValuesL[i]) { 
    if (LEDValues[i] == HIGH) {
    String year = String(now.year(), DEC);
    String month = String(now.month(), DEC);
    String day = String(now.day(), DEC);
    String hour = String(now.hour(), DEC);
    String min = String(now.minute(), DEC); 
    String sec = String(now.second(), DEC);
    
// Помещаем все строки даты и времени в одну строку
  dataFile = SD.open("datafile.csv", FILE_WRITE); 
  if ((millis() - lastDebounceTime) > debounceDelay) { 
    if (dataFile){
      String data = String(Colors_Array[i] + year + "/" + month + 
      "/" + day + "," + hour + ":" + min + ":" + sec);
      Serial.println(data);
      dataFile.println(data);
      dataFile.close();     
    }}}}   
  delay(20); 
}}

, 👍0

Обсуждение

отлаживать код... тестировать каждый участок кода отдельно, @jsotola

}}}} выделяется как больной палец... этого не должно быть видно ни в одном коде C++, особенно в коде, написанном новичком... это указывает на то, что код неправильно отформатирован, и в результате , склонный к ошибкам программирования... на самом деле ваш код беспорядочный, @jsotola

сделайте себе большое одолжение и избавьте себя от множества проблем, постоянно поддерживая правильный формат кода... это значительно облегчит отслеживание хода программы и снизит вероятность добавления строк кода не в том месте место, @jsotola

Используете ли вы внешние подтягивающие/подтягивающие резисторы на контактах кнопок? Вы также интенсивно используете класс String, что может привести к нестабильности., @6v6gt

вы делаете SD.begin(CS); два раза подряд... может это на что-то влияет... у меня нет возможности проверить, @jsotola

На скольких форумах вы это публиковали?, @Gil


1 ответ


0

С чего начать?

Начнем с самого "оскорбительного" строки кода. Все они начинаются с одного и того же ключевого слова: String.

Когда я удаляю код Модуля часов реального времени из вашего скетча и вставляю жестко закодированные значения для отсутствующих данных RTC, например, String year = String(2023, DEC);, в окне сообщений Arduino IDE, использующем версию IDE 1.8.9 на OSX, говорится:

Глобальные переменные используют 1278 байт (62%) динамической памяти, оставляя 770 байт для локальных переменных. Максимум 2048 байт.

Когда UNO достигает 75% использования динамической памяти, вы можете получить следующее сообщение:

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

После того как вы добавите свой код RTC, я могу представить, что ваше использование динамической памяти превысит отметку 75%.

Вам не нужно создавать новую строку для записи данных на SD-карту. Вы можете просто писать/печатать данные, как хотите, затем не забудьте закрыть файл. Например:

dataFile.print(F("Writing millis()="));
dataFile.println(millis());
dataFile.close();

У вас есть дополнительный dataFile.close(); в настройках.

Вот 2 скетча, которые выводят одно и то же сообщение на последовательный монитор, но их место для хранения программ и динамическая память меньше, используя char< массив /code> против объекта String.

// Использование объекта String.
// Sketch использует 2844 байта (8%) пространства для хранения программ.
// Глобальные переменные используют 214 байт (10%) динамической памяти
String TestStringString = "TestString";

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

void loop(){
  Serial.println(TestStringString);
}

VS

// Использование символьной строки.
// Sketch использует 1504 байта (4%) места для хранения программы.
// Глобальные переменные используют 198 байт (9%) динамической памяти
char TestCharString[10 + 1] = "TestString";

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

void loop(){
  Serial.println(TestCharString);
}
,

Обратите внимание, что вы можете написать `char TestCharString[] = "TestString"; и позволить компилятору считать байты., @Edgar Bonet