Web Page Scoreboard Example

From STEAMwiki
Revision as of 12:58, 14 June 2016 by Andy (talk | contribs)
Jump to: navigation, search

To make our marshmallow catapult activity more fun, we built this electronic target with a web page scoreboard.

Target and scoreboard in action: https://vine.co/v/iQ5l0IpKmAq

HTML Scoreboard

https://thimbleprojects.org/dimentians/64210/

Wiring

Connect the 120 pixel neopixel strip to pin D2.

The particle code also has a bunch of code for controlling motors on pins D0 and D1 and a sequence of normal LEDs on D6 and D7. The arrays for these can have more pins added if you want to control more.

In addition to the scoreboard functions to signal points, there are particle functions to control these motors and LEDs.

Particle Arduino Code

Before pasting the Particle Arduino code into your project, include the neopixel library. The online particle code editor (IDE) doesn't automatically do this from the #include statements.


// This #include statement was automatically added by the Particle IDE.
#include "neopixel/neopixel.h"


// Manually control cloud connection in case there isn't one
SYSTEM_MODE(SEMI_AUTOMATIC);



#define PIXEL_PIN D2
#define PIXEL_COUNT 120
#define PIXEL_TYPE WS2812B

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

// How many pulses are visible down the strip at once
#define shipPulseSegments 1
#define shipPulsePixelCount 120

int pixelsPerPulse = shipPulsePixelCount/shipPulseSegments;
int shipPulseColour[shipPulseSegments+1];
float shipPulseOpacity[shipPulseSegments+1];
int shipPulseStep = 0;
int setColour = 0;

// 0 = pixel pulses. 1 = pixel display
int pixelMode = 0;

int motorDelays[] = {0,0,0,0};
int motorPins[] = {D0, D1};

int animPosition = 0;
int animSequence[][6] = { 
{1,0,0,0,0,0}, 
{0,1,0,0,0,0}, 
{0,0,1,0,0,0},
{0,0,0,1,0,0},
{0,0,0,0,1,0},
{0,0,0,0,0,1} };
int LEDPins[] = {D6, D7};
int animSpeed = 10;

// Light sensor code
int lightSensorPins[] = {A0, A1};
int lightSensors[] = {0, 0};
int lightTriggered[] = {0, 0};
int ambientLight[] = {0, 0};
long lightReading = 0;

void setup() {
        // On Photon, Particle.connect() doesn't block if the system mode has been set to SEMI_AUTOMATIC
    Particle.connect();
    pinMode(D7, OUTPUT); 
    
    calibrateSensors();

  // Serial.begin(9600);
    Particle.function("pixelPulse", pixelPulse);
    Particle.function("pixelDisplay", pixelDisplay);
    Particle.function("motorOn", motorOn);
    //Particle.function("setAllColour", setAllColour);
    Particle.function("setAnimSpeed", setAnimSpeed);
    
    for (int i=0; i < 4; i++){
        pinMode(motorPins[i], OUTPUT);
        digitalWrite(motorPins[i], LOW);
    }
    
    for (int i=0; i < 6; i++){
        pinMode(LEDPins[i], OUTPUT);
    }
    
    
    for (int i = 0; i <= shipPulseSegments; i++) {
        shipPulseColour[i] = 0;
        shipPulseOpacity[i] = 0.0;
    }  
    strip.begin();
    strip.show(); // Initialize all pixels to 'off'
    
    // Default show pixels
    //pixelDisplay("39031404");
    
    for (int i = 120; i < 127; i++) {
	    strip.setPixelColor(i, 0, 0, 255);
	}

    for (int i = 127; i < 132; i++) {
	    strip.setPixelColor(i, 255, 0, 0);
	}

    for (int i = 132; i < 137; i++) {
	    strip.setPixelColor(i, 0, 255, 0);
	}

    for (int i = 137; i < 143; i++) {
	    strip.setPixelColor(i, 255, 255, 0);
	}

    Serial.begin(9600);
    
    
}

void loop () {
    
    if (pixelMode == 0) {
        shipPulse();
    } 
    strip.show();
    motorUpdate();
    
    LEDUpdate();
    checkSensors();
   
    delay(20);
}

void calibrateSensors() {
    // Check the ambient light level
    
    for (int i=0; i<2; i++) {
        pinMode(lightSensorPins[i], INPUT);
        lightReading = 0;
        for (int f=0; f<10; f++) {
            lightReading += analogRead(lightSensorPins[i]);
            delay(10);
        }
        ambientLight[i] = lightReading / 10;
    }
}

void checkSensors() {
    
    
    for (int i=0; i<2; i++) {
        lightSensors[i] = analogRead(lightSensorPins[i]);
        
        if(lightTriggered[i] == 0 && lightSensors[i] < (ambientLight[i] -400)) {
            // new light sensor trigger
            lightTriggered[i] = 1;
            Particle.publish("Score", String(i));
            pixelScore(i);
           
            //Serial.println(lightSensors[i]);
        } else if(lightTriggered[i] == 1 && lightSensors[i] >= (ambientLight[i] -400)) {
            // light sensor stopped triggering
            lightTriggered[i] = 0;
            Particle.publish("ScoreOff", String(i));
            pixelPulse("orange");
            //Serial.println(lightSensors[i]);
        }
        
    }
    
    //Serial.println(lightSensors[0]); 
    // marshmellow blocking light = 1200. Ambient = 3000
}

void pixelScore(int sensorNumber) {
    
    // Set pixelMode = 1 to disable the pulses during the display
	pixelMode = 1;
	
	 if (sensorNumber == 0) {
        // Outer ring
        // pixelDisplay("10082030");
        int pixelCount = 0;
        int orangeCount = 120 - 43;
        int blackCount = 43;
        for (int i = 0; i < orangeCount; i++) {
    	    strip.setPixelColor(pixelCount, 255, 180, 0);
    	    pixelCount++;
    	}
    	for (int i = 0; i < blackCount; i++) {
    	    strip.setPixelColor(pixelCount, 0, 0, 0);
    	    pixelCount++;
    	}
    } else if (sensorNumber == 1) {
        // Inner ring. 38 pixels
        int pixelCount = 0;
        int blackCount = 120-38;
        int greenCount = 38;
         for (int i = 0; i < blackCount; i++) {
    	    strip.setPixelColor(pixelCount, 0, 0, 0);
    	    pixelCount++;
    	}
    	for (int i = 0; i < greenCount; i++) {
    	    strip.setPixelColor(pixelCount, 0, 255, 0);
    	    pixelCount++;
    	}
    }

}

void LEDUpdate() {
    animPosition++;
    if (animPosition >= 6 * animSpeed) {
        animPosition = 0;
    }
    
    int animStep = animPosition / animSpeed;
    
    for (int i=0; i < 2; i++){
        digitalWrite(LEDPins[i], animSequence[animStep][i]);
    }
    
    
    
}

void shipPulse() {
  for (int i = 0; i < shipPulseSegments+1; i++) {
    // Each segment. Build one extra segment off to the left, since they are shifted off the end

    for (int f = 0; f <  pixelsPerPulse; f++) {
      int pulsePixelIndex = (i-1)*pixelsPerPulse + f + shipPulseStep;
      if (pulsePixelIndex >= 0 && pulsePixelIndex < shipPulsePixelCount) {
        // don't bother with the pixels that have left out the side
        // Each pixel within a segment

        if (shipPulseColour[i] == 0) {
          // Black pixel
            strip.setPixelColor(pulsePixelIndex, strip.Color(0,0,0));
        } 
        else {
          // Fade the pixel out as it get further away from the brightest one
          
          float pixelOpacity = float(f) / float(pixelsPerPulse) * float(f) / float(pixelsPerPulse) * float(f) / float(pixelsPerPulse) * shipPulseOpacity[i];
          uint32_t thisPulsePixel = Wheel(shipPulseColour[i], pixelOpacity);
          
          strip.setPixelColor(pulsePixelIndex, thisPulsePixel);
          
        }
      }
    }
  }

  shipPulseStep++;
  if (shipPulseStep > pixelsPerPulse) {

    // Push the existing colours down one
    int oldColour = shipPulseColour[shipPulseSegments-1];
    float oldOpacity = shipPulseOpacity[shipPulseSegments-1];

    for (int i = shipPulseSegments; i > 0; i--) {
      shipPulseColour[i] = shipPulseColour[i-1];
      shipPulseOpacity[i] = shipPulseOpacity[i-1];
    }  

    // Fade out old colours
    if (oldColour > 0) {
      Serial.println(oldOpacity);
    }

    if (oldOpacity > 0.1) {
      // loop - repeat the same colour
      
      shipPulseColour[0] = oldColour;
      shipPulseOpacity[0] = oldOpacity * 0.3;
      
      
      // Disable looping
      //shipPulseOpacity[0] = 0;
    } 
    else {

      // Randomize what to do next
      int nextAction = random(10);
      
      // Never make a new pulse, since this is now triggered by the function pixelPulse()
      //int nextAction = 2;
      
      // Serial.println(nextAction);
      
     
      if (nextAction == 0) {
        // Add a new colour
        int newPosition = random(shipPulseSegments);
        int newColour = random(256);
        if (setColour == 0) {
            shipPulseColour[newPosition] = newColour;
        } else {
            shipPulseColour[newPosition] = setColour;
        }
        shipPulseOpacity[newPosition] = 1.0;
      } 
      else {
        // Set to black
        shipPulseColour[0] = 0;
        shipPulseOpacity[0] = 0.0;
      }
    }

    shipPulseStep = 0;
    //Serial.println(shipPulseStep); 
  }
}



int setAnimSpeed(String command) {
    animSpeed = command.toInt();
    return 1;
}

int setAllColour(String command) {
    setColour = command.toInt();
    return 1;
}


int pixelPulse(String command) {
    pixelMode = 0;
    
	// Add a new colour
    int newPosition = 0;
    int newColour = random(256);
    if (command == "red") {
        newColour = 85;
    } else if (command == "orange") {
        newColour = 63;
    } else if (command == "yellow") {
        newColour = 42;
    } else if (command == "cyan") {
        newColour = 212;
    } else if (command == "green") {
        newColour = 255;
    } else if (command == "blue") {
        newColour = 170;
    } else if (command == "violet") {
        newColour = 227;
    } else if (command == "pink") {
        newColour = 110;
    }
    
    shipPulseColour[newPosition] = newColour;
    shipPulseOpacity[newPosition] = 1.0;
    return 1;
}

int pixelDisplay(String command) {
    
    // Set pixelMode = 1 to disable the pulses during the display
	pixelMode = 1;
	
	int blueCount   = command.substring(0, 2).toInt();
	int redCount    = command.substring(2, 4).toInt();
	int orangeCount = command.substring(4, 6).toInt();
	int greenCount  = command.substring(6, 8).toInt();
	
	int firstDisplayPixel = 0;
	int pixelCount = firstDisplayPixel;

	for (int i = 0; i < blueCount; i++) {
	    strip.setPixelColor(pixelCount, 0, 0, 255);
	    pixelCount++;
	}
	for (int i = 0; i < redCount; i++) {
	    strip.setPixelColor(pixelCount, 255, 0, 0);
	    pixelCount++;
	}
	for (int i = 0; i < orangeCount; i++) {
	    strip.setPixelColor(pixelCount, 255, 180, 0);
	    pixelCount++;
	}
	for (int i = 0; i < greenCount; i++) {
	    strip.setPixelColor(pixelCount, 0, 255, 0);
	    pixelCount++;
	}
	return 1;
}

int motorOn(String command) {
    int motorPin = A0;
    
    if (command == "0") {
        motorPin = motorPins[0];
        motorDelays[0] = millis() + 5000;
        
    } else if (command == "1") {
        motorPin = motorPins[1];
        motorDelays[1] = millis() + 5000;
    } else if (command == "2") {
        motorPin = motorPins[2];
        motorDelays[2] = millis() + 5000;
    } else if (command == "3") {
        motorPin = motorPins[3];
        motorDelays[3] = millis() + 5000;
        
    } else if (command == "4") {
        motorPin = motorPins[4];
        motorDelays[4] = millis() + 5000;
    }
        
    digitalWrite(motorPin, HIGH);
}

int motorUpdate() {
    for (int i=0; i < 4; i++){
        if (motorDelays[i] != 0) {
            if (motorDelays[i] < millis()) {
                digitalWrite(motorPins[i], LOW);
                motorDelays[i] = 0;
            }
        }
    }
}


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos, float opacity) {

  if(WheelPos < 85) {
    return strip.Color((WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity, 0);
  } 
  else if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color((255 - WheelPos * 3) * opacity, 0, (WheelPos * 3) * opacity);
  } 
  else {
    WheelPos -= 170;
    return strip.Color(0, (WheelPos * 3) * opacity, (255 - WheelPos * 3) * opacity);
  }
}

<\pre>