Управляемая вводом переменная счетчика спорадически увеличивается, если определенные функции вызываются в Setup()

Я использую ATTiny84 на специальной печатной плате спиннера (схематическое изображение ниже), вдохновленной этой инструкцией. Я программирую его с помощью карманного программатора SparkFun AVR, ATTinyCore и адаптера с пого-пином. Датчик Холла не используется. Приведенный ниже код просто устраняет дребезг ввода с кнопки, которая продвигает переменную режима. Если переменная режима равна 7, код мигает 8 светодиодами таким образом, что при вращении прядильщика появляется рисунок кувшинки. Это написано для пинмэппинга против часовой стрелки.

Код работает, пока я не включу в настройку функцию blipLED(). Его вызов приводит к тому, что переменная режима периодически циклически повторяется, увеличиваясь нажатием кнопки или (чаще) прикосновением к металлическому предмету в цепи. Кто-нибудь знает, почему это может быть?

В приведенном ниже коде blipLEDs() в setup() закомментированы.

Спасибо,

Франклин

Схема


/*
  LED test
*/

#ifdef PINMAPPING_CW
#error "Sketch was written for counterclockwise pin mapping!"
#endif

#include <EEPROM.h>

int LEDS[] = {10, 9, 8, 7, 6, 5, 4, 3};  // Порт А против часовой стрелки

//int LEDS[] = {0, 1, 2, 3, 4, 5, 7, 6}; // Порт А по часовой стрелке

// константы не изменятся. Они используются здесь для установки номеров контактов:
const int buttonPin = 0;   // номер вывода кнопки

// Переменные изменятся:
int buttonState = HIGH;             // текущее чтение с входного вывода
int mode = 0;                // текущий выбранный светодиод для мигания
int modes = 8;               // количество доступных светодиодов
int lastButtonState = HIGH;  // предыдущее чтение с вывода кнопки ввода

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

void setup() {

  for(int LED=0; LED<(sizeof(LEDS)/sizeof(int)); LED++){
    pinMode(LEDS[LED], OUTPUT);
  }
  pinMode(buttonPin, INPUT_PULLUP); //включить внутренний подтягивающий резистор

  // получить сохраненный режим из eeprom
  mode = EEPROM.read(0);
  if (mode >= modes) {
    mode = 0; // первый раз может быть очень большим
  }

  digitalWrite(LEDS[mode], HIGH); 
  
  // вызов приведенного ниже приводит к тому, что переменная режима периодически циклически повторяется, увеличиваясь нажатием кнопки или (чаще) прикосновением к металлическому предмету на схеме)
  //blipLEDs();

}

  
// функция цикла запускается снова и снова навсегда
void loop(){

  checkButton();
  if (mode == 7) {
    lilyPad();
  }

}

void lilyPad() {

  for(int LED=0; LED<(sizeof(LEDS)/sizeof(int)); LED++){
       digitalWrite(LEDS[LED], HIGH); 
       delay(1); 
       digitalWrite(LEDS[LED], LOW); 
  } 
  for(int LED=(sizeof(LEDS)/sizeof(int))-1; LED >= 0; LED--){
       digitalWrite(LEDS[LED], HIGH); 
       delay(1); 
       digitalWrite(LEDS[LED], LOW); 
  }     

}

void blipLEDs(){
  // что-то, чтобы показать, что мы живы
  for(int LED=0; LED<(sizeof(LEDS)/sizeof(int)); LED++){
    digitalWrite(LEDS[LED], HIGH); 
    delay(10); 
    digitalWrite(LEDS[LED], LOW); 
  } 
  for(int LED=sizeof(LEDS)/sizeof(int); LED>mode; LED--){
    digitalWrite(LEDS[LED], HIGH); 
    delay(10); 
    digitalWrite(LEDS[LED], LOW); 
  } 
  digitalWrite(LEDS[mode], HIGH);
}

void checkButton() {

  // прочитать состояние переключателя в локальную переменную:
  int currentButtonState = digitalRead(buttonPin);

  // проверяем, не нажали ли вы кнопку только что
  // (т.е. вход изменился с ВЫСОКОГО на НИЗКИЙ), и вы ждали достаточно долго
  // с момента последнего нажатия, чтобы игнорировать любой шум:

  // Если переключатель становится НИЗКИМ из-за шума или нажатия:
  if (currentButtonState != lastButtonState) {
    // сброс таймера устранения дребезга
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // каким бы ни было чтение, оно было там дольше, чем устранение дребезга
    // задержка, так что примите это как фактическое текущее состояние:

    // если состояние кнопки действительно изменилось (а не просто шум):
    if (currentButtonState != buttonState) {
      //устанавливаем состояние кнопки
      buttonState = currentButtonState;

      //режим увеличения только в том случае, если состояние новой кнопки НИЗКОЕ

      if (buttonState == LOW) {
        mode += 1;
        // если режим больше или равен общему количеству светодиодов, сбросить режим на 0
        if (mode >= modes) {
          mode = 0;
        }
        EEPROM.write(0, mode);
        blipLEDs();
      }
    }
  }
  // Сохраняем текущее чтение кнопки. В следующий раз в цикле это будет последнее состояние кнопки.
  lastButtonState = currentButtonState;
}

, 👍-1

Обсуждение

Я бы начал отлаживать эту проблему, пытаясь сделать максимально простую версию программы, а затем добавлять обратно код/функции до тех пор, пока она не перестанет работать — обычно это проясняет, в чем проблема. В этом случае, возможно, попробуйте обрезать программу до тех пор, пока, скажем, вы не сможете просто нажать кнопку, чтобы перейти в режим увеличения, а также показать текущий режим, просто зажигая светодиод (без вращения или eeprom) и посмотреть, работает ли это. Затем попробуйте добавить только сохранение/загрузку eeprom и посмотрите, что произойдет. Сообщите, что вы найдете!, @bigjosh


1 ответ


0

Второй цикл в blipLEDs() начинается с индекса "отклонение на единицу":

for(int LED=sizeof(LEDS)/sizeof(int); // ...

Поскольку он записывается на какой-то пин, это зависит от содержимого доступной памяти, на какой пин записывается. Это может быть контакт кнопки, поскольку его индекс равен "0".

,