is the serial monitor bit-rate set to 115200
And this cannot work:
if (abs (x - xLast [n]) > 45 || abs (y - yLast [n]) > 45)
{
msecLast [n] = msec; // *** Here msecLast[n] is set equal to msec ***
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, 98, 60);
if (msec - msecLast [n] >= PeriodBEL) // *** Therefore here (msec - msecLast[n]) will always be zero ***
{
//Turn off the note with a given off/release velocity
noteOff(0, 98, 15000);
}
if (msec - msecLast [n] >= PeriodLED)
See my comments marked with the triple asterisks ***
In addition as PeriodBEL is different to PeriodLED you must
- use two different msecLast arrays for both
OR - as PeriodLED = 4 x PeriodBel you could use a counter and take action for the Leds every forth time ...
You may check this sketch (I am not sure about the pins you are using!!!):
Outdated Sketch ...
/*
ESP32
https://www.mouser.com/ProductDetail/Espressif-Systems/ESP32-DevKitC-32D
Pinout
ESP SparkFun Shield
GND GND (jumper all grounds together for Shield)
16 2
17 3
4 4
RX RX
TX TX
5V +5V
3V3 3.3V
*/
#include <Adafruit_NeoPixel.h>
#define RXD2 16 // was 2, not needed
#define TXD2 18 // was 3 MIDI-In
/* Digital pins for LEDs */
#define PIN0 22 // don't use, actually D1 - GPIO8, retrace other pin on PCB
#define PIN1 32 // JP2
#define PIN2 33 // JP3
#define PIN3 27 // JP4
#define PIN4 13 // JP5
//#define note 0 //The MIDI note value to be played
//#define resetMIDI 4 //Reset line
//#define instrument 0
#define NUMPIXELS 14
Adafruit_NeoPixel pixels0 (NUMPIXELS, PIN0, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels1 (NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 (NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels3 (NUMPIXELS, PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels4 (NUMPIXELS, PIN4, NEO_GRB + NEO_KHZ800);
byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Reset line
int instrument = 0;
// X Y
// 1: 2, 15
// 2: 4, 0
// 3: 35, 34
// 4: 26, 25
// 5: 12, 14
const byte PinX [] = { 2, 4, 35, 26, 12 };
const byte PinY [] = { 15, 0, 34, 25, 14 };
const int N = sizeof(PinX);
int xLast [N];
int yLast [N];
int i [N];
int count [N];
boolean toneIsActive[N];
unsigned long msecLast [N];
const unsigned long PeriodLED = 200;
const unsigned long PeriodBEL = 50;
unsigned long msec;
char s [80];
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (115200);
//Setup soft serial for MIDI control
Serial2.begin(31250, SERIAL_8N1, RXD2, TXD2);
for (int n = 0; n < N; n++)
{
xLast [n] = analogRead (PinX [n]);
yLast [n] = analogRead (PinY [n]);
toneIsActive[n] = false;
count[n] = 0;
}
pixels0.begin ();
pixels1.begin ();
pixels2.begin ();
pixels3.begin ();
pixels4.begin ();
//Reset
pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);
talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume to near max (127)
}
// -----------------------------------------------------------------------------
//Send a MIDI note-on message. Like pressing a piano key
//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}
//Send a MIDI note-off message. Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}
//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
Serial2.write(cmd);
Serial2.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if ( (cmd & 0xF0) <= 0xB0)
Serial2.write(data2);
}
// -----------------------------------------------------------------------------
void update ( int n, Adafruit_NeoPixel * pixels )
{
int x;
int y;
if (!toneIsActive[n]) {
x = analogRead (PinX [n]);
y = analogRead (PinY [n]);
if (abs (x - xLast [n]) > 45 || abs (y - yLast [n]) > 45)
{
talkMIDI(0xB0, 0, 0x00); //Default bank GM1
talkMIDI(0xC0, 98, 0); //Set instrument number. 0xC0 is a 1 data byte command
msecLast [n] = msec;
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, 98, 60);
toneIsActive[n] = true;
}
}
if (toneIsActive[n]){
if (msec - msecLast [n] >= PeriodBEL)
{
//Turn off the note with a given off/release velocity
noteOff(0, 98, 15000);
toneIsActive[n] = false;
count[n]++;
}
if (count[n] >= 4)
{
count[n] = 0;
if (i [n] >= NUMPIXELS)
{
i [n] = 0; // reset i at max value
pixels->clear (); // Set all pixel colors to 'off'
}
pixels->setPixelColor (i [n],
pixels->Color (150 - i [n] * 20, i [n] * 20, 0));
pixels->show ();
i [n]++;
}
}
xLast [n] = x;
yLast [n] = y;
}
// -----------------------------------------------------------------------------
void loop ()
{
msec = millis ();
update (0, & pixels0);
update (1, & pixels1);
update (2, & pixels2);
update (3, & pixels3);
update (4, & pixels4);
}
P.S.: I am also not quite sure about your intentions ... However it should be required to move the lines
xLast [n] = x;
yLast [n] = y;
to another place. I changed it in this sketch:
Open here for the sketch
/*
ESP32
https://www.mouser.com/ProductDetail/Espressif-Systems/ESP32-DevKitC-32D
Pinout
ESP SparkFun Shield
GND GND (jumper all grounds together for Shield)
16 2
17 3
4 4
RX RX
TX TX
5V +5V
3V3 3.3V
*/
#include <Adafruit_NeoPixel.h>
#define RXD2 16 // was 2, not needed
#define TXD2 18 // was 3 MIDI-In
/* Digital pins for LEDs */
#define PIN0 22 // don't use, actually D1 - GPIO8, retrace other pin on PCB
#define PIN1 32 // JP2
#define PIN2 33 // JP3
#define PIN3 27 // JP4
#define PIN4 13 // JP5
//#define note 0 //The MIDI note value to be played
//#define resetMIDI 4 //Reset line
//#define instrument 0
#define NUMPIXELS 14
Adafruit_NeoPixel pixels0 (NUMPIXELS, PIN0, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels1 (NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 (NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels3 (NUMPIXELS, PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels4 (NUMPIXELS, PIN4, NEO_GRB + NEO_KHZ800);
byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Reset line
int instrument = 0;
// X Y
// 1: 2, 15
// 2: 4, 0
// 3: 35, 34
// 4: 26, 25
// 5: 12, 14
const byte PinX [] = { 2, 4, 35, 26, 12 };
const byte PinY [] = { 15, 0, 34, 25, 14 };
const int N = sizeof(PinX);
int xLast [N];
int yLast [N];
int i [N];
int count [N];
boolean toneIsActive[N];
unsigned long msecLast [N];
const unsigned long PeriodLED = 200;
const unsigned long PeriodBEL = 50;
unsigned long msec;
char s [80];
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (115200);
//Setup soft serial for MIDI control
Serial2.begin(31250, SERIAL_8N1, RXD2, TXD2);
for (int n = 0; n < N; n++)
{
xLast [n] = analogRead (PinX [n]);
yLast [n] = analogRead (PinY [n]);
toneIsActive[n] = false;
count[n] = 0;
}
pixels0.begin ();
pixels1.begin ();
pixels2.begin ();
pixels3.begin ();
pixels4.begin ();
//Reset
pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);
talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume to near max (127)
}
// -----------------------------------------------------------------------------
//Send a MIDI note-on message. Like pressing a piano key
//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}
//Send a MIDI note-off message. Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}
//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
Serial2.write(cmd);
Serial2.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if ( (cmd & 0xF0) <= 0xB0)
Serial2.write(data2);
}
// -----------------------------------------------------------------------------
void update ( int n, Adafruit_NeoPixel * pixels )
{
int x;
int y;
if (!toneIsActive[n]) {
x = analogRead (PinX [n]);
y = analogRead (PinY [n]);
if (abs (x - xLast [n]) > 45 || abs (y - yLast [n]) > 45)
{
talkMIDI(0xB0, 0, 0x00); //Default bank GM1
talkMIDI(0xC0, 98, 0); //Set instrument number. 0xC0 is a 1 data byte command
msecLast [n] = msec;
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, 98, 60);
toneIsActive[n] = true;
xLast [n] = x;
yLast [n] = y;
}
}
if (toneIsActive[n]){
if (msec - msecLast [n] >= PeriodBEL)
{
//Turn off the note with a given off/release velocity
noteOff(0, 98, 15000);
toneIsActive[n] = false;
count[n]++;
}
if (count[n] >= 4)
{
count[n] = 0;
if (i [n] >= NUMPIXELS)
{
i [n] = 0; // reset i at max value
pixels->clear (); // Set all pixel colors to 'off'
}
pixels->setPixelColor (i [n],
pixels->Color (150 - i [n] * 20, i [n] * 20, 0));
pixels->show ();
i [n]++;
}
}
}
// -----------------------------------------------------------------------------
void loop ()
{
msec = millis ();
update (0, & pixels0);
update (1, & pixels1);
update (2, & pixels2);
update (3, & pixels3);
update (4, & pixels4);
}
looks like the above logic makes the timer dependent on the trigger condition. in the original code, latch2 was used to recognize the event.
that event should also prepare the timer: capture msec and possibly a variable period, either PeriodLED or PeriodBel, unless there are 2 separate timers
the timer(s) should be checked while latch2 is true and presumably one would reset latch2 false
not clear from the code what is intended, 1 or 2 timers, but the timer should not be condition on the trigger
Thanks both for your help. It's still not quite how it needs to be, but I will try to figure out the programs...
I just want each LED strand and chime/note to turn on, simultaneously, with motion. So if one accelerometer is triggered, it runs. If another triggers, the first continues and the second runs. Both would run once in that example.
This ran each LED with motion and then infinitely cycles the LEDs without turning off. The goal is to have it cycle once per strand for any movement trigger in the corresponding strand.
Ok, if you use the second sketch I posted (not the "outdated" one) it will only step forward on led per tone.
Is it correct that you want the corresponding led strip to cycle once per tone?
If yes you may try this sketch (after changing the pins to your setup please
):
/*
ESP32
https://www.mouser.com/ProductDetail/Espressif-Systems/ESP32-DevKitC-32D
Pinout
ESP SparkFun Shield
GND GND (jumper all grounds together for Shield)
16 2
17 3
4 4
RX RX
TX TX
5V +5V
3V3 3.3V
*/
//#define WOKWI
#include <Adafruit_NeoPixel.h>
#define RXD2 16 // was 2, not needed
#define TXD2 18 // was 3 MIDI-In
/* Digital pins for LEDs */
#define PIN0 22 // don't use, actually D1 - GPIO8, retrace other pin on PCB
#define PIN1 32 // JP2
#define PIN2 33 // JP3
#define PIN3 27 // JP4
#define PIN4 13 // JP5
//#define note 0 //The MIDI note value to be played
//#define resetMIDI 4 //Reset line
//#define instrument 0
#define NUMPIXELS 14
Adafruit_NeoPixel pixels0 (NUMPIXELS, PIN0, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels1 (NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 (NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels3 (NUMPIXELS, PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels4 (NUMPIXELS, PIN4, NEO_GRB + NEO_KHZ800);
byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Reset line
int instrument = 0;
// X Y
// 1: 2, 15
// 2: 4, 0
// 3: 35, 34
// 4: 26, 25
// 5: 12, 14
const byte PinX [] = { 2, 4, 35, 26, 12 };
const byte PinY [] = { 15, 0, 34, 25, 14 };
const int N = sizeof(PinX);
int xLast [N];
int yLast [N];
int i [N];
boolean lightLED[N];
boolean toneIsActive[N];
unsigned long msecLast [N];
unsigned long msecLastLED [N];
const unsigned long PeriodLED = 200;
const unsigned long PeriodBEL = 50;
unsigned long msec;
char s [80];
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (115200);
//Setup soft serial for MIDI control
Serial2.begin(31250, SERIAL_8N1, RXD2, TXD2);
for (int n = 0; n < N; n++)
{
xLast [n] = analogRead (PinX [n]);
yLast [n] = analogRead (PinY [n]);
toneIsActive[n] = false;
lightLED[n] = false;
msecLast[n] = 0;
msecLastLED[n] = 0;
}
pixels0.begin ();
pixels1.begin ();
pixels2.begin ();
pixels3.begin ();
pixels4.begin ();
//Reset
pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);
talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume to near max (127)
}
// -----------------------------------------------------------------------------
//Send a MIDI note-on message. Like pressing a piano key
//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}
//Send a MIDI note-off message. Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}
//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
Serial2.write(cmd);
Serial2.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if ( (cmd & 0xF0) <= 0xB0)
Serial2.write(data2);
}
// -----------------------------------------------------------------------------
void update ( int n, Adafruit_NeoPixel * pixels )
{
int x;
int y;
if (!toneIsActive[n]) {
x = analogRead (PinX [n]);
y = analogRead (PinY [n]);
#ifdef WOKWI
if (abs (x - xLast [n]) > 45)
#else
if (abs (x - xLast [n]) > 45 || abs (y - yLast [n]) > 45)
#endif
{
talkMIDI(0xB0, 0, 0x00); //Default bank GM1
talkMIDI(0xC0, 98, 0); //Set instrument number. 0xC0 is a 1 data byte command
msecLast [n] = msec;
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, 98, 60);
toneIsActive[n] = true;
xLast [n] = x;
yLast [n] = y;
}
}
if (toneIsActive[n]){
if (msec - msecLast [n] >= PeriodBEL)
{
//Turn off the note with a given off/release velocity
noteOff(0, 98, 15000);
toneIsActive[n] = false;
lightLED[n] = true;
}
}
if (lightLED[n] && msec - msecLastLED[n] > PeriodLED)
{
msecLastLED[n] = msec;
if (i [n] >= NUMPIXELS)
{
i [n] = 0; // reset i at max value
pixels->clear (); // Set all pixel colors to 'off'
lightLED[n] = false;
} else
{
pixels->setPixelColor (i [n],
pixels->Color (150 - i [n] * 20, i [n] * 20, 0));
i [n]++;
}
pixels->show ();
}
}
// -----------------------------------------------------------------------------
void loop ()
{
msec = millis ();
update (0, & pixels0);
update (1, & pixels1);
update (2, & pixels2);
update (3, & pixels3);
update (4, & pixels4);
}
You can check it on WOKWI:
https://wokwi.com/projects/366180935202469889
Thanks. It works great on Wokwi, but something isn't right with my setup. It just rings and cycles through infinitely.
I suggest you check the analogRead() part ...
The lines
talkMIDI(0xB0, 0, 0x00); //Default bank GM1
talkMIDI(0xC0, 98, 0); //Set instrument number. 0xC0 is a 1 data byte command
could probably also be moved to setup() as I assume that default bank and instrument will not change during the use of the application ... It would save some traffic on Serial2.
Just a thought: If your accelerometers all work in parallel they will possibly send more tone commands than your device is capable to play in a short time on the same channel?!?
Maybe you have either to use different channels or do not allow a further tone as long as one is active?
I moved them into setup and it still infinitely cycles...
Try this (again change the pins if required ...
):
/*
ESP32
https://www.mouser.com/ProductDetail/Espressif-Systems/ESP32-DevKitC-32D
Pinout
ESP SparkFun Shield
GND GND (jumper all grounds together for Shield)
16 2
17 3
4 4
RX RX
TX TX
5V +5V
3V3 3.3V
*/
// #define WOKWI
#include <Adafruit_NeoPixel.h>
#define RXD2 16 // was 2, not needed
#define TXD2 18 // was 3 MIDI-In
/* Digital pins for LEDs */
#define PIN0 22 // don't use, actually D1 - GPIO8, retrace other pin on PCB
#define PIN1 32 // JP2
#define PIN2 33 // JP3
#define PIN3 27 // JP4
#define PIN4 13 // JP5
//#define note 0 //The MIDI note value to be played
//#define resetMIDI 4 //Reset line
//#define instrument 0
#define NUMPIXELS 14
Adafruit_NeoPixel pixels0 (NUMPIXELS, PIN0, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels1 (NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels2 (NUMPIXELS, PIN2, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels3 (NUMPIXELS, PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels4 (NUMPIXELS, PIN4, NEO_GRB + NEO_KHZ800);
byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Reset line
int instrument = 0;
// X Y
// 1: 2, 15
// 2: 4, 0
// 3: 35, 34
// 4: 26, 25
// 5: 12, 14
const byte PinX [] = { 2, 4, 35, 26, 12 };
const byte PinY [] = { 15, 0, 34, 25, 14 };
const int N = sizeof(PinX);
int xLast [N];
int yLast [N];
int i [N];
boolean lightLED[N];
boolean toneIsActive[N];
unsigned long msecLast [N];
unsigned long msecLastLED [N];
const unsigned long PeriodLED = 200;
const unsigned long PeriodBEL = 50;
unsigned long msec;
char s [80];
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (115200);
//Setup soft serial for MIDI control
Serial2.begin(31250, SERIAL_8N1, RXD2, TXD2);
for (int n = 0; n < N; n++)
{
xLast [n] = analogRead (PinX [n]);
yLast [n] = analogRead (PinY [n]);
toneIsActive[n] = false;
lightLED[n] = false;
msecLast[n] = 0;
msecLastLED[n] = 0;
}
pixels0.begin ();
pixels1.begin ();
pixels2.begin ();
pixels3.begin ();
pixels4.begin ();
//Reset
pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);
talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume to near max (127)
}
// -----------------------------------------------------------------------------
//Send a MIDI note-on message. Like pressing a piano key
//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}
//Send a MIDI note-off message. Like releasing a piano key
void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}
//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
Serial2.write(cmd);
Serial2.write(data1);
//Some commands only have one data byte. All cmds less than 0xBn have 2 data bytes
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if ( (cmd & 0xF0) <= 0xB0)
Serial2.write(data2);
}
// -----------------------------------------------------------------------------
void update ( int n, Adafruit_NeoPixel * pixels )
{
int x;
int y;
boolean anyToneActive = false;
for (int j=0;j<N;j++){
if (toneIsActive[j]) anyToneActive = true;
}
if (!toneIsActive[n] && !anyToneActive) {
x = analogRead (PinX [n]);
y = analogRead (PinY [n]);
#ifdef WOKWI
if (abs (x - xLast [n]) > 45)
#else
if (abs (x - xLast [n]) > 45 || abs (y - yLast [n]) > 45)
#endif
{
talkMIDI(0xB0, 0, 0x00); //Default bank GM1
talkMIDI(0xC0, 98, 0); //Set instrument number. 0xC0 is a 1 data byte command
msecLast [n] = msec;
//Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
noteOn(0, 98, 60);
toneIsActive[n] = true;
xLast [n] = x;
yLast [n] = y;
}
}
if (toneIsActive[n]){
if (msec - msecLast [n] >= PeriodBEL)
{
//Turn off the note with a given off/release velocity
noteOff(0, 98, 15000);
toneIsActive[n] = false;
lightLED[n] = true;
}
}
if (lightLED[n] && msec - msecLastLED[n] > PeriodLED)
{
msecLastLED[n] = msec;
if (i [n] >= NUMPIXELS)
{
i [n] = 0; // reset i at max value
pixels->clear (); // Set all pixel colors to 'off'
lightLED[n] = false;
} else
{
pixels->setPixelColor (i [n],
pixels->Color (150 - i [n] * 20, i [n] * 20, 0));
i [n]++;
}
pixels->show ();
}
}
// -----------------------------------------------------------------------------
void loop ()
{
msec = millis ();
update (0, & pixels0);
update (1, & pixels1);
update (2, & pixels2);
update (3, & pixels3);
update (4, & pixels4);
}
This sketch just does not allow to create a new tone as long as any tone is active. Maybe still to quick ... But a try.
I changed the 45s to 200. Although, this takes out the chime/note sound. Or maybe the chime/note parts was triggering it indefinitely anyway.
Sometimes a strand stays on. They also go several times after one motion. Probably need some sort of debounce.
Edit: now the chime/note is sounding continuously again and the LEDs are going on forever.
should the tone change as each pixel is and should it turn off when the last pixel is? should they both go hand-in-hand?
Or something similar. If strand1 moves, that stand's LEDs should light up once with a sound. It would be great if each strand could emit a song faster or slower depending on how often they are triggered. But for now, just getting the lights and sound 1:1 is the goal.
You have to make a decision regarding your intention... ![]()
- A time lasts 50 msec plus attenuation time.
- One led stand takes 14x200 msec time which sums up to 2.8 seconds.
If you want to synchronize the timing must be the same.
Does it have to do with timing? Can't the note/sound trigger once any individual LED strand starts? As though it is enabled only from the first LED of the strand only?
What makes it difficult to create a solution is that it (at least to me) your intention is unfortunately not clear ... ;-(
E.g. you have these constants:
const unsigned long PeriodLED = 200;
const unsigned long PeriodBEL = 50;
During PeriodLED the tone per strand (!) may be triggered ON/OFF 4 times.
What shall the according Led strand do during this time?
Another open question (for me) is how your MIDI device reacts if it gets sound commands every 50 msec (what happens if your sensors are constantly triggering the sound output). I have already limited it so that they cannot fire while another sound is active. However the MIDI command includes also a "release velocity" ... When will the sound be really off?
I can image a sketch that
- allows to send one sound command only every 200 msec (as an example) triggered by one of the five accelerometers
- switches one Led in the respective strand of the corresponding accelerometer immediately when the tone is triggered
This would still enable five sounds/sec.
It would of course require some changes to the logic to avoid that the accelerometers with the lower number will have priority, especially if the trigger threshold is low.
Say each LED stand has 14 LEDs. They are each separate. With some movement, above the threshold, the string of 14 LEDs should light up once and one tone/note should also accompany the LED strand (not each LED).
This should happen simultaneously for each strand. So if many strands are moving, then the note/chime sound should occur more frequently. If only one strand moves, the note/chime should only sound once.
const byte PinX [] = { 2, 4, 35, 26, 12 };
const int N = sizeof(PinX);
for (int j = 0; j < N; j++)
{
if (toneIsActive[j])
anyToneActive = true;
}
I do not understand this part. N always = 5. Wouldn't anyToneActive always be true?
why isn't update() more like:
- recognize when the trigger occurs and activate things and turn on a tone
- separately check if active and when the timer expires
- recognize when the pixels are done (>= NUMPIXELS) and turn off both the pixels and tones
bool active [N];
void update ( int n, Adafruit_NeoPixel * pixels )
{
int x = analogRead (PinX [n]);
int y = analogRead (PinY [n]);
if (abs (x - xLast [n]) > 45 || abs (y - yLast [n]) > 45) {
active [n] = true;
msecLast [n] = msec;
noteOn(0, 98, 60);
}
if (active [n]) {
if (msec - msecLast [n] >= PeriodBEL) {
msecLast [n] = msec;
sprintf (s, " pinX %2d, i %3d, x %4d, y %4d",
PinX [n], i [n], x, y);
Serial.println (s);
if (i [n] >= NUMPIXELS) {
i [n] = 0; // reset i at max value
pixels->clear (); // Set all pixel colors to 'off'
noteOff(0, 98, 15000);
active [n] = false;
}
else {
pixels->setPixelColor (i [n],
pixels->Color (150 - i [n] * 20, i [n] * 20, 0));
pixels->show ();
i [n]++;
}
}
}
xLast [n] = x;
yLast [n] = y;
}