Skip to content

Instantly share code, notes, and snippets.

@npdgm
Created March 28, 2023 18:19
Show Gist options
  • Select an option

  • Save npdgm/2bec3b30c0933d09af83c4bd1efc7e18 to your computer and use it in GitHub Desktop.

Select an option

Save npdgm/2bec3b30c0933d09af83c4bd1efc7e18 to your computer and use it in GitHub Desktop.
Test : Arduino on ESP32 ; I2S output audio output (radio streaming) ; WS2812 LEDs driven by I2S method
#include <Arduino.h>
#include <WiFi.h>
#include <Audio.h>
#include <NeoPixelBus.h>
#include <NeoPixelAnimator.h>
#define I2S_DOUT 27
#define I2S_BCLK 32
#define I2S_LRC 33
#define LED_PIN 4
#define LED_COUNT 13
#define LED_SATURATION 128
String ssid = "*******";
String password = "*******";
Audio audio;
//NeoPixelBus<NeoGrbFeature, NeoEsp32BitBangWs2812xMethod> strip(LED_COUNT, LED_PIN);
//NeoPixelBus<NeoGrbFeature, NeoEsp32I2s0Ws2812xMethod> strip(LED_COUNT, LED_PIN);
NeoPixelBus<NeoGrbFeature, NeoEsp32I2s1Ws2812xMethod> strip(LED_COUNT, LED_PIN);
//NeoPixelBus<NeoGrbFeature, NeoEsp32I2sNWs2812xMethod> strip(LED_COUNT, LED_PIN);
RgbColor red(LED_SATURATION, 0, 0);
RgbColor green(0, LED_SATURATION, 0);
RgbColor blue(0, 0, LED_SATURATION);
RgbColor white(LED_SATURATION);
RgbColor black(0);
const uint16_t PixelCount = LED_COUNT - 1;
const uint16_t AnimCount = PixelCount / 5 * 2 + 4;
const uint16_t PixelFadeDuration = 800;
const uint16_t NextPixelMoveDuration = 1000 / PixelCount;
NeoGamma<NeoGammaTableMethod> colorGamma;
struct MyAnimationState {
RgbColor StartingColor;
RgbColor EndingColor;
uint16_t IndexPixel;
};
NeoPixelAnimator animations(AnimCount);
MyAnimationState animationState[AnimCount];
uint16_t frontPixel = 0;
RgbColor frontColor;
void SetRandomSeed() {
uint32_t seed;
seed = analogRead(0);
delay(1);
for (int shifts = 3; shifts < 31; shifts += 3) {
seed ^= analogRead(0) << shifts;
delay(1);
}
randomSeed(seed);
}
void FadeOutAnimUpdate(const AnimationParam& param) {
// this gets called for each animation on every time step
// progress will start at 0.0 and end at 1.0
// we use the blend function on the RgbColor to mix
// color based on the progress given to us in the animation
RgbColor updatedColor = RgbColor::LinearBlend(
animationState[param.index].StartingColor,
animationState[param.index].EndingColor,
param.progress);
// apply the color to the strip
strip.SetPixelColor(animationState[param.index].IndexPixel,
colorGamma.Correct(updatedColor));
}
void LoopAnimUpdate(const AnimationParam& param) {
if (param.state == AnimationState_Completed) {
// done, time to restart this position tracking animation/timer
animations.RestartAnimation(param.index);
// pick the next pixel inline to start animating
frontPixel = (frontPixel + 1) % PixelCount; // increment and wrap
if (frontPixel == 0) {
// we looped, lets pick a new front color
frontColor = HslColor(random(360) / 360.0f, 1.0f, 0.5f);
}
uint16_t indexAnim;
// do we have an animation available to use to animate the next front pixel?
// if you see skipping, then either you are going to fast or need to increase
// the number of animation channels
if (animations.NextAvailableAnimation(&indexAnim, 1)) {
animationState[indexAnim].StartingColor = frontColor;
animationState[indexAnim].EndingColor = RgbColor(0, 0, 0);
animationState[indexAnim].IndexPixel = frontPixel + 1;
animations.StartAnimation(indexAnim, PixelFadeDuration, FadeOutAnimUpdate);
}
}
}
void setup() {
Serial.begin(115200);
log_i("Total heap: %d", ESP.getHeapSize());
log_i("Free heap: %d", ESP.getFreeHeap());
log_i("Total PSRAM: %d", ESP.getPsramSize());
log_i("Free PSRAM: %d", ESP.getFreePsram());
SetRandomSeed();
strip.Begin();
strip.ClearTo(black);
strip.SetPixelColor(0, red);
strip.Show();
WiFi.disconnect();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
log_i("Connecting to WiFi...");
while (WiFi.status() != WL_CONNECTED) {
strip.SetPixelColor(0, blue);
strip.Show();
delay(1500);
}
strip.SetPixelColor(0, green);
strip.Show();
log_i("WiFi connected!");
pinMode(25, OUTPUT);
digitalWrite(25, LOW);
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.forceMono(true);
audio.setVolume(21);
digitalWrite(25, HIGH);
//audio.connecttohost("http://icecast.radiofrance.fr/fip-lofi.aac"); // 32k aac
//audio.connecttohost("http://icecast.radiofrance.fr/fip-midfi.aac"); // 96k aac
audio.connecttohost("http://icecast.radiofrance.fr/fip-midfi.mp3"); // 128k mp3
//audio.connecttohost("http://icecast.radiofrance.fr/fip-hifi.aac"); // 196k aac
//audio.connecttohost("http://europe2.lmn.fm/europe2.mp3"); // 128k mp3
animations.StartAnimation(0, NextPixelMoveDuration, LoopAnimUpdate);
}
void loop() {
audio.loop();
animations.UpdateAnimations();
strip.Show();
}
void audio_info(const char *info) {
log_i("info = %s", info);
}
void audio_id3data(const char *info) {
log_i("id3data = %s", info);
}
void audio_eof_mp3(const char *info) {
log_i("eof_mp3 = %s", info);
}
void audio_showstation(const char *info) {
log_i("station = %s", info);
}
void audio_showstreamtitle(const char *info) {
log_i("streamtitle = %s", info);
}
void audio_bitrate(const char *info) {
log_i("bitrate = %s", info);
}
void audio_commercial(const char *info) {
log_i("commercial = %s ", info);
}
void audio_icyurl(const char *info) {
log_i("icyurl = %s", info);
}
void audio_lasthost(const char *info) {
log_i("lasthost = %s", info);
}
void audio_eof_speech(const char *info) {
log_i("eof_speech = %s", info);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment