Светодиодное кольцо с различными эффектами циклически

Мне нужна помощь с моим небольшим проектом. Я не знаю Arduino, поэтому использовал ChatGPT для написания кода. После нескольких часов тестирования я почти получил то, что мне нужно. Схема следующая: светодиодное кольцо, кнопка и потенциометр. Я использую потенциометр для управления яркостью, а кнопка переключается между различными режимами (эффектами). После попыток выяснить, что происходит, я думаю, что нашел проблему, но я не знаю, как ее исправить.

В коде ниже проблема в функции toggleMode(). Это выражение: mode = (mode + 1) % 3;, нарушает правильное выполнение. Все три эффекта могут быть циклически повторены только один раз, а затем он застревает на последнем эффекте. Есть ли какое-либо другое выражение, которое я могу использовать для вычисления «mode»? Вот полный код (также есть несколько строк для отладки, как вы можете видеть):

#include <FastLED.h>
#include <Arduino.h> // Включить основную библиотеку Arduino для поддержки последовательного порта

// Определяем количество светодиодов в светодиодном кольце
#define NUM_LEDS 24

// Определить пин данных
#define DATA_PIN 6

// Определить тип светодиода
#define LED_TYPE WS2812B

// Определить порядок цветов
#define COLOR_ORDER GRB

// Создаем массив объектов CRGB для хранения цветов каждого светодиода
CRGB leds[NUM_LEDS];

// Определить вывод для потенциометра
#define POTENTIOMETER_PIN A0

// Определить пин для кнопки
#define BUTTON_PIN 2

// Определим минимальное и максимальное значения яркости
#define MIN_BRIGHTNESS 0
#define MAX_BRIGHTNESS 255

// Переменная для хранения текущего режима (0: статическая радуга, 1: сверкание)
int mode = 0;


int previousButtonState = HIGH;

void setup() {
  // Инициализируем последовательную связь со скоростью 9600 бод
 Serial.begin(9600);

  mode = 2;
  // Инициализируем библиотеку FastLED
 FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
 
  // Установить начальную яркость
 FastLED.setBrightness(MAX_BRIGHTNESS / 2);
 
  // Установить вывод кнопки как вход с внутренним подтягивающим резистором
 pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  // Считать значение с потенциометра
 int potValue = analogRead(POTENTIOMETER_PIN);
 
  // Сопоставьте значение потенциометра с диапазоном яркости
 int brightness = map(potValue, 0, 1023, MIN_BRIGHTNESS, MAX_BRIGHTNESS);
 
  // Установить яркость светодиодного кольца
 FastLED.setBrightness(brightness);
 
  // Проверка состояния кнопки с устранением дребезга
 int buttonState = digitalRead(BUTTON_PIN);
 if (buttonState == LOW && previousButtonState == HIGH) {
    // Кнопка нажата в первый раз
    // Переключить режим при нажатии кнопки
 toggleMode();
  }
 
  previousButtonState = buttonState;

  // Вызвать соответствующую функцию в зависимости от режима
 if (mode == 0) {
 Serial.println("Mode: Rainbow");
 rainbow();
  } else if (mode == 1) {
 Serial.println("Mode: Sparkle");
 sparkle();
  } else if (mode == 2) {
 Serial.println("Mode: Static Rainbow Fade");
 staticRainbowFade();
  }
 
  // Отображение обновленных цветов светодиодов
 FastLED.show();
 
  // Задержка для управления скоростью цикла
 delay(30);
}

// Функция переключения режима между радугой и блеском
void toggleMode() {
  mode = (mode + 1) % 3;
 
    //Отладка кода
 Serial.print("Mode toggled: ");
 Serial.println(mode);
}

// Функция для создания эффекта радуги
void rainbow() {
  // Значение приращения оттенка определяет скорость радуги
 static uint8_t hue = 0;
 
  // Заполните светодиодное кольцо цветами
 for(int i = 0; i < NUM_LEDS; i++) {
 leds[i] = CHSV(hue + (i * 255 / NUM_LEDS), 255, 255);
  }

  // Увеличиваем значение оттенка для следующей итерации
  hue++;
}


// Функция для создания эффекта мерцания с плавным затуханием и изменением цвета
void sparkle() {
  // Вероятность загорания светодиода (регулируйте по мере необходимости)
 const float sparkleProbability = 0.02; // Отрегулируйте это значение, чтобы изменить плотность блеска
 
  // Проходим по каждому светодиоду
 for (int i = 0; i < NUM_LEDS; i++) {
    // Проверьте, должен ли светодиод загореться
 if (random(0, 1000) < (sparkleProbability * 1000)) {
      // Устанавливаем случайный цвет для мерцающего светодиода
      CRGB sparkleColor = CHSV(random(0, 255), 255, 255); // Случайный цвет
 leds[i] = sparkleColor;
    }
    // Выключить все светодиоды
 leds[i].fadeToBlackBy(10); // Отрегулируйте скорость затухания (более низкое значение затухает быстрее)
  }
}


// Функция для создания статического эффекта радуги с плавным появлением и исчезновением
void staticRainbowFade() {
  // Заполните светодиодное кольцо цветами радуги
 rainbow();

  // Постепенное появление
 for (int brightness = 0; brightness <= 255; brightness++) {
    // Установить яркость всех светодиодов
 FastLED.setBrightness(brightness);
 
    // Отображение обновленных цветов светодиодов
 FastLED.show();
 
    // Задержка для управления скоростью затухания (регулируйте по мере необходимости для достижения желаемого эффекта)
 delay(7); // Отрегулируйте это значение для увеличения скорости
  }
 
  // Задержка между появлением и исчезновением
 delay(1000); // Отрегулируйте это значение для задержки между появлением и исчезновением
 
  // Плавное затухание
 for (int brightness = 255; brightness >= 0; brightness--) {
    // Установить яркость всех светодиодов
 FastLED.setBrightness(brightness);
 
    // Отображение обновленных цветов светодиодов
 FastLED.show();
 
    // Задержка для управления скоростью затухания (регулируйте по мере необходимости для достижения желаемого эффекта)
 delay(7); // Отрегулируйте это значение для скорости затухания
  }
}

, 👍0

Обсуждение

просто увеличивайте режим mode++ ... затем устанавливайте на 0, если он достигает 3, @jsotola

Спасибо! Это выглядит гораздо более простым решением! Проблема в том, что я не знаю, куда это добавить... Я пытался добавить это в toggleMode(), но ничего не происходит., @Niki

@Niki Ты читал мой ответ? Замена одного рабочего кода на другой рабочий код не исправит твою ошибку, которая имеет не связанную с этим причину., @the busybee

@thebusybee Да, я проверил ссылку Nordic. Я думал, что пример Blinky из примеров Arduino SDK, но теперь я его нашел и проверю., @Niki

@Niki, это может тебе помочь... кое-что, что я написал в качестве демонстрации... https://wokwi.com/projects/362275278547275777, @jsotola


1 ответ


0

Строка изменения режима верна. jsotola упоминает альтернативную форму, например:

void toggleMode() {
  mode++;
  if (mode == 3) {
    mode = 0;
  }

  // Отладочный код
  Serial.print("Mode toggled: ");
  Serial.println(mode);
}

Но это не ошибка, и это не поможет.

Ошибка в том, что ваш staticRainbowFade() задерживается примерно на 4,5 секунды. Только после этого времени кнопка считывается.

Соответствующие части приведены здесь в сжатом виде:

void loop() {
  //...
  int buttonState = digitalRead(BUTTON_PIN);
  //...
  } else if (mode == 2) {
    Serial.println("Mode: Static Rainbow Fade");
    staticRainbowFade(); // <=== this takes about 4.5 seconds
  }
  // ...
}

void staticRainbowFade() {
  // ...
  for (int brightness = 0; brightness <= 255; brightness++) {
    // ...
    delay(7);
  }
 
  delay(1000);
 
  for (int brightness = 255; brightness >= 0; brightness--) {
    // ...
    delay(7);
  }
}

В качестве немедленного «решения» вы можете оставить кнопку ненажатой примерно на 5 секунд, а затем нажать ее примерно на 5 секунд. Это должно изменить режим.

Однако это всего лишь обходной путь. На самом деле вам следует переделать свой скетч в форму без задержки. Поскольку это требует некоторых усилий, я не представляю его здесь. Вы можете взглянуть на пример Blinky, который не использует delay(), чтобы получить представление. Другая тема для исследования — это "конечный автомат", который разделяет отдельную логику.

,

Или - как еще один обходной путь - также считывать кнопку в циклах for внутри staticRainbowFade(). И по крайней мере уменьшить задержку в 1 с между циклами for. Хотя переписать код без задержки гораздо чище, @chrisl

Я не знаю, что переписать. Мне просто нужно, чтобы это работало так, как я ожидаю. Я не программист (очевидно). Мне интересны многие вещи, и я не могу изучить все, даже если захочу. Вот почему я начал играть с кодированием ChatGPT, и я доволен результатами, но есть некоторые проблемы, которые ИИ не может решить (пока, надеюсь). Спасибо за ответ. Я продолжу читать и постараюсь исправить это., @Niki

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