I'm working on a project where inputs from an array of photo interrupters are read by an Arduino ATMega. When the arduino senses a sensor has been triggered, it activates a specific LED on a NeoPixel strip and a specific tone on a piezo buzzer for the duration of the trigger. When not triggered, each LED in the array cycles a random sequence of colors with no buzzer sound. For those interested, there was a previous thread addressing a different set of issues on the same project, and the forum was incredibly helpful in resolving them:
https://forum.arduino.cc/index.php?topic=668665.0
The problem now: the LEDs work perfectly when triggered, but the buzzer sounds like it's trying to make more than one tone (I can faintly hear the correct tone in the resulting noise). I should mention that on power-up the circuit runs a test, flashing the LEDs with the corresponding buzzer tone, and that all works fine. The audio is clean and the tones are correct. But when the photo interrupter signal enters the picture, that's when the audio is corrupted.
Here is the code:
// https://forum.arduino.cc/index.php?topic=668665
// 5 mar 2020
#include <Adafruit_NeoPixel.h>
// Which pin on the Arduino is connected to the NeoPixels?
#define LED_PIN 10
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 12
#define GS4 415 // 1*
#define AS4 466 // 2
#define B4 494 // 3
#define CS5 554 // 4
#define DS5 622 // 5*
#define F5 698 // 6
#define FS5 740 // 7
#define GS5 831 // 8*
#define AS5 932 // 9*
#define C6 1047 // 10*
#define D6 1175 // 11
#define E6 1319 // 12
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
//states
enum {ST1_idle, ST1_triggered} currentState1 = ST1_idle;
enum {ST2_idle, ST2_triggered} currentState2 = ST2_idle;
// ala https://www.gammon.com.au/statemachine
//pulse, to prove there's no blocking
unsigned long previousPulse;
bool pulseState;
int pulseInterval = 500;
const byte sensors[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
const byte numberOfSensors = sizeof(sensors) / sizeof(sensors[0]);
const int speakerPin = 6;
const int notes[] = {GS4, AS4, B4, CS5, DS5, F5, FS5, GS5, AS5, C6, D6, E6};
enum theStates {ST_idle, ST_triggered};
theStates currentState[numberOfSensors] = {ST_idle, ST_idle};
unsigned long lastBlink[numberOfSensors];
int blinkInterval[numberOfSensors] = {480, 520, 450, 510, 380, 490, 500, 475, 415, 390, 465, 500};
unsigned long triggeredAt[numberOfSensors];
void setup()
{
// initialize serial communication:
Serial.begin(9600);
Serial.print("setup() ... ");
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, pulseState);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
Serial.println(" done");
delay(1000);
// AV test
strip.setPixelColor(0, 125, 0, 125);
strip.show();
tone(speakerPin, notes[0]);
delay(100);
strip.setPixelColor(1, 0, 125, 125);
strip.show();
tone(speakerPin, notes[1]);
delay(100);
strip.setPixelColor(2, 125, 125, 0);
strip.show();
tone(speakerPin, notes[2]);
delay(100);
strip.setPixelColor(3, 85, 85, 85);
strip.show();
tone(speakerPin, notes[3]);
delay(100);
strip.setPixelColor(4, 85, 165, 0);
strip.show();
tone(speakerPin, notes[4]);
delay(100);
strip.setPixelColor(5, 0, 85, 165);
strip.show();
tone(speakerPin, notes[5]);
delay(100);
strip.setPixelColor(6, 85, 0, 165);
strip.show();
tone(speakerPin, notes[6]);
delay(100);
strip.setPixelColor(7, 165, 0, 85);
strip.show();
tone(speakerPin, notes[7]);
delay(100);
strip.setPixelColor(8, 165, 85, 0);
strip.show();
tone(speakerPin, notes[8]);
delay(100);
strip.setPixelColor(9, 145, 45, 45);
strip.show();
tone(speakerPin, notes[9]);
delay(100);
strip.setPixelColor(10, 125, 0, 125);
strip.show();
tone(speakerPin, notes[10]);
delay(100);
strip.setPixelColor(11, 0, 125, 125);
strip.show();
tone(speakerPin, notes[11]);
delay(100);
// turn off
strip.clear();
// strip.fill(0, 0, 11);
noTone(speakerPin);
delay(2000);
// passcode test
strip.setPixelColor(8, 0, 125, 125);
strip.show();
tone(speakerPin, notes[8]);
delay(300);
strip.setPixelColor(9, 145, 45, 45);
strip.show();
tone(speakerPin, notes[9]);
delay(300);
strip.setPixelColor(7, 165, 0, 85);
strip.show();
tone(speakerPin, notes[7]);
delay(300);
strip.setPixelColor(0, 125, 0, 125);
strip.show();
tone(speakerPin, notes[0]);
delay(300);
strip.setPixelColor(4, 145, 185, 0);
strip.show();
tone(speakerPin, notes[4]);
delay(300);
// turn off
strip.clear();
noTone(speakerPin);
delay(2000);
Serial.println(" ");
for (byte i = 0; i < numberOfSensors; i++)
{
Serial.print(i);
Serial.println(" is idle");
}
}//setup
void loop()
{
manageStates();
doPulse();
} //loop
void manageStates()
{
for (byte i = 0; i < numberOfSensors; i++)
{
int val = analogRead(i); //val's not need anywhere else, so local to manage states
//if val *is* needed elsewhere, make an array val[numberOfSensors] as a global
switch (currentState[i]) //ST_idle, ST_triggered
{
case ST_idle:
if (millis() - lastBlink[i] >= blinkInterval[i])
{
lastBlink[i] = millis();
strip.setPixelColor(random(i, 1), random(i, 50), random(i, 50), random(i, 50));
strip.show();
noTone(speakerPin);
}
if (val < 100)
{
currentState[i] = ST_triggered;
Serial.print(i);
Serial.println(" is triggered");
}
break;
case ST_triggered:
strip.setPixelColor(i, 200, 0, 0);
strip.show();
tone(speakerPin, notes[i]);
if (val >= 100) //lost trigger
{
currentState[i] = ST_idle;
Serial.print(i);
Serial.println(" is idle");
}
break;
}//switch i
}//for
}//manageSnyttates
void doPulse()
{
if (millis() - previousPulse >= pulseInterval)
{
previousPulse = millis();
pulseState = !pulseState;
digitalWrite(LED_BUILTIN, pulseState);
}
}//do pulse
I've read there can be problems using NeoPixels with a piezo buzzer, but if that's the issue I would think the problem would present during the test at power-up.
Ideas?