I’ve got a program that plays a tone and flashes an LED for each button in an 11-button keypad. To be more specific, each key is connected to a sensor: when a key is depressed, the Arduino senses a change in voltage and activates the tone and LED for as long as the button is pressed. I have the code set up using a “for loop” to constantly scan the 11 sensors for changes in voltage, and I use a basic state machine to switch between the two states: triggered and idle.
The problem: When a key is pressed and held, there is distortion in the tone which I believe is caused by reactivating the tone repeatedly while it is depressed. When I take the for loop out of the code and try with just one button, the tone has no distortion. Here’s the code:
#include <toneAC.h>
#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;
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);
Serial.println(" ");
for (byte i = 0; i < numberOfSensors; i++) {
Serial.print(i);
Serial.println(" is idle");
}
} // setup
void loop() {
manageStates();
}
void manageStates() {
for (byte i = 0; i < numberOfSensors; i++) {
int val = analogRead(i);
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();
noToneAC();
}
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();
toneAC(notes[i]);
if (val >= 100) { // lost trigger
currentState[i] = ST_idle;
Serial.print(i);
Serial.println(" is idle");
}
break;
} // switch i
} // for
} // manageStates
How can I remove the distortion caused by the for loop when a key is held in the pressed position? What am I missing here?