Web Page Scoreboard Example

From STEAMwiki
Revision as of 20:20, 27 September 2019 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.

<syntaxhighlight lang="C++">

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

  1. include "neopixel/neopixel.h"


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


  1. define PIXEL_PIN D2
  2. define PIXEL_COUNT 120
  3. 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

  1. define shipPulseSegments 1
  2. 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; int triggerLevel;

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;
   }
   
   triggerLevel = (ambientLight[0] + ambientLight[1]) / 8;
   if (triggerLevel > 300) {
       triggerLevel = 300;
   }
   
   Particle.publish("triggerLevel", String(triggerLevel));

}

void checkSensors() {

   for (int i=0; i<2; i++) {
       lightSensors[i] = analogRead(lightSensorPins[i]);
       
       
       
       if(lightTriggered[i] == 0 && lightSensors[i] < (ambientLight[i] -triggerLevel)) {
           // 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] -triggerLevel)) {
           // light sensor stopped triggering
           lightTriggered[i] = 0;
           Particle.publish("ScoreOff", String(i));
           pixelPulse("orange");
           //Serial.println(lightSensors[i]);
       }
       
   }
   
   // Serial.println(lightSensors[1]); 
   // sensor 0
   // Ambient at SL = 650
   // Projectile blocking = 280
   // sensor 1
   // Ambient at SL = 680
   // Projectile blocking = 250
   // 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);
 }

}


<\syntaxhighlight>