Hi all,
I'm trying to help out a buddy with a project he's working on, basically involves having an accelerometer drive a series of 64 LEDs (8 clusters of 8 LEDs), he's using the following equipment:
The basic idea is that the more the accel moves, the "faster" light should travel around the ring (the 8 clusters of 64 LEDs are arranged in a circle)
I came up with a few ideas to get things running smoothly:
- polling the current value of accelerometer and comparing to the previous value, using 180 and some absolute value arithmetic to make a shift from 359 to 1 degree or vice versa not so drastic:
void speedcalculate(){
//abs value
absX[0] = abs(x-180);
absY[0] = abs(y-180);
absZ[0] = abs(z-180);
//acceleration
accelerationX = (abs(absX[0]-absX[1]));
//velocity
velocityX[0] = (velocityX[1] + accelerationX);
velocityX[0] = constrain(velocityX[0], 0, maxvel);
velocityX[0] = map_double(velocityX[0], 0, maxvel, 0, 8);
intVelocityX = (int) velocityX[0];
- because we are using the shift registers to control the LEDs, all we can do is run them HIGH or LOW, so instead of controlling PWM values, I am thought we would use an array of 8 values where the index represents the shift register in question, and the value it is storing (a number between 0 and 8) represents how many LEDs should be on in that cluster. I thought I could accomplish this with this bit of code:
//velocity -> LED cup translation
for (int i = 0; i < 8; i++) {
if(i == 0) {
if (ModulePast[i] > 0 && ModulePast[i] >= ModulePast[1] && ModulePast[i] >= ModulePast[2] && ModulePast[i] >= ModulePast[3] && ModulePast[i] >= ModulePast[4] && ModulePast[i] >= ModulePast[5] && ModulePast[i] >= ModulePast[6] && ModulePast[i] >= ModulePast[7]) {
ModuleNow[i] = ModulePast[i];
ModuleNow[i] -= intVelocityX;
ModuleNow[7] += intVelocityX;
constrain(ModuleNow[i], 0, 8);
constrain(ModuleNow[7], 0, 8);
}
}
else if (ModulePast[i] > 0 && ModulePast[i] >= ModulePast[0] && ModulePast[i] >= ModulePast[1] && ModulePast[i] >= ModulePast[2] && ModulePast[i] >= ModulePast[3] && ModulePast[i] >= ModulePast[4] && ModulePast[i] >= ModulePast[5] && ModulePast[i] >= ModulePast[6] && ModulePast[i] >= ModulePast[7]) {
ModuleNow[i] = ModulePast[i];
ModuleNow[i] -= intVelocityX;
ModuleNow[i-1] += intVelocityX;
constrain(ModuleNow[i], 0, 8);
constrain(ModuleNow[i-1], 0, 8);
}
the if i == 0 part was to compensate for trying to make the loop continuous (IE if there are LEDs on in module 0, they should move to module 7 as they're next to each other in the loop). The long chain boolean AND statements (ModulePast >= ModulePast[1]) was a dumb way of trying to come up with a way where the code would only execute if the value of that register was highest value in the entire array, but I now realize there is even a problem with this, as it would only get to 4 before it would stop executing. <- the basic behavior we are after is that if you think of the 8 LEDs on a single shift register as a cup, they should transfer intVelocityX LEDs to the next module every loop, with intVelocityX being an integer between 0 and 8 which is a number given by the accelerometer/speed calculation.
the last bit of code would take the numbers stored in the array and turn the appropriate pins HIGH based on the value it found for that register:
```
*//write LEDs
shifter.clear();
for (int i = 0; i < 8; i++) {
for (int j = 0; j <= ModuleNow[i]; j++) {
ledOn = ((8 * i) + j);
Serial.println(ledOn);
shifter.setPin(ledOn, HIGH);
}
}
shifter.write();*
```
Will post a hypothetical run through of what we want to happen in following post...