49713 Designing for the Internet of Things
· 16 members
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Found in DioT 2019: Connected Communities
Enhance the stadium fan experience with a portable device that enables fans to more actively engage and immerse in the atmosphere and also place live bets.
The NBA Cool Ball is an interaction and ambient appliance which is designed for the basketball fans when they watching a basketball game onsite. It provides several features to give audiences feedback instantly associate with the game processing. Moreover, it creates a gamification way to engage people to focus on the game by betting the scoring and get awards after it.
Fans supporting the same team form a tightly-knit community. However, they are scattered and hard to identify during everyday life. This all changes when they gather at the stadium on match day. They then form a physical community that is directly addressable as a whole.
Fans go to the stadium to support their home-team and the players. They want to be part of the game and be able to make an impact. They also want to celebrate with other fans and create an atmosphere that they all enjoy.
During games, fans are intensively engaged in the happenings on the court. It is difficult to connect or communicate with their fellow fans through gestures or words. They now perceive excitement, anger and disappointment of fellow friends through their body movement.
This could be augmented with some light that not only shows to fans how their surrounding fellow friends feel about the game, but also demonstrate support that is perceivable from the court by the players.
The needs of fans have been acknowledged and addressed through some attempts.
The NBA Cool Ball operates while fans cheer for their teams, and creates a connection (if not competition) among fans and their surroundings.
When the home team scores, Cool Ball will generate a running pattern (complemented with rainbow colors) to notify and celebrate with the crowd.
Users can also bet whether the current attempt turns into a score. If she/he bets it right, the Cool Ball will vibrate (while also showing the running lights).
Following is a marketing video for NBA Cool Ball.
For a more detailed version, click here. (Due to size limit, we were not able to upload it here. )
We used an accelerometer to measure how violent the ball is shaking. However, the position (tilt) of the acceleromoter cannot be pre-determined, thus the influence of gravity cannot be offset. We decided to record 10 value of acceleration along the 3 axis and compute the variance to determine the "shakiness".
We experimented how "Shakiness", or "violence", can be derived from the variation of acceleration along 3 axis: Maximum variance, Average variance, or Minimum variance. It turned out that Minimum variance was the most effective indicator of shaking.
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// This #include statement was automatically added by the Particle IDE.
#include <SparkFunMMA8452Q.h>
// This #include statement was automatically added by the Particle IDE.
#include <SparkFunMMA8452Q.h>
#include <Wire.h> // Must include Wire library for I2C
#include <math.h>
// This #include statement was automatically added by the Particle IDE.
MMA8452Q accel;
//https://learn.sparkfun.com/tutorials/lis3dh-hookup-guide?_ga=2.109610374.2021355271.1575496274-1654527264.1575496274
//http://integratedinnovation.xsead.cmu.edu/gallery/projects/cohort-culture-a3573993-f4c3-4cce-9f96-e8e38a545e59
//https://learn.adafruit.com/rgb-led-strips/arduino-code
//https://www.precisionmicrodrives.com/content/how-to-drive-a-vibration-motor-with-arduino-and-genuino/
#define LED_PIN A2
#define LED_COUNT 30
#define LED_TYPE WS2812B
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, LED_TYPE); //type
uint32_t c = strip.Color(255,0,0);
int fsrPin = A5;
int accelPin = D6;
int vibPin = D5;
int bettime=0;
int scoretime=0;
int fsrRead=0;
int betcorrect=0;
int X[10];
int Y[10];
int Z[10];
int violence = 0;
int n=0;
//monitor
int accx=0;
int accy=0;
int accz=0;
/*
// control publish interval
long lastPublishedAt = 0;
int publishAfter = 1000;//delay
*/
void setup()
{
pinMode(fsrPin, INPUT);
pinMode(accelPin, INPUT);
pinMode(vibPin, OUTPUT);
//accel.init();
accel.begin(SCALE_2G, ODR_1);
Particle.subscribe( "coolball/homescore" , homescore );
//Particle.variable("accx", &accx, INT);
//Particle.variable("accy", &accy, INT);
//Particle.variable("accz", &accz, INT);
Particle.variable("fsrRead", &fsrRead, INT);
Particle.variable("violence", &violence, INT);
Particle.variable("betcorrect", &betcorrect, INT);
Particle.variable("bettime", &bettime, INT);
digitalWrite(vibPin, LOW);
}
void loop()
{
fsrRead=analogRead(fsrPin);
if (fsrRead>1200)
{
if (millis()-bettime > 3000)
{
bettime=millis();//renew bet time
}
}
bright();
//digitalWrite(vibPin, LOW);
}
void bright()
{
if (accel.available()){
accel.read(); // Update accelerometer data
//test range
accx=accel.x;
accy=accel.y;
accz=accel.z;
X[n%10]=accel.x;
Y[n%10]=accel.y;
Z[n%10]=accel.z;
//variation of the acceleration values
int varX = 0;
int varY = 0;
int varZ = 0;
//first, compute the average
int avgX = 0;
int avgY = 0;
int avgZ = 0;
for (int i=0; i<10; i++)
{
avgX=avgX+X[i];
avgY=avgY+Y[i];
avgZ=avgZ+Z[i];
}
avgX = avgX/10;
avgY = avgY/10;
avgZ = avgZ/10;
//the variation
for (int i=0; i<10; i++)
{
varX=varX+(X[i]-avgX)*(X[i]-avgX);
varY=varY+(Y[i]-avgY)*(Y[i]-avgY);
varZ=varZ+(Z[i]-avgZ)*(Z[i]-avgZ);
}
/*
//get the max variance as violence
if (varX>varY)
{
if (varX>varZ) violence=varX;
else violence=varZ;
}
else
{
if (varY>varZ) violence=varY;
else violence=varZ;
}
*/
violence = (varX + varY + varZ)/3;
if (violence> 2800000) //check the threshold
{
int brightness = map(violence, 3000000, 3300000, 60, 255);
for (int i=0; i<LED_COUNT; i++)
{
c = strip.Color(0,0,brightness);
strip.setPixelColor(i,c);
}
strip.show();
delay(1000);
}
else {
for (int i=0; i<LED_COUNT; i++)
{
c = strip.Color(0,0,20);
strip.setPixelColor(i,c);
}
strip.show();
}
}
}
void homescore(const char *event, const char *data)
{
scoretime=millis();
// make sure it comes from other device
String eventName = String( event );
String deviceID = System.deviceID();
if( eventName.indexOf( deviceID ) != -1 ){
return;
}
else // rainbow color
{
rainbow();
}
//should get event publish time and give to live bet.
//currently just use the time argon receives the event
livebet();
}
void livebet ()
{
//judge if within timeframe
if (scoretime - bettime < 3000)
{
for (int i=0;i<2;i++) //vibrate twice
{
digitalWrite(vibPin, HIGH);
delay(500);
digitalWrite(vibPin, LOW);
delay(100);
}
betcorrect++;
}
}
void rainbow()
{
//start with red
int r=255;
int g=0;
int b=0;
int i=0;
//running red
for (i=0; i<LED_COUNT; i++)
{
c = strip.Color(r,g,b);
strip.setPixelColor(i,c);
strip.show();
delay(10);
}
//reset to rainbow
for (i=0; i<5; i++)
{
c = strip.Color(127,0,0);
strip.setPixelColor(i,c);
}
for (i=5; i<10; i++)
{
c = strip.Color(0,255,0);
strip.setPixelColor(i,c);
}
for (i=10; i<15; i++)
{
c = strip.Color(255,255,0);
strip.setPixelColor(i,c);
}
for (i=15; i<20; i++)
{
c = strip.Color(255,0,255);
strip.setPixelColor(i,c);
}
for (i=20; i<25; i++)
{
c = strip.Color(0,255,0);
strip.setPixelColor(i,c);
}
for (i=25; i<30; i++)
{
c = strip.Color(127,255,127);
strip.setPixelColor(i,c);
}
strip.show();
delay(100);
//running red (x2)
for (i=0; i<LED_COUNT; i++)
{
c = strip.Color(r,g,b);
strip.setPixelColor(i,c);
strip.show();
delay(10);
}
}
Click to Expand
int fsrPin = A5;
int fsrReading = 0;
int last_published = 0;
void setup() {
pinMode(fsrPin, INPUT);
}
void loop() {
fsrReading = analogRead(fsrPin);
if (fsrReading > 1500)
{
if (millis() - last_published > 1000)
{
Particle.publish("coolball/homescore", "homescore");
last_published = millis();
}
}
}
Click to Expand
Accelerometer
Vibration motor
Overall
Also, thanks to Benqiao Jiang for her generous time and comments regarding basketball stadiums, match composition, fan behavior, and expectations.
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Enhance the stadium fan experience with a portable device that enables fans to more actively engage and immerse in the atmosphere and also place live bets.
December 5th, 2019