/*
https://github.com/RalphBacon/ESP32-Variable-Passing-Using-Queues-Global-Vars
*/
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include <driver/i2s.h>
#include <FS.h>
#include <SPIFFS.h> // Use SPIFFS for file system
TaskHandle_t Task_Neo;
QueueHandle_t queue;
// Define pins for NeoPixel, I2S, and sensor
#define LED_PIN 14
#define SENSOR_PIN 2 // Example sensor pin
// Number of NeoPixels
#define NUMPIXELS 16
// Create the NeoPixel object
Adafruit_NeoPixel pixels(NUMPIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
// I2S configuration
#define I2S_WS 5 // Word Select (LRC on MAX98357A)
#define I2S_SD 18 // Data Out (DIN on MAX98357A)
#define I2S_SCK 4 // Bit clock pin (BCLK on MAX98375A)
// global variables
int counter = 0;
//bool flashLED = false; - use task queue.
bool sensorTriggered = false; // Initialize sensorTriggered
void playAudio(const char* filename);
void printWavHeader(File &file);
void neo(void* parameter) {
for (;;) {
// Get the number of flashes required
int flashLED;
xQueueReceive(queue, &flashLED, portMAX_DELAY);
// Check if the button is pressed (LOW means pressed due to pull-up resistor)
if (flashLED == true) {
Serial.println("Shake detected!"); // Let us know there was a shake
//counter++;
Serial.println(counter);
flashLED = false;
// xQueueSend(queue, &flashLED, portMAX_DELAY);
if (counter == 2) {
// Play audio and flash NeoPixel for second shake
// play_wav("awe-a"); // play audio (not implemented)
for (int i = 0; i < 3; i++) {
partyFlash(180); // Flash NeoPixel
}
} else if (counter == 3) {
// Play audio and flash NeoPixel for third shake
// play_wav("awe-b"); // play audio (not implemented)
for (int i = 0; i < 3; i++) {
partyFlash(250); // Flash NeoPixel
}
} else if (counter == 4) {
// Play audio and flash NeoPixel for fourth shake
// play_wav("awe-c"); // play audio (not implemented)
for (int i = 0; i < 3; i++) {
partyFlashBlue(250); // Flash NeoPixel
}
} else if (counter == 5) {
// Reset counter and flash NeoPixel for fifth shake
counter = 0;
// play_wav("untz"); // play audio (not implemented)
for (int i = 0; i < 3; i++) {
ledFlash(180); // Flash NeoPixel
}
//pixels.setPixelColor(0, pixels.Color(255, 255, 255)); // White
pixels.fill(pixels.Color(255,255,255), 0, -1);
pixels.show();
delay(1000); // Light it for one second
//pixels.setPixelColor(0, pixels.Color(0, 0, 0)); // Off
pixels.fill(pixels.Color(0,0,0), 0, -1);
pixels.show();
} else {
// Play audio and flash NeoPixel for first shake
// play_wav("haha"); // play audio (not implemented)
//pixels.setPixelColor(0, pixels.Color(255, 255, 255)); // White
pixels.fill(pixels.Color(255,255,255), 0, -1);
pixels.show();
delay(1000); // Light it for one second
//pixels.setPixelColor(0, pixels.Color(0, 0, 0)); // Off
pixels.fill(pixels.Color(0,0,0), 0, -1);
pixels.show();
}
// Debounce delay
delay(100);
}
}
}
void setup() {
Serial.begin(115200);
Serial.println("Setup started.");
pinMode(LED_PIN, OUTPUT);
pinMode(SENSOR_PIN, INPUT_PULLUP);
// Initialize the NeoPixel library
pixels.begin();
pixels.setBrightness(255); // Set brightness (0-255)
// Initialize I2S
i2s_config_t i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 22050, // 22 kHz sample rate
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // 16-bit per sample
.channel_format = I2S_CHANNEL_FMT_ALL_LEFT, // Mono format
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = 0,
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false,
.tx_desc_auto_clear = true,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_SD,
.data_in_num = I2S_PIN_NO_CHANGE
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
// Initialize sensor pin with internal pull-up resistor
pinMode(SENSOR_PIN, INPUT_PULLUP);
// Initialize SPIFFS
/**
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialization failed!");
return;
}
Serial.println("SPIFFS initialized successfully.");
**/
// Create the queue with 5 slots of 2 bytes
queue = xQueueCreate(5, sizeof(int));
xTaskCreatePinnedToCore(
neo, /* Function to implement the task */
"Task_Neo",/* Name of the task */
1000, /* Stack size in words */
NULL, /* Task input parameter */
1, /* Priority of the task */
&Task_Neo, /* Task handle. */
1); /* Core where the task should run */
Serial.println("Setup completed.");
}
void loop() {
//Serial.println("sensor: " + String(digitalRead(SENSOR_PIN)));
if (digitalRead(SENSOR_PIN) == LOW) { // Check if the sensor is triggered
if (!sensorTriggered) { // Only increment counter on the first detection
counter++;
sensorTriggered = true;
int flashLED = true;
xQueueSend(queue, &flashLED, portMAX_DELAY);
Serial.print("Counter incremented to: ");
Serial.println(counter);
if (counter == 2) {
Serial.println("Playing awe-a.wav");
//playAudio("/awe-a.wav");
} else if (counter == 3) {
Serial.println("Playing awe-b.wav");
//playAudio("/awe-b.wav");
} else if (counter == 4) {
Serial.println("Playing awe-c.wav");
//playAudio("/awe-c.wav");
} else if (counter == 5) {
Serial.println("Playing untz.wav");
//counter = 0; // this is done in the neo task
//playAudio("/untz.wav");
} else {
// counter == 1
Serial.println("Playing haha.wav");
//playAudio("/haha.wav");
}
}
} else {
sensorTriggered = false; // Reset the trigger flag after action
}
delay(100); // Add a delay to prevent rapid triggering
}
void partyFlash(int duration) {
unsigned long startTime = millis();
while (millis() - startTime < duration) {
//pixels.setPixelColor(0, pixels.Color(255, 255, 255)); // White
pixels.fill(pixels.Color(255,255,255), 0, -1);
pixels.show();
delay(duration);
//pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // Red
pixels.fill(pixels.Color(255,0,0), 0, -1);
pixels.show();
delay(duration);
//pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // Green
pixels.fill(pixels.Color(0,255,0), 0, -1);
pixels.show();
delay(duration);
//pixels.setPixelColor(0, pixels.Color(0, 0, 0)); // Off
pixels.fill(pixels.Color(0,0,0), 0, -1);
pixels.show();
delay(duration);
}
}
void partyFlashBlue(int duration) {
unsigned long startTime = millis();
while (millis() - startTime < duration) {
//pixels.setPixelColor(0, pixels.Color(0, 0, 255)); // Blue
pixels.fill(pixels.Color(0,0,255), 0, -1);
pixels.show();
delay(duration);
//pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // Red
pixels.fill(pixels.Color(255,0,0), 0, -1);
pixels.show();
delay(duration);
//pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // Green
pixels.fill(pixels.Color(0,255,0), 0, -1);
pixels.show();
delay(duration);
//pixels.setPixelColor(0, pixels.Color(0, 0, 0)); // Off
pixels.fill(pixels.Color(0,0,0), 0, -1);
pixels.show();
delay(duration);
}
}
void ledFlash(int duration) {
unsigned long startTime = millis();
while (millis() - startTime < duration) {
//pixels.setPixelColor(0, pixels.Color(255, 255, 255)); // White
pixels.fill(pixels.Color(255,255,255), 0, -1);
pixels.show();
delay(duration);
//pixels.setPixelColor(0, pixels.Color(0, 0, 0)); // Off
pixels.fill(pixels.Color(0,0,0), 0, -1);
pixels.show();
delay(duration);
}
}
void printWavHeader(File &file) {
uint8_t buffer[44];
file.seek(0);
file.read(buffer, 44);
uint32_t sampleRate = *(uint32_t*)&buffer[24];
uint16_t bitsPerSample = *(uint16_t*)&buffer[34];
uint16_t numChannels = *(uint16_t*)&buffer[22];
Serial.print("Sample Rate: ");
Serial.println(sampleRate);
Serial.print("Bits Per Sample: ");
Serial.println(bitsPerSample);
Serial.print("Number of Channels: ");
Serial.println(numChannels);
}
void playAudio(const char* filename) {
File audioFile = SPIFFS.open(filename, "r");
if (!audioFile) {
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Playing file: ");
Serial.println(filename);
// Print WAV header information
printWavHeader(audioFile);
// Read audio data from file and play using I2S
size_t bytes_read;
uint8_t buffer[512]; // Adjust buffer size if needed
while ((bytes_read = audioFile.read(buffer, sizeof(buffer) / 2)) > 0) {
uint16_t sample;
size_t bytes_written;
for (size_t i = 0; i < bytes_read; i += 2) {
// Convert the mono sample to stereo by duplicating it
sample = buffer[i] | (buffer[i + 1] << 8);
uint32_t stereoSample = sample | (sample << 16);
i2s_write(I2S_NUM_0, &stereoSample, sizeof(stereoSample), &bytes_written, portMAX_DELAY);
}
}
audioFile.close();
Serial.println("Finished playing file");
}