/*
ESP32 https://www.mouser.com/ProductDetail/Espressif-Systems/ESP32-DevKitC-32D
Could work with Arduino Uno or similar.
*/
#include <Adafruit_NeoPixel.h>
#define RXD2 16
#define TXD2 17
//Digital LED addressing control pins (one for each strand)
#define PIN4 27 // ckt down
#define PIN5 13 // ckt up
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 13
Adafruit_NeoPixel pixels4(NUMPIXELS, PIN4, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels5(NUMPIXELS, PIN5, NEO_GRB + NEO_KHZ800);
unsigned long previousTime = millis(); // timestamp
unsigned long currentTime;
bool latch = false;
const unsigned long eventInterval = 9;
unsigned long startMillis4 = millis();
unsigned long startMillis5 = millis();
unsigned long now4;
unsigned long now5;
byte l = 0;
byte m = 0;
bool latch4 = false;
bool latch5 = false;
const int period = 200;
byte note = 0; //The MIDI note value to be played
byte resetMIDI = 4; //Reset line
int instrument = 0;
int x4_a, y4_a;
int x4_b, y4_b;
int x5_a, y5_a;
int x5_b, y5_b;
void setup()
{
Serial.begin(115200);
//Setup soft serial for MIDI control
Serial2.begin(31250, SERIAL_8N1, RXD2, TXD2);
pinMode(26, INPUT);
pinMode(25, INPUT);
pinMode(27, INPUT);
pinMode(14, INPUT);
pixels4.begin();
pixels5.begin();
}
void loop()
{
if (latch == false)
{
x4_a = analogRead(26);
y4_a = analogRead(25);
x5_a = analogRead(27);
y5_a = analogRead(14);
latch = true;
}
currentTime = millis();
if (currentTime - previousTime >= eventInterval && latch == true)
{
x4_b = analogRead(26); // accelerometer x
y4_b = analogRead(25); // accelerometer y
x5_b = analogRead(27);
y5_b = analogRead(14);
x4_a = x4_b - x4_a;
y4_a = y4_b - y4_a;
x5_a = x5_b - x5_a;
y5_a = y5_b - y5_a;
Serial.print("x: ");
Serial.print(x4_a);
Serial.print(" y: ");
Serial.println(y4_a);
Serial.print("x: ");
Serial.print(x5_a);
Serial.print(" y: ");
Serial.println(y5_a);
//Update the timing for the next time around
previousTime = currentTime;
latch = false;
}
int xTolerance = 35;
int yTolerance = 35;
if (abs(x4_a) > xTolerance || abs(y4_a) > yTolerance)
{
latch4 = true;
}
if (abs(x5_a) > xTolerance || abs(y5_a) > yTolerance)
{
latch5 = true;
}
// 4th strand, activate ---
now4 = millis();
if (latch4 == true)
{
if (now4 - startMillis4 >= period)
{
startMillis4 = now4; // save timestamp
if (l >= NUMPIXELS)
{
l = 0; // reset i at max value
pixels4.clear(); // Set all pixel colors to 'off'
latch4 = false;
}
pixels4.setPixelColor( l, pixels4.Color(150 - l * 20, l * 20, 0) );
pixels4.show(); // Send the updated pixel colors to the hardware
l++; // go to next value
}
}
// 5th strand, activate ---
now5 = millis();
if (latch5 == true)
{
if (now5 - startMillis5 >= period)
{
startMillis5 = now5; // save timestamp
if (m >= NUMPIXELS)
{
m = 0; // reset i at max value
pixels5.clear();
latch5 = false;
}
pixels5.setPixelColor( m, pixels5.Color(150 - m * 20, m * 20, 0) );
pixels5.show();
m++; // go to next value
}
}
}
I think there is something off with my placement of "latches." The LED should only go off or trigger if the accelerometers sense a large movement different (based on the tolerance).
Placing time stamp checks inside any conditional block, is often the kiss of death. It's not an automatic failure, but it is a risky hazard that has to be carefully implemented (and it's rarely actually necessary).
There are two LED strands. An LED strand should only go off, light, if its respective accelerometer senses a large enough movement difference (based on a tolerance).
So if accelerometer4 is triggered, LED strand4 should light. If accelerometer5 is triggered, LED strand5 should light. If they are both triggered at the same time, they should both go off. If there is no or little movement, nothing should light.
Which one? Please don't use non-specific language.
From the description in reply #6, there is no functional coupling between the two strips, each one can operate independently. So, you should make one work, and then simply add another one in loop(). To do that, you must ensure that nothing blocks. Instead of duplication, you could also factor the code and create strip objects using a C++ class, or at least use arrays.
You did not yet understand how effective communication about programming works
You have to be very precise. And the highest precisision is to post your actual and complete sketch with added comments where you changed something
What is "the first if-statement"???
What is "second if-statement"???
this is a unprecise description
an un-beatable precise description would be to post you actual and complete sketch.
the main purpose of the forum is to help based on detailed informations = actual and complete sketch. But of course you are free to work on it on your own for how long you ever want
Serial is a great debug assistant.
Send stuff like your latches and other variables through serial, and you might suddenly see what your sketch sees and what it misses.
It will help you pinpoint the problem.
To prevent a too fast scrolling output of serial, build in some delay()s.
Your serial communications and the delays can be commented out when you're done debugging, or in case you're 100% sure debugging is done these lines can be deleted.
// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope
#define dbgi(myFixedText, variableName,timeInterval) \
{ \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
}
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a
// Serial.print is executed
// end of macros dbg and dbgi
// print only once when value has changed
#define dbgc(myFixedText, variableName) \
{ \
static long lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
#define dbgcf(myFixedText, variableName) \
{ \
static float lastState; \
if ( lastState != variableName ){ \
Serial.print( F(#myFixedText " " #variableName" changed from ") ); \
Serial.print(lastState); \
Serial.print( F(" to ") ); \
Serial.println(variableName); \
lastState = variableName; \
} \
}
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__) );
Serial.print( F(" compiled ") );
Serial.print( F(__DATE__) );
Serial.print( F(" ") );
Serial.println( F(__TIME__) );
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
unsigned long MyTestTimer1 = 0; // Timer-variables MUST be of type unsigned long
unsigned long MyTestTimer2 = 0; // Timer-variables MUST be of type unsigned long
const byte OnBoard_LED = 13;
long myLong = 0;
float myFloat = -0.1;
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
}
void loop() {
BlinkHeartBeatLED(OnBoard_LED, 250);
// print value of variable myLong once every 500 milliseconds
dbgi("dbgi1:", myLong, 500);
// print value of variable myLong only if value has CHANGED
// since last time it was printed
dbgc("dbgc1:", myLong);
// print value of variable myFloat only if value has CHANGED
// since last time it was printed
dbgcf("dbgcf:", myFloat);
// check if 2000 milliseconds have passed by
if ( TimePeriodIsOver(MyTestTimer1, 2000) ) {
// when REALLY 2000 milliseconds have passed by
myLong++; // increment variable myLong by 1
}
// check if 6000 milliseconds have passed by
if ( TimePeriodIsOver(MyTestTimer2, 6000) ) {
// when REALLY 6000 milliseconds have passed by
myFloat += 0.5; // incrfement variable myFloat by 0.5
}
}