Hello,
I have this code where 3 (or more) vibration motors are controlled by corresponding resistive force sensors. Each force sensor's analog value gets assigned a force level 0-3, 0 being no touch, and 3 being the maximum force. Every time the force level changes, the vibration motor that corresponds to that sensor should pulse. The RGB LED should show the current force level as a color (although this will be mixed if more than one sensor is pressed, not ideal).
This was working great with 1 sensor, one motor. When I added more, I knew I didn't want to just copy and paste, it would be bulky and hard to edit. As I did some research, it seemed arrays and for loops would give me the ability to scale it up. And it has worked, the LED color changing works, and the vibration motors pulse, for each set of sensors/motors. But maybe someone can help me fix the following-
The issues I know of:
-
When I press sensor no. 1 and no. 2 for example, I get all three vibration motors going off, though somewhat sporadically. But how is motor no. 3 getting any output from the for loop if sensor no. 3 is not being pressed and showing a value of 0?
-
The last force sensor in the array seems to be giving the other 2 a small signal of 20-40 when pressed (happens after this sensor reaches force level 2). I think this is the root of the problem but cannot figure out why it is happening.
-
I don't think my assignForceLevel() or pulseLed() are in the tidiest form, and am thinking that could be the source of the above problem. There is a lot of repetition in both, with a string of if/else statements. I would love any ideas for restructuring anything and everything to achieve the functionality and the scalability.
Code and schematic are posted below.
Thank you!
const int NUM_LEDS = 3; //number of leds + 1 for off state
//const int calButton = 3; //Button for calibration
const int sensorPin[] = {18,19,20}; //sensor pins
const int NUM_FINGERS = sizeof(sensorPin)/sizeof(sensorPin[0]); // set number of fingers equal to number of sensor pins defined
const int vtPin[NUM_FINGERS] = {4,5,6};
const int LEDPinArray[NUM_LEDS] = { 10,11,12 }; //array used to set up all leds
unsigned long currentMillis;
unsigned long previousMillis;
const long pulseTime = 150;
int sensorValue[NUM_FINGERS] = {0,0,0}; //intitial sensorValue
int forceLevel[NUM_FINGERS] = {0,0,0};
bool flag1[NUM_FINGERS];
bool flag2[NUM_FINGERS];
bool flag3[NUM_FINGERS];
const int goalminV = 0; //low end of range to map to
const int goalmaxV = 1023; //high end of range to map to
int minV = 0; //intitial minimum to be
int maxV = 1023; //intitial maximum to be
int split1 = goalmaxV / NUM_LEDS; //splitting point between LED 1 and 2
int split2 = split1 * 2; //splitting point between LED 2 and 3
String p1 = "_";
void powerOnSelectedLEDOnly(int index) //power on each led based on whether it is selected
{
for (int i = 0; i < NUM_LEDS; i++) {
if (i == (index - 1)) {
digitalWrite(LEDPinArray[i], HIGH);
} else {
digitalWrite(LEDPinArray[i], LOW);
}
}
}
void initAllLEDs() { //set up all led pins as OUTPUT
for (int i = 0; i < NUM_LEDS; i++) {
pinMode(LEDPinArray[i], OUTPUT);
}
}
void initAllVTs() { //set up all VT pins as OUTPUT
for (int i = 0; i < NUM_FINGERS; i++) {
pinMode(vtPin[i], OUTPUT);
}
}
void assignForceLevel() {
for (int i = 0; i < NUM_FINGERS; i++) {
if ((sensorValue[i] > 0) && (sensorValue[i] < split1)) {
forceLevel[i] = 1;
} else if ((sensorValue[i] > split1) && (sensorValue[i] < split2)) {
forceLevel[i] = 2;
} else if (sensorValue[i] > split2) {
forceLevel[i] = 3;
} else {
forceLevel[i] = 0;
}
}
}
void pulseVts() {
for (int i = 0; i < NUM_FINGERS; i ++) { //turn on VT
if ((forceLevel[i] == 1) && (flag1[i] == 0)) {
digitalWrite(vtPin[i], HIGH);
flag1[i] = 1;
previousMillis = millis() + pulseTime; //get the current "time" (actually the number of milliseconds since the program started)
}
if ((digitalRead(vtPin[i] == HIGH)) && (millis() >= previousMillis)) {
digitalWrite(vtPin[i], LOW);
if (forceLevel[i] != 1) {
flag1[i] = 0;
}
}
if ((forceLevel[i] == 2) && (flag2[i] == 0)) {
digitalWrite(vtPin[i], HIGH);
flag2[i] = 1;
previousMillis = millis() + pulseTime; //get the current "time" (actually the number of milliseconds since the program started)
}
if ((digitalRead(vtPin[i] == HIGH)) && (millis() >= previousMillis)) {
digitalWrite(vtPin[i], LOW);
if (forceLevel[i] != 2) {
flag2[i] = 0;
}
}
if ((forceLevel[i] == 3) && (flag3[i] == 0)) {
digitalWrite(vtPin[i], HIGH);
flag3[i] = 1;
previousMillis = millis() + pulseTime; //get the current "time" (actually the number of milliseconds since the program started)
}
if ((digitalRead(vtPin[i] == HIGH)) && (millis() >= previousMillis)) {
digitalWrite(vtPin[i], LOW);
if (forceLevel[i] != 3) {
flag3[i] = 0;
}
}
}
}
void setup() {
// put your setup code here, to run once:
initAllLEDs();
initAllVTs();
//pinMode(calButton, INPUT);
//pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
previousMillis = millis();
}
void loop() {
// put your main code here, to run repeatedly:
for (int i = 0; i < NUM_FINGERS; i ++) { //read sensorValues continuously
int readVal = analogRead(sensorPin[i]);
sensorValue[i] = readVal;
}
assignForceLevel();
pulseVts();
for (int i = 0; i < NUM_FINGERS; i ++) { //print sensor values
Serial.println(sensorValue[i] + p1 + sensorValue[i] + p1 + minV + p1 + maxV + p1 + forceLevel[i] + p1 + flag2[i] + p1 + digitalRead(vtPin[i]));
powerOnSelectedLEDOnly(forceLevel[i]);
}
delay(50);
//calibrateWhile();
}
/*void calibrate() {
digitalWrite(LED_BUILTIN, HIGH);
for (int i = 0; i < NUM_FINGERS; i ++) {
int readVal = analogRead(sensorPin[i]);
sensorValue[i] = readVal;
//maxV = 0;
if (sensorValue[i] > maxV) {
maxV = sensorValue[i];
}
if (sensorValue[i] < minV) {
minV = sensorValue[i];
}
}
}
void calibrateWhile(){
while (digitalRead(calButton) == 1) //recalibrate min and max when button is pressed
{
maxV = 0;
calibrate();
Serial.println("Calibrating...");
for (int i = 0; i < NUM_FINGERS; i ++) {
Serial.println(analogRead(sensorPin[i]) + p1 + goalminV + p1 + goalmaxV + p1 + forceLevel[i]);
}
if (digitalRead(calButton) == 0) {
break;
}
}
digitalWrite(LED_BUILTIN, LOW); // turn led off to show calibration is done
}*/```

