//Jumper code(applicable for both particle boards)
//Designing for IoT 12/12/2019
// Source for light strip code: https://learn.adafruit.com/rgb-led-strips/arduino-code
#define REDPIN A3
#define GREENPIN A4
#define BLUEPIN A2
#define FADESPEED 5 // make this higher to slow down
//variables for controlling the light strip
int lastFade = 0;//the variable recording the time entering the light pattern function
int timeElapsed=0;//record the current time
int colorValue = 0; //the color we're going to assign to the light strip
int redValue = 0;
int blueValue = 0;
bool ifNotify=false;//controlling if the reminder is on
//these 10 variables are the time intervals for the light pattern when the player wins
int timerDuration =500;
int timerDuration2 =1000;
int timerDuration3 = 1500;
int timerDuration4 = 2000;
int timerDuration5 = 2500;
int timerDuration6 = 3000;
int timerDuration7 = 3500;
int timerDuration8 = 4000;
int timerDuration9 = 4500;
int timerDuration10 = 5000;
// Define a pin that we'll place the FSR on
// Remember to add a 10K Ohm pull-down resistor too.
int fsrPin = A0;
int fsrReading = 0;
int countChannel=0;//this variable is part of the counting logic
// Create a variable to store the LED brightness.
int ledBrightness = 0;
int d1 = 1000;//time interval for updating the servo
int highReading=1000;//thresholds of couting the pressure as one jump
int lowReading=100;
int jumpCount=0;//jump count for this player
String JC=" ";//medium to store received data from the other player
int jumpCount2=0;//jump count for the other player
int servoPin = D6;
Servo myServo;
int servoPos = 90;//initial position of the servo(arrow)
int LastClick=0;//the variable recording the time entering the servo update function
int Subtraction=0;//updated angle of the servo
bool refreshtimeOrNot=false;//part of the logic to make sure cloud event is published once for each time
long lastPublishedAt = 0;// This value will store the last time we published an event
int publishAfter = 1000;// this is the time delay before we should publish a new event from this device
int now=0;//variable recording current time
bool otherSideOn=false;//variable indicating if the other player is there
bool updateOrNot=true;//controlling if we want to update the servo
//(part of the logic to prevent the outdated cloud data from affecting the servo)
int lastUpdate=0;//last time we enable servo update
int updateDelay=3000;//the time span we want to lock the update
void setup() {
// Set up the LED for output
pinMode(REDPIN, OUTPUT);
pinMode(GREENPIN, OUTPUT);
pinMode(BLUEPIN, OUTPUT);
Particle.variable("force", &fsrReading, INT);
Particle.variable("count", &jumpCount, INT);
Particle.variable("count2", &jumpCount2, INT);
Particle.variable("Subtraction", &Subtraction, INT);
Particle.variable( "Last", LastClick);
Particle.variable( "now", now);
Particle.variable( "ledBrightness", ledBrightness);
Particle.variable( "otherSideOn", otherSideOn);
// attaches the servo on the D6 pin to the servo object
myServo.attach(servoPin);
//cloud function for testing
Particle.function("servo", servoControl);
Particle.function("updateservo", outerUpdate2);
Particle.function("resetCount", resetCount);
Particle.variable( "servoPos" , &servoPos , INT );// Keep a cloud variable for the current position
Particle.subscribe( "diot/2019/paired/jumper/update" , handleSharedEvent );//receiving jumpcount data from the other player
Particle.function( "beginRemind", reminder);//a function that enables light strip pattern when this player wins
}
void loop() {
// Use analogRead to read the photo cell reading
// This gives us a value from 0 to 4095
fsrReading = analogRead(fsrPin);
// Map this value into the PWM range (0-255)
// and store as the led brightness
ledBrightness = map(fsrReading, 200, 4095, 0, 100);
if(fsrReading<200){
ledBrightness=0;//prevent the light strip from blinking when there is low pressure on FSR
}
if(ifNotify==false){//when we don't want the light strip to show the winning pattern
lastFade=millis();
if(otherSideOn){//when the other player is there, show the mixed color on the light strip
analogWrite(GREENPIN, ledBrightness);
analogWrite(REDPIN, ledBrightness);
analogWrite(BLUEPIN, ledBrightness);
}else{//otherwise we only show green light(or one of the RGB color)
analogWrite(GREENPIN, ledBrightness);
analogWrite(REDPIN, 0);
analogWrite(BLUEPIN,0);
}
}else{//when we need the light strip to show the winning pattern
reminder("");//turn on the winning pattern
}
//part of the jump counting logic, we need to detect a high to low pressure fluctuation to count as one jump
if(countChannel==0){
Channel0();//enter this function when detecting high pressure
}else if(countChannel==1){
Channel1();//enter this function when detecting low pressure
}
//final calculated angle for the servo representing the substraction between the jump counts of 2 players
Subtraction=90-(jumpCount-jumpCount2)*4;
// update the servo
outerUpdate();
if(Subtraction<10){//when this player is winning
updateOrNot=false;//stop updating jump count data from the other player to prevent servo's angle reset failure
resetCount(" ");//reset the servo
ifNotify=true;//enable the winning pattern of the light strip
}else if(Subtraction>170){//when this player loses
resetCount(" ");//reset the servo
}
if(updateOrNot==false){//when not updating the servo
lockUpdate();
}else{
lastUpdate=millis();//update the timer
}
}
void Channel0(){
if(fsrReading>highReading){//when detecting high pressure
countChannel=1;//entering next channel
}
}
void Channel1(){
if(fsrReading<lowReading){//when detecting low pressure after previous high reading
countChannel=0;//switch back to the previous channel
jumpCount++;//add up to the jump count
}
}
void outerUpdate(){//when we want to update the servo
now=millis();
if(refreshtimeOrNot==false)
{//if it's false, run the following code for once
LastClick=millis();//initialize the timer of the update function
refreshtimeOrNot=true;//make sure the codes here only run once each time
}
if(now>LastClick+d1){//run these lines every d1 milliseconds
publishMyEvent();//send the jumpcount of this player to the other player
outerUpdate2(" ");//update the servo
LastClick=now;//record the last update time
}
}
int outerUpdate2(String command){//function for servo update
servoControl( String(Subtraction));
return 1;
}
int servoControl(String command)//function for servo update
{
// Convert
int newPos = command.toInt();
// Make sure it is in the right range
// And set the position
servoPos = constrain( newPos, 9 , 171);
// Set the servo
myServo.write( servoPos );
// done
return 1;
}
void publishMyEvent()//publish event when telling the other friend the person using this board is available
{
// Remember that a device can publish at rate of about 1 event/sec,
// with bursts of up to 4 allowed in 1 second.
// Back to back burst of 4 messages will take 4 seconds to recover.
// So we want to limit the amount of publish events that happen.
// check that it's been 10 seconds since our last publish
if( lastPublishedAt + publishAfter < millis() )
{
// Remember our subscribe is matching "db2018/paired/"
// We'll append the device id to get more specific
// about where the event came from
// System.deviceID() provides an easy way to extract the device
// ID of your device. It returns a String object of the device ID,
// which is used to identify your device.
String eventName = "diot/2019/paired/jumper/update" + System.deviceID();
// now we have something like "diot/2019/paired/0123456789abcdef"
// and that corresponds to this devices info
// then we share the jump count of this player out
Particle.publish( eventName, String(jumpCount));
// And this will get shared out to all devices using this code
// we just published so capture this.
lastPublishedAt = millis();
}
}
void handleSharedEvent(const char *event, const char *data)//when receiving function that the the other friend is available, execute the following codes
{
// Now we're getting ALL events published using "db2018/paired/"
// This includes events from this device.
// So we need to ignore any events that we sent.
// Let's check the event name
String eventName = String( event ); // convert to a string object
// This gives us access to a bunch of built in methods
// Like indexOf()
// Locates a character or String within another String.
// By default, searches from the beginning of the String,
// but can also start from a given index,
// allowing for the locating of all instances of the character or String.
// It Returns: The index of val within the String, or -1 if not found.
// We can use this to check if our event name contains the
// id of this device
String deviceID = System.deviceID();
// device id = 0123456789abcdef
// event = "diot/2019/paired/0123456789abcdef"
if( eventName.indexOf( deviceID ) != -1 ){
// if we get anything other than -1
// the event came from this device.
// so stop doing stuff
return;
}else{ // otherwise do your stuff to respond to
// the paired device here
JC=data;//use JC to transfer the received data to string
if(JC!="reset"){ //if not informed to reset angle
if(updateOrNot==true){//and when the update is not locked
jumpCount2=JC.toInt();//accept the other player's jump count
}
if(jumpCount2>=1 ){//when there is another player out there
otherSideOn=true;
}
}else{//when this board is told by the other board to reset
//reset the servo
JC="0";
jumpCount=0;
jumpCount2=0;
updateOrNot=false;//do not receive other oudated data to prevent reset failure
}
}
}
int resetCount(String command)
{
//reset this servo
JC="0";
jumpCount=0;
jumpCount2=0;
String eventName = "diot/2019/paired/jumper/update" + System.deviceID();
Particle.publish( eventName, "reset");//tell the other board to reset as well
return 1;
}
void lockUpdate(){//lock the servo from updating
if (lastUpdate<millis()-updateDelay){//the lock will continue for a while
updateOrNot=true;
}
}
int reminder(String anystr){
//enbale winning pattern for the light strip(not a smart way to do it but a quick and dirty way to get the job done)
timeElapsed = millis() -lastFade; //let the timer begin from 0
if( timeElapsed < timerDuration ){//First 500 millisec: turn blue
int colorValue = map( timeElapsed, 0, timerDuration, 0 , 255 );
int blueValue = colorValue;
analogWrite(BLUEPIN, blueValue);
}else if(timeElapsed < timerDuration2){//Middle 10 minutes: It should slowly transition to red over the course of the next 500 millisec
colorValue = map( timeElapsed, timerDuration, timerDuration2, 0 , 255 );
int redValue = colorValue;
blueValue = 255 - colorValue;
analogWrite(BLUEPIN, blueValue);
analogWrite(REDPIN, redValue);
} else if(timeElapsed < timerDuration3){//repeat the process
colorValue = map( timeElapsed, timerDuration2, timerDuration3, 0 , 255 );
blueValue = colorValue;
redValue = 255-colorValue;
analogWrite(BLUEPIN, blueValue);
analogWrite(REDPIN, redValue);
}else if(timeElapsed < timerDuration4){//repeat the process
colorValue = map( timeElapsed, timerDuration3, timerDuration4, 0 , 255 );
redValue = colorValue;
blueValue = 255 - colorValue;
analogWrite(BLUEPIN, blueValue);
analogWrite(REDPIN, redValue);
}else if(timeElapsed < timerDuration5){//repeat the process
colorValue = map( timeElapsed, timerDuration4, timerDuration5, 0 , 255 );
blueValue = colorValue;
redValue = 255-colorValue;
analogWrite(BLUEPIN, blueValue);
analogWrite(REDPIN, redValue);
}else if(timeElapsed < timerDuration6){//repeat the process
colorValue = map( timeElapsed, timerDuration5, timerDuration6, 0 , 255 );
redValue = colorValue;
blueValue = 255 - colorValue;
analogWrite(BLUEPIN, blueValue);
analogWrite(REDPIN, redValue);
}else if(timeElapsed < timerDuration7){//repeat the process
colorValue = map( timeElapsed, timerDuration6, timerDuration7, 0 , 255 );
blueValue = colorValue;
redValue = 255-colorValue;
analogWrite(BLUEPIN, blueValue);
analogWrite(REDPIN, redValue);
}else if(timeElapsed < timerDuration8){//repeat the process
colorValue = map( timeElapsed, timerDuration7, timerDuration8, 0 , 255 );
redValue = colorValue;
blueValue = 255 - colorValue;
analogWrite(BLUEPIN, blueValue);
analogWrite(REDPIN, redValue);
}else if(timeElapsed < timerDuration9){//repeat the process
colorValue = map( timeElapsed, timerDuration8, timerDuration9, 0 , 255 );
blueValue = colorValue;
redValue = 255-colorValue;
analogWrite(BLUEPIN, blueValue);
analogWrite(REDPIN, redValue);
}else if(timeElapsed < timerDuration10){// fade out to off.
colorValue = map( timeElapsed, timerDuration9, timerDuration10, 0 , 255 );
blueValue = 255-colorValue;
analogWrite(BLUEPIN, blueValue);
}
else{//turn off the lights when the routine finishes
analogWrite(REDPIN, 0);
analogWrite(GREENPIN, 0);
analogWrite(BLUEPIN, 0);
ifNotify=false;//end the winning pattern
otherSideOn=false;//refresh the other player's state,assume they leave next round(if they do not, this boolean will be true again)
}
return 0;
}
Click to Expand
Content Rating
Is this a good/useful/informative piece of content to include in the project? Have your say!
You must login before you can post a comment. .