Back to Parent

//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!

0