Thanks for the pointers. I've spent a few hours on this now and got something that works. Its not the most elegant but its been reliable. I created my own version of morse code. Four digits long with four different lengths of beep. I'm starting each code with a 4 long beep then using a mix of 1,2 and 3 length beeps for the actual data. That gives me 27 codes but it'll be easy to extend with more digits or more numbers.
The code is a bit hacked around as I've been tinkering but it is good to have something working. I'm a self taught, late starter coder so I'm sure there is stuff in there that will make proper coders wince but I'm open to criticism and advice on neatening it up.
I will probably tighten up the audio clips and the timing. I'm sure it could all be much faster. Each clip takes about 0.1 seconds, which is very slow for a microprocessor but its close to instant to the eye.
These are a couple of the audio clips:
4111

4221

And this is the code
#include <Adafruit_NeoPixel.h>
#define PIN 11
#define PIXNUM 32
#define ButtonLed 6
uint32_t c;
int col;
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXNUM, PIN, NEO_GRB + NEO_KHZ800);
// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.
int counter = 0;
int lastcounter = 0;
int thedata = 0;
int thebits = 0;
int inputArraySize = 5;
int inputs[5];
int biggestSoFar = 0;
int NeoOn = 0;
boolean NeoFlash = false;
int flashCounter = 0;
int flashMax = 4;//How many times to loop the flash
int flashLoop = 8;//How many LEDs per loop
unsigned long previousMillis = 0; // will store last time LED was updated
const long flashInterval = 400; // interval at which to flash (milliseconds)
const long blinkInterval = 300; // interval at which to flash (milliseconds)
void setup() {
pinMode(A5, INPUT);
pinMode(ButtonLed, OUTPUT);
// Start serial communication with the PC (over hardware serial)
Serial.begin(9600);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
int AudioSignal = analogRead(A5);//read the audio level
AudioSignal = abs(AudioSignal - 506);//how far is it from the zero (mid) point
biggestSoFar = AudioSignal; //set current as the biggest so far
for (int i = 1; i < inputArraySize; i++) {
int pos = inputArraySize - i;
inputs[pos] = inputs[pos - 1]; //shift each signal to the next postion
if (inputs[pos] > biggestSoFar)biggestSoFar = inputs[pos];//find the biggest in the last n inputs
}
inputs[0] = AudioSignal;
//Serial.println(biggestSoFar);
delay(1);
if (biggestSoFar < 10 ) {
//Serial.print("_");
counter = 0;
}
if (biggestSoFar > 100 ) {
//Serial.print("X");
counter++;
lastcounter = counter;
}
if (lastcounter != 0 and counter == 0) {
Serial.print(lastcounter);
Serial.print(" ");
int number = checknumber(lastcounter);
if (number == 4) {
thedata = 0;
thebits = 0;
}
else {
thedata *= 10;
thedata += number;
thebits ++;
}
Serial.println(number);
if (thebits == 3) {
thebits = 0;
Serial.print("*** ");
Serial.print(thedata);
Serial.println(" ***");
}
lastcounter = 0;
}
if (thedata > 100 && thedata < 199) {
NeoOn = 100;
}
if (thedata > 200 && thedata < 299) {
NeoOn = 200;
}
if (thedata >= 300)DoButtonState();
DoLightState();
}
int DoLightState() {
unsigned long currentMillis = millis();
if (NeoOn == 100) { //light is off, turn it on
Serial.println("--- BLINK ---");
if (thedata == 121) c = strip.Color(180, 80, 0); //amber
if (thedata == 111) c = strip.Color(200, 0, 0); //red
if (thedata == 112) c = strip.Color(0, 200, 0); //green
if (thedata == 113) c = strip.Color(0, 0, 200); //blue
for (int k = 0; k < PIXNUM; k++) {
strip.setPixelColor(k, c);
}
strip.show();
NeoOn = 101;
previousMillis = currentMillis;
}
else if (NeoOn == 101) { //light is on, check how long it has been on
if (currentMillis - previousMillis >= blinkInterval) {
strip.clear();
strip.show();
NeoOn = 0;
}
}
else if (NeoOn == 200) { //light is off, flash it on
Serial.println("### LOOP ###");
if (thedata == 221) c = strip.Color(180, 80, 0); //amber
if (thedata == 211) c = strip.Color(200, 0, 0); //red
if (thedata == 212) c = strip.Color(0, 200, 0); //green
if (thedata == 213) c = strip.Color(0, 0, 200); //blue
flashCounter = 0;
NeoOn = 201;
previousMillis = currentMillis;
}
else if (NeoOn == 201) { //loop the lights
if (currentMillis - previousMillis >= flashInterval) {
int out = flashCounter % flashLoop;
int off = out - 2;//how many LEDs on at a time
if (off < 0)off += flashLoop;
strip.setPixelColor(out, c);
strip.setPixelColor(off, 0);
out += flashLoop;
off += flashLoop;
strip.setPixelColor(out, c);
strip.setPixelColor(off, 0);
strip.show();
flashCounter++;
previousMillis = currentMillis;
if (flashCounter > flashMax * flashLoop) { //flash completed
NeoOn = 0;
strip.clear();
strip.show();
}
}
}
if (thedata > 100)thedata = 0; //reset if we have complete data
}
int DoButtonState() {
if (thedata == 311)digitalWrite(ButtonLed, HIGH); //light button LED
if (thedata == 322)digitalWrite(ButtonLed, LOW); //turn off button LED
thedata = 0;
}
int checknumber(int numberToTest) {
if (numberToTest > 35)return 4;
if (numberToTest > 27)return 3;
if (numberToTest > 18)return 2;
if (numberToTest > 5)return 1;
return 0;
}
And the serial port debug
40 4
22 2
10 1
11 1
*** 211 ***
### LOOP ###
42 4
13 1
13 1
14 1
*** 111 ***
--- BLINK ---
40 4
22 2
22 2
10 1
*** 221 ***
### LOOP ###