The code below represents a blood-level meter made with arduino with 5 different states: Standby, and showing water, sugar, caffeine or alcohol-level.
Most of the time it works well, but sometimes it starts lagging a lot, and the touch sensor that changes states does not give any response. Now the problem is not in the hardware, because with earlier versions of the software, the problem with the touch sensor does not appear.
I added Serial.prints to the start of all functions to see when the lag appeared, and the last print before lagging was always changeState(), so maybe the problem is somewhere in there. Or maybe has something to do with the attachInterrupt?
Oh and if you see improvements, they are always welcome!
//-------------------------
//--------Libraries--------
//-------------------------
#include <ChainableLED.h>
//-------------------------
//---Sensors & Actuators---
//-------------------------
#define lightSensor 8
#define touchSensor 2
#define vibrationMotor 4
//ChainableLED
#define clkPin A2
#define dataPin A3
#define numLEDS 1
//-------------------------
//--------Variables--------
//-------------------------
ChainableLED leds(clkPin,dataPin,numLEDS);
//Blood-levels
byte waterLVL = 50, sugarLVL = 40, drunkCaffeine, caffeineLVL = 20, drunkAlcohol, alcoholLVL = 30;
boolean waterWarn = false, sugarWarn = false, caffeineWarn = false, alcoholWarn = false;
byte bloodCounter = 0;
#define updateTime 50 //Update blood-levels every 5 seconds;
#define maxLVL 40
int touchTime = 0;
byte vibrateCount = 0;
#define shortVibration 3
#define longVibration 10
boolean isOn = false; //Does lightsensor detect light? If so, device is on
#define minLight 500 //Minimum amount of light detected to turn off Standby
byte stateCounter = 0; //Amount of time state is visible
#define delayTime 100 //Amount of ms to wait after loop
#define stateWaitTime 50 //Time state stay in focus until they change back to water
byte curR = 0; //Current RGB-values for led
byte curG = 0;
byte curB = 0;
#define colorSteps 15
//-------------------------
//------Setup & Loop-------
//-------------------------
void setup() {
Serial.begin(9600);
leds.init();
pinMode(touchSensor, INPUT);
pinMode(lightSensor, INPUT);
pinMode(vibrationMotor, OUTPUT);
//getRandomBloodValues();
attachInterrupt(touchSensor-2, increaseState, RISING);
delay(3000);
}
void loop() {
//updateBloodValues();
//getWarning();
//updateStateMachine();
delay(delayTime);
}
//-------------------------
//------Conditions---------
//-------------------------
boolean isLight() {
if (digitalRead(lightSensor) == HIGH) {
return true;
} else return false;
}
//-------------------------
//-----State machines------
//-------------------------
enum curState {Standby, Water, Sugar, Caffeine, Alcohol};
curState state;
void updateStateMachine() {
switch (state) {
// Wearable staat in standby
case Standby:
if (isLight()) {state = Water; changeColour(0,0,255);}
break;
// Wearable toont waterniveau en 3 leds die aangeven
//of caffeine en/of alcohol aanwezig zijn in het bloed
case Water:
if(!isLight()){
state = Standby;
break;
}
break;
// Wearable toont suikerniveau in bloed
case Sugar:
if(changeState()){break;}
stateCounter++;
break;
// Wearable toont caffeine-niveau in bloed
case Caffeine :
if(changeState()){break;}
stateCounter++;
break;
// Wearable toont alcohol-niveau in bloed
case Alcohol :
if(changeState()){break;}
stateCounter++;
break;
} // end switch
} // end updateStateMachine
//-------------------------
//----AttachInterrupts-----
//-------------------------
void increaseState() {
switch (state) {
case Standby:
state = Water;
stateCounter = 0;
changeColour(0,0,map(waterLVL, 0, 100, 0, 255));
break;
case Water:
state = Sugar;
stateCounter = 0;
changeColour(map(sugarLVL, 0, 100, 0, 255),map(sugarLVL, 0, 100, 0, 255),0);
break;
case Sugar:
if(caffeineLVL>0){
state = Caffeine;
changeColour(0,map(caffeineLVL, 0, 100, 0, 255),0);
}
else if (alcoholLVL>0){
state = Alcohol;
changeColour(map(alcoholLVL, 0, 100, 0, 255), 0, map(alcoholLVL, 0, 100, 0, 255));
}
else{
state=Water;
changeColour(0,0,map(waterLVL, 0, 100, 0, 255));
}
stateCounter = 0;
break;
case Caffeine:
if(alcoholLVL>0){
state = Alcohol;
changeColour(map(alcoholLVL, 0, 100, 0, 255),0,map(alcoholLVL, 0, 100, 0, 255));
}
else{
state = Water;
changeColour(0,0,map(waterLVL, 0, 100, 0, 255));
}
stateCounter = 0;
break;
case Alcohol:
state = Water;
stateCounter = 0;
changeColour(0,0,map(waterLVL, 0, 100, 0, 255));
break;
}
}
//-------------------------
//--------Actions----------
//-------------------------
boolean changeState(){
if(!isLight){
state = Standby;
return true;
}
else if(stateCounter > stateWaitTime){
state = Water;
changeColour(0,0,255);
stateCounter = 0;
return true;
}
return false;
}
void updateBloodValues(){
if(bloodCounter > updateTime){
if(!waterLVL <= 0){waterLVL -= 10;}
if(!sugarLVL <= 0){sugarLVL -= 10;}
if(!caffeineLVL <= 0){caffeineLVL -= 10;}
if(!alcoholLVL <= 0){alcoholLVL -= 10;}
bloodCounter = 0;
/*Serial.println("");
Serial.print("Water level = ");Serial.println(waterLVL);
Serial.print("Sugar level = ");Serial.println(sugarLVL);
Serial.print("Caffeine level = ");Serial.println(caffeineLVL);
Serial.print("Alcohol level = ");Serial.println(alcoholLVL);
Serial.println("");*/
}
else bloodCounter++;
}
void getWarning(){
if(waterLVL < 20 && waterWarn == false){
state = Water;
vibrate(shortVibration);
waterWarn = true;
} else if(waterLVL > 20) waterWarn = false;
if(sugarLVL > maxLVL && sugarWarn == false){
Serial.println("Watch out for the sugar!");
state = Sugar;
vibrate(shortVibration);
sugarWarn = true;
} else if(sugarLVL <= maxLVL) sugarWarn = false;
if(caffeineLVL > maxLVL && caffeineWarn == false){
Serial.println("Watch out for the caffeine");
state = Caffeine;
vibrate(shortVibration);
caffeineWarn = true;
} else if(caffeineLVL <= maxLVL) caffeineWarn = false;
if(alcoholLVL > maxLVL && alcoholWarn == false){
Serial.println("Watch out for the alcohol!");
state = Alcohol;
vibrate(shortVibration);
alcoholWarn = true;
} else if(alcoholLVL <= maxLVL) alcoholWarn = false;
}
void vibrate(byte reps){
do{
digitalWrite(vibrationMotor, HIGH);
vibrateCount++;
delay(100);
} while(vibrateCount< reps+1);
digitalWrite(vibrationMotor, LOW);
vibrateCount = 0;
}
void changeColour(byte newR, byte newG, byte newB){
for(int i=0; i<colorSteps+1; i++){
leds.setColorRGB(0, (curR-(i*((curR-newR)/colorSteps))), curG-(i*(curG-newG)/colorSteps), curB-(i*(curB-newB)/colorSteps));
delay(35);
}
curR = newR; curG = newG; curB = newB;
}