By Gustell Preston, Noah Johnson, Stephanie Cheng and Shreya Bansal
Acknowledgement
This project would not come to fruition without the invaluable mentorship and support of our instructor, Professor Allison Lassiter, and our peers in the CPLN571 Sensing the City class (Spring 2023). We are grateful to have our idea published.
Overview
This is an interactive playground installation made to scale across the city of Philadelphia. DigiPlay aims to create equitable access to play and promote health for kids 2-12 in Philadelphia by turning playgrounds into interactive and immersive experiences. This is achieved by adding a digitally latent layer to playgrounds that strives to improve the play experience, supplement STEM education, and encourage more physical activity for children in Philadelphia schools.
The challenge
As it stands, many elementary school playgrounds in Philadelphia are either converted parking lots or have aging, inadequate playground equipment. As a result, 25% of the youth in Philadelphia do not get sustained physical activity even once a week. Unfortunately, upgrading and refurbishing playground equipment can cost anywhere between $8,000-$50,000, and there is no substantial line item in the Philadelphia School District’s annual budget to support upgrading playgrounds for children. As a result of this lack of physical activity, many kids in the city are facing health challenges such as obesity. In fact, 1 in 5 of youth in Philadelphia, the majority of whom are black or Hispanic, are overweight or obese. Furthermore, 70% of children in in North Philly are overweight or obese, which is nearly double the obesity and overweight rate for youth in the United States. Better access to play can solve these challenges for kids.
The solution
DigiPlay works to solve this challenge of inequitable access to play by transforming dull play spacing into interactive ones that encourage movement and serve as another avenue for learning and education in schools. Our solution has three major components, outfitting schools that already had some play equipment with DigiPlay sensors, Creating digital experiences for schools with no play equipment, and layering on educational components of the playground. Additionally, our solution is cost effective for schools to adopt. Creating 1-3 interactive installations on a playground would cost the school ~$300 to install and another ~$100 to maintain on a yearly basis.
Interactive Playground
- Light and sound to add a digital layer of fun and excitement to old playground equipment
Interactive Lots
- Light and sound to add a layer of fun and excitement to abandoned parking lots used as play areas for kids
Interact & Learn
- Digital sensors bring education to life at the playground from interactive science installations to take-home Arduino kits, kids can learn about health and engineering as they play and get active
Site selection
To facilitate playgrounds that have existing play equipment, we first looked at all elementary and middle schools in Philadelphia. We then looked at the playgrounds across Philadelphia and narrowed down to all that serve this age group of 2-12 years. Next, we identified all playgrounds within a 0.1 mile radius of a school. To test our pilot, we chose a school closer to base called the Albert M. Greenfield playground.
Diagram of project
Heart-rate sensor and break-beams
The first intervention of the project involves transforming the wall at the back of the playground into an interactive and educational space. A heart rate monitor with a display is attached to the wall along with a mural painted with thermo-chromatic paint that changes colour when touched. Through the design, children are encouraged to interact with the heart rate sensor to understand their cardiac health. If the heart rate is low, the display will have phrases that encourage more activity.
The second installation involves bolstering the jungle-gym with break beam sensors. As a child climbs or touches the different bars on the jungle gym, the light beam between two sensors is broken, triggering a musical note played through speakers.
Interactive playfield
The third and fourth interventions can be retrofitted to existing ball game infrastructure and open space to make them more interactive and fun. The first installation uses an ultrasonic motion sensor to detect when a ball passes through the bottom of a hoop. When this occurs, the LED strip lights up. A point is added to the tally on the display screen attached to the hoop as well. A button is attached to this display–upon pressing it, the display can be used for soccer instead. When a ball passes through the break-beam sensors, the LEDs light up, and a point is tallied on the display as well. These installations can be understood better in the following videos of our prototypes.
At Play >
Technical specifications
The following sections provides a more detailed look into how we created our own Digiplay playground model and how you can too! The digital playground model we built utilizes three different Arduino Uno boards, one for each individual installment: the Heart Rate Sensing Wall, the Musical Jungle Gym, and the Interactive Playground.
Most items can be found in an Arduino starter kit. Specifically we had access to the “ELEGOO UNO Project Super Starter Kit.” All parts that are not included in this kit are marked with an asterisk (*). Additionally, the choice to use three Arduino boards was partially for modularity and partially because of the limited number of digital pins per Arduino Uno.
Heart Rate Sensing Wall Module
For this module, a Pulse Oximeter/Heart-Rate Sensor is interfaced with an LCD display through an Uno controller to display the user’s heart rate. For more details about this module and wiring/coding a heart rate sensor and an LCD Display please refer to Shreya’s helpful tutorial, Arduino’s LCD tutorial, and Sparkfun’s MAX3010x Sensor Library Github.
Parts
- 1x Elegoo Uno R3 Controller Board
- 1x Heart Rate Click Sensor GY-MAX30102*
- 1x LCD 1602 Module Display Monitor
- 1x 830 Tie-Points Breadboard
- numerous jumper wires
Tutorial
- Make sure you have the necessary libraries, MAX3010x, LiquidCrystal, and filters.h installed into your Arduino IDE.
- Next, wire up your arduino to LCD display and the Heart-Rate Sensor as seen below in the wiring diagram.
- With the arduino plugged into a laptop with the code open, validate the code and run it.
- After waiting a few seconds for Heart-Rate sensor to stabilize, test the code by pressing your finger on the black strip of the heart-rate sensor.
Wiring Diagram
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
// This code uses real time data measured on MAX3010 heart rate monitor and produces a display on LCD screen (16x2) // 04.03.2023 // Shreya Bansal // This code is an extension of code from the MAX3010 library > example code > MAX30105PulseoximeterHeartrate // and code from ELEGOO Super starter kit chapter 14 >LCD Display // first, include libraries for MAX3010 and LCD Display #include <MAX3010x.h> #include "filters.h" #include <LiquidCrystal.h> // Sensor (adjust to your sensor type) MAX30105 sensor; // set a sampling rate const auto kSamplingRate = sensor.SAMPLING_RATE_400SPS; // set a sampling frequency const float kSamplingFrequency = 400.0; // set a Finger Detection Threshold and Cooldown const unsigned long kFingerThreshold = 10000; const unsigned int kFingerCooldownMs = 500; // set an Edge Detection Threshold const float kEdgeThreshold = -2000.0; // Filters const float kLowPassCutoff = 5.0; const float kHighPassCutoff = 0.5; // Averaging const bool kEnableAveraging = true; const int kAveragingSamples = 50; const int kSampleThreshold = 5; // Initialize an instantiated lcd object from the library // with the numbers of the interface pins given as int variables const int rs = 7, en = 6, d4 = 5, d5 =4, d6 = 3, d7 = 2; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); void setup() { Serial.begin(9600); lcd.begin(16, 2); // set if else condition to display on serial monitor whether sensor is working or not if(sensor.begin() && sensor.setSamplingRate(kSamplingRate)) { // if the sensor detects pulse, print the following message on LCD display lcd.print("Hello from CityBeat"); } // if the sensor is not initialized, print the following on LCD else { Serial.println("Sensor not found"); while(1); } } // Filter Instances HighPassFilter high_pass_filter(kHighPassCutoff, kSamplingFrequency); LowPassFilter low_pass_filter(kLowPassCutoff, kSamplingFrequency); Differentiator differentiator(kSamplingFrequency); MovingAverageFilter<kAveragingSamples> averager; // Timestamp of the last heartbeat long last_heartbeat = 0; // Timestamp for finger detection long finger_timestamp = 0; bool finger_detected = false; // Last diff to detect zero crossing float last_diff = NAN; bool crossed = false; long crossed_time = 0; void loop() { // read sample on sensor every 1000 milliseconds auto sample = sensor.readSample(1000); float current_value = sample.red; // Detect Finger using raw sensor value if(sample.red > kFingerThreshold) { if(millis() - finger_timestamp > kFingerCooldownMs) { finger_detected = true; } } else { // Reset values if the finger is removed differentiator.reset(); averager.reset(); low_pass_filter.reset(); high_pass_filter.reset(); finger_detected = false; finger_timestamp = millis(); } if(finger_detected) { current_value = low_pass_filter.process(current_value); current_value = high_pass_filter.process(current_value); float current_diff = differentiator.process(current_value); // Valid values? if(!isnan(current_diff) && !isnan(last_diff)) { // Detect Heartbeat - Zero-Crossing if(last_diff > 0 && current_diff < 0) { crossed = true; crossed_time = millis(); } if(current_diff > 0) { crossed = false; } // Detect Heartbeat - Falling Edge Threshold if(crossed && current_diff < kEdgeThreshold) { if(last_heartbeat != 0 && crossed_time - last_heartbeat > 300) { // Show Results int bpm = 60000/(crossed_time - last_heartbeat); if(bpm > 50 && bpm < 250) { // Average? if(kEnableAveraging) { int average_bpm = averager.process(bpm); // Show if enough samples have been collected if(averager.count() > kSampleThreshold) { // first print output of average heartrate on serial monitor Serial.print("Heart Rate (avg, bpm): "); Serial.println(average_bpm); // then print output of average heartrate on LCD display lcd.clear(); lcd.print("avg Rate: "); lcd.print(average_bpm); lcd.print("bpm"); } } else { // otherwise print output of heartrate on serial monitor Serial.print("Heart Rate (current, bpm): "); Serial.println(bpm); // otherwise print output of heartrate on LCD Display lcd.clear(); lcd.print(" rate: "); lcd.println(bpm); } } } crossed = false; last_heartbeat = crossed_time; } } last_diff = current_diff; } } |
Musical Jungle Gym Module
This module largely borrows from Tom Igoe’s code for the buzzer interface, the Elegoo Super Start Kit Textbook Lesson 7 on passive buzzers, and lady ada from Adafruit’s IR breakbeam sensor tutorial.
Parts
- 1x Elegoo Uno R3 Controller Board
- 3x IR Break Beam Sensors*
- 1x Passive Buzzer
- 1x 830 Tie-Points Breadboard
- numerous jumper wires
Tutorial
- Make sure you have the necessary library, pitches.h, installed.
- Next, wire up your arduino to the three IR break beam sensors and the passive buzzer.
- On your prototype model, or on a real piece of playground equipment such as a similar jungle gym or set of monkey bars, secure the break beam sensors on the surface of the bar. This is best done in a way where the two side of the sensor are lined up as directly as possible, with both affixed to the beam using electrical tape. Make sure you are accommodating the distance threshold of your break beam sensors.
- Furthermore, if a particular sequence of notes is desired (e.g. in an ascending pitch order), make sure you align the respective break beam sensors to the respective bars in succession.
- With the arduino plugged into a laptop with the code open, validate the code and run it.
- Test the sensor by tapping the bar to break the beam.
Wiring Diagram
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
//Musical Jungle Gym Digiplay Module // Noah Dylan Johnson // Last Updated May 5, 2023 // This code interfaces three IR Break-Beam Sensor with a Passive Buzzer // When one of the Break Beam sensors is triggered, the buzzer will play a defined note // In our set up, we utilize a sensor on each of three stages of a jungle gym, // so that when the user steps or climbs between rungs different musical notes are played // This interaction creates a musical experience out of simple motion. // Ideas and code from Tom Igoe's code for the buzzer interfce // http://www.arduino.cc/en/Tutorial/Tone // Ideas and code from Elegoo Super Starter Kit Textbook Lesson 7 on Passive Buzzers //Ideas and code from lady ada IR Breakeam Sensors // https://learn.adafruit.com/ir-breakbeam-sensors/arduino //Import the necessary Libraries #include "pitches.h" //pitches library for playing different frequency pitches on the buzzer //Initialization of constants for the sensor and buzzer pin assignments #define SENSORPIN1 2 //IR Break Beam Sensor 1 Pin #define SENSORPIN2 3 //IR Break Beam Sensor 2 Pin #define SENSORPIN3 4 //IR Break Beam Sensor 3 Pin #define BUZZERPIN 8 //Passive Buzzer Pin //Initialization of variables that can/will change int note1_to_play = NOTE_E4; // Choose note that you want to play for this specific break beam sensor int note2_to_play = NOTE_G4; // Choose note that you want to play for this specific break beam sensor int note3_to_play = NOTE_C4; // Choose note that you want to play for this specific break beam sensor int sensorState1 = 0, sensorState2 = 0, sensorState3 = 0; // variable for reading the Breakbeams' status //The setup will run once and contains the Arduino pin initialization void setup() { pinMode(SENSORPIN1, INPUT); // initialize the sensor pin 1 as a digital input so that we can read its voltage status digitalWrite(SENSORPIN1, HIGH); // turn on the pullup resistor to help define a known and well-defined on and off states for the sensor pinMode(SENSORPIN2, INPUT); // initialize the sensor pin 2 as a digital input so that we can read its voltage status digitalWrite(SENSORPIN2, HIGH); // turn on the pullup resistor to help define a known and well-defined on and off states for the sensor pinMode(SENSORPIN3, INPUT); // initialize the sensor pin 3 as a a digital input so that we can read its voltage status digitalWrite(SENSORPIN3, HIGH); // turn on the pullup resistor to help define a known and well-defined on and off states for the sensor // You can read more about pull up resistors and their use here: https://learn.sparkfun.com/tutorials/pull-up-resistors/all Serial.begin(9600); // Initialize the Serial Monitor with a baud rate of 9600. Serial Monitor is mainly used for debugging here } //This code will run after the setup and will run repeatedly void loop(){ // read the state of each breakbeam sensor digital value: int sensorState1 = digitalRead(SENSORPIN1); int sensorState2 = digitalRead(SENSORPIN2); int sensorState3 = digitalRead(SENSORPIN3); // check if any of the sensor beams are broken // if it is, the sensorState is LOW, since current will flow to ground // if the sensor beam is not broken the state is HIGH due to the pullup resistor path if (sensorState1 == LOW) { // If the beam is broken then output the sensor number to the Serial and tell the buzzer to play the corresponding note Serial.println("1"); // Print the Sensor Number tone(BUZZERPIN, note1_to_play); // use the tone function with the parameters of the pin to send voltage too and the frequency of the selected note } else if (sensorState2 == LOW) { Serial.println("2");// Print the Sensor Number tone(BUZZERPIN, note2_to_play); // use the tone function with the parameters of the pin to send voltage too and the frequency of the selected note } else if (sensorState3 == LOW) { Serial.println("3"); // Print the Sensor Number tone(BUZZERPIN, note3_to_play); // use the tone function with the parameters of the pin to send voltage too and the frequency of the selected note } else { // Code to run if none of the sensor's are triggered, which will silence the buzzer Serial.println("0"); noTone(BUZZERPIN); // function that tells the buzzer to turn off and play no sound } } |
Interactive Playground Module
This final module is also based on the aforementioned break beam sensor and LCD display tutorials. In addition, it utilizes code from Shae Erisson’s NeoPixel Ring simple sketch, lady ada on Adafruit’s LED strips tutorial, the Elegoo Super Start Kit Textbook Lesson 10 Ultrasonic Sensor Module, David A. Mellis’s LCD Tutorial library, and more.
Parts
- 1x Arduino Uno R3 Controller Board*
- 1x IR Break Beam Sensor*
- 1x Ultrasonic Motion Sensor
- 1x LCD 1602 Module Display Monitor
- 1x Digital RGB LED 1m Strip* cut into 3 sections
- 1x Joystick Module
- 1x 830 Tie-Points Breadboard
- 1x 1kOhm Resistor
- 1x 220 Ohm Resistor
- numerous jumper wires
Tutorial
- Make sure you have the necessary libraries, Adafruit_Neopixel.h and Ultrasonic.h installed.
- Next, wire up your arduino to the LED strips, joystick, LCD Display, ultrasonic motion sensor, and IR break beam sensor as seen below in the wiring diagram.
- Affix the LED strips as desired and depending on the playground equipment. The basketball hoop LEDs are recommends to be taped to the back board of a basketball hoop, with the ultrasonic motion sensor located underneath the rim of the hoop, with the wires below. The LCD display and joystick are recommended to be affixed to the pole of the basketball hoop. For the soccer goal module, the LED strips are to be taped along a section of the floor of which players would like to be demarcated as a goal. The IR break beam sensors should be taped onto either end of this length of floor with electric tape.
- With the arduino plugged into a laptop with the code open, validate the code and run it.
- Test the code by putting an object or your hand close to the ultrasonic motion sensor and break the beam of the break beam sensor.
- The sensor is ready to use–make sure you press the joystick button to ensure you are using the sensor in the right mode.
Wiring Diagram
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
//Interactive Soccer/Basketball Playground Games // Noah Dylan Johnson // Last Updated May 5, 2023 // In this code two seperate sensing modules, one for senssing basketball shots going through a hoop and // one that sensing a soccer ball passing through a goal, are interfaced in a switchable game style via a button and LCD Display. // When the button is pressed the display prints the current game being played and the LED strip for the set up lights up solid, green for soccer, blue for basketball // The score for each game is printed and updated on the LCD Display // The soccer goal is created with an IR breakbeam sensor that triggers an LED strip upon breaking // The basketball hoop is fitted with an ultrasonic motion sensor that triggers two LED strips to light up when a distance threshold is passed on the Ultrasonic sensor // This code uses code and ideas from: // NeoPixel Ring simple sketch (c) 2013 Shae Erisson // "Arduino library for controlling single-wire-based LED pixels and strip" // https://github.com/adafruit/Adafruit_NeoPixel // RGB LED Strips tutorial byy lady ada on Adafruit // https://learn.adafruit.com/rgb-led-strips/overview // Ideas and code taken from the Elegoo Super Starter Kit Textbook Lesson 10 Ultrasonic Sensor Module // LCD Tutorial Library originally added 18 Apr 2008 // by David A. Mellis // library modified 5 Jul 2009 // by Limor Fried (http://www.ladyada.net) // example added 9 Jul 2009 // by Tom Igoe // modified 22 Nov 2010 // by Tom Igoe // http://www.arduino.cc/en/Tutorial/LiquidCrystal //lady ada IR Breakeam Sensors Tutorial // https://learn.adafruit.com/ir-breakbeam-sensors/arduino // How to Wire and Program a Button Arduino Built-in-Example // created 2005 // by DojoDave <http://www.0j0.org> // modified 30 Aug 2011 // by Tom Igoe //https://docs.arduino.cc/built-in-examples/digital/Button //Import the necessary Libraries #include <Adafruit_NeoPixel.h> // Adafruit library for interfacing with the Digital LED strips #include <Ultrasonic.h> // Minimalist library for ultrasound module to Arduino, Author Erick Simões //LED Strip Pin and constant definitions // Which pin on the Arduino is connected to the NeoPixels #define PINS 10 //PINS is the LED strip for the soccer goal #define PINB1 9 //PINB1 is one of the LED strips for the basketball hoop #define PINB2 8 //PINB2 is one of the LED strips for the basketball hoop #define NUMPIXELS 12 // Number of pixels in the LED strip #define DELAYVAL 100 // Time (in milliseconds) to pause between pixels // When setting up the NeoPixel object, we tell it how many pixels, // and which pin to use to send signals. Note that for older NeoPixel // strips you might need to change the third parameter -- see the // strandtest example for more information on possible values. Adafruit_NeoPixel pixelsS(NUMPIXELS, PINS, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel pixelsB1(NUMPIXELS, PINB1, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel pixelsB2(NUMPIXELS, PINB2, NEO_GRB + NEO_KHZ800); // Ultrasonic Sensor pin and variables definitions // Hook up HC-SR04 with Trig to Arduino Pin 13, Echo to Arduino pin 12 #define TRIGGER_PIN 13 #define ECHO_PIN 12 //Create an object from the Ultrasonic class Ultrasonic ultrasonic(TRIGGER_PIN, ECHO_PIN); int distance; // an integer variable that helps us keep track of the distance something is being sensed at by the ultrasonic sensor int scoreDistance = 8; // This variable is chosen as the distance limit measured by the ultrasonic sensor for a basketball shot to be scored //IR Breakbeam sensor pin and variables definition #define SENSORPIN 14 int sensorState = 0; // include the Arduino LCD library #include <LiquidCrystal.h> // Initialize an instantiated lcd object from the library // with the numbers of the interface pins given as int variables const int rs = 7, en = 6, d4 = 5, d5 =4, d6 = 3, d7 = 2; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //Joystick button pin and variables definition int BUTTON_PIN = 19; int gameState = 0; // helps tracks the current game being played, basketball or soccer int lastButtonState = 0; // the previous state of button int currentButtonState = 0; // the current state of button int Sscore = 0; // integer variable to keep track of the current soccer goals scored int Bscore = 0; // integer variable to keep track of the current number of baskets scored //This code runs once and contains most of the Arduino voltage initializations and pin determinations void setup() { // initialize serial communications at 9600 bps: Serial.begin(9600); // set up the LCD's number of columns and rows and print a friendly initial message lcd.begin(16, 2); lcd.print("Game Time!"); delay(5000); // delay added before a game can be selected pinMode(BUTTON_PIN, INPUT_PULLUP); // initialize the joystick button terminal as a digital input with a pull up resistor //activate pull-up resistor on the joystick button pin to help define a known and well-defined on and off states for the sensor // You can read more about pull up resistors and their use here: https://learn.sparkfun.com/tutorials/pull-up-resistors/all pinMode(SENSORPIN, INPUT); // Initialize the ir break beam sensor as a digital input digitalWrite(SENSORPIN, HIGH); // turn on the pullup resistor to help define a known and well-defined on and off states for the sensor pixelsS.begin(); // INITIALIZE NeoPixel strip object for the soccer goal pixelsB1.begin(); // INITIALIZE NeoPixel strip object 1 for the basketball hoop pixelsB2.begin(); // INITIALIZE NeoPixel strip object 1 for the basketball hoop // Set all pixel colors to 'off' for all 3 of the LED strips pixelsS.clear(); // the .clear() command tells the LED strip that we want nothing displayed pixelsS.show(); // Send the updated pixel colors to the hardware. pixelsB1.clear(); pixelsB1.show(); pixelsB2.clear(); pixelsB2.show(); } //This code runs after the setup and will run repeatedly until power is lost void loop() { pixelsS.clear(); pixelsB1.clear(); pixelsB2.clear(); lastButtonState = currentButtonState; // save the last state of the button currentButtonState = digitalRead(BUTTON_PIN); // read new state of the button //if statement that checks to see if the button has been pressed which if it has been enters the if statement which //contains the dynamics of switching between games and the LED lighting and LCD printing that occurs for each game if(lastButtonState == HIGH && currentButtonState == LOW) { lcd.clear(); delay(1000); // toggle state of Game with LOW meaning that the game is soccer if(gameState == LOW) { //Soccer Sscore = 0; //reset the soccer score to 0 gameState = HIGH; //flip the gamestate variable so that next time the button is pressed it will switch sports lcd.clear(); lcd.print("Soccer"); //display the current game delay(1000); pixelsS.fill(pixelsS.Color(0, 150, 0)); //light up the Soccer LED strip solid green pixelsS.show(); delay(2000); //After a 2 second display the LED strips are turned off to not distract during the game pixelsS.clear(); pixelsS.show(); //Clear the LCD Display and now print the current score of soccer, which starts at 0 lcd.clear(); lcd.print("Score is "); lcd.print(Sscore); } else { //Basketball Bscore = 0; //reset the basketball score to 0 gameState = LOW; //flip the gamestate variable so that next time the button is pressed it will switch sports lcd.clear(); lcd.print("Basketball"); //display the current game delay(1000); //light up the basketball LED strips solid blue pixelsB1.fill(pixelsB1.Color(0, 0, 150)); pixelsB2.fill(pixelsB2.Color(0, 0, 150)); pixelsB1.show(); pixelsB2.show(); delay(2000); //After a 2 second display the LED strips are turned off to not distract during the game pixelsB1.clear(); pixelsB2.clear(); pixelsB1.show(); pixelsB2.show(); //Clear the LCD Display and now print the current score of basketball, which starts at 0 lcd.clear(); lcd.print("Score is "); lcd.print(Bscore); } } else { //if the button has not been pressed then we enter the else statement which contains the gameplay dynamics // toggle state of LED if(gameState == 1) { //Checks to see if we are currently playing Soccer(1) or Basketball(0) sensorState = digitalRead(SENSORPIN);// check if the sensor beam is broken // if it is, the sensorState is LOW: if (sensorState == LOW) { Sscore++; //Increment the soccer score by 1 point lcd.clear(); lcd.print("GOAL!!!"); //Print a fun message on the LCD display when a goal is scored // A for loop is used here to light up the LED strippixel by pixel. for(int i=0; i<NUMPIXELS; i++) { // For each pixel... // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255 // Here we're using a moderately bright green color: pixelsS.setPixelColor(i, pixelsS.Color(0, 150, 0)); pixelsS.show(); delay(DELAYVAL); // Pause before next pass through loop } delay(3000); lcd.clear(); lcd.print("Score is "); //Print the updated score to the LCD Display lcd.print(Sscore); } else { //if no goal is scored we want to turn off the LED strip pixelsS.clear(); pixelsS.show(); } } else { //basketball time all you hooperz distance = ultrasonic.read(); //Qury the dsitance being measured by the ultrasonic sensor if (distance < scoreDistance){ //Check if the distance is below the scoring threshold distance //if it is below then trigger the lighting and lcd printing Bscore++; //increment basketball score by 1 lcd.clear(); lcd.print("Nice Shot!");//Print a fun message on the LCD display when a shot is scored // A for loop is used here to light up the LED strips pixel by pixel. for(int i=0; i<NUMPIXELS; i++) { // For each pixel... // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255 // Here we're using a moderately bright blue color: pixelsB1.setPixelColor(i, pixelsB1.Color(0, 0, 150)); pixelsB1.show(); pixelsB2.setPixelColor(i, pixelsB2.Color(0, 0, 150)); pixelsB2.show(); delay(DELAYVAL); // Pause before next pass through loop } delay(3000); lcd.clear(); lcd.print("Score is "); //Print the updated score to the LCD Display lcd.print(Bscore); } else { // turn LEDs off if a hoop has not been scored pixelsB1.clear(); pixelsB2.clear(); pixelsB1.show(); pixelsB2.show(); } } } // adding a small delay prevents reading the buttonState to fast // ( debouncing ) - basically is removing unwanted noise from triggering the button //Here is a nice in depth article about debouncing //https://my.eng.utah.edu/~cs5780/debouncing.pdf delay(20); } |
Future considerations
Based on our GIS analysis, we want to start by rolling out the project in North Philadelphia with the Fitzpatrick Playground on 12501 Torrey Road.
Further references
- Knight Foundation: https://knightfoundation.org/smart-cities-2/
- https://www.pysc.org/initiatives/youth-engagement-in-sports-yes-initiative/
- https://vimeo.com/117303273