Loaded Every Thing From My Work

This commit is contained in:
ghassan committed 2020-01-28 08:42:25 +03:00
1 parent 4d81b2687b
commit 3229659f4e
176 files changed
+9623

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.
+258
View File
@@ -0,0 +1,258 @@
//======================================================
// LIBRARIES
//======================================================
#include <Button.h>
#include <ArduinoJson.h>
#include <TimeTrigger.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// MODE SELECTION VARIABLES
int mode;
bool flagChange = false;
// FIXED MESSAGES
#define POWERUP "{\"status\":\"POWER UP\"}"
#define UNDERSTOOD "{\"status\":\"OK\"}"
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
// GAME NAMES
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
#define GM_REACTION "{\"gm\":\"REACTION\"}"
#define GM_DECISION "{\"gm\":\"DECISION\"}"
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
// COMMAND LIST
#define CM_START "{\"cm\":\"START\"}"
#define CM_RESET "{\"cm\":\"RESET\"}"
#define CM_STOP "{\"cm\":\"STOP\"}"
#define CM_EXIT "{\"cm\":\"EXIT\"}"
// JSON JSON_CAPACITY
#define JSON_CAPACITY 500
//======================================================
// HARDWARE SELECTION
//======================================================
#define TERMINAL Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define VTH 65 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define PWR 65 // MIN THRESHOLD VOLTAGE FROM ZERO POINT TO BE ACCOUNTED AS KICK
#define NUM_PIXELS 22 // NUMBER OF LED'S IN NEO PIXEL STRIP
#define MPU_ADD 0x69 // On Board MPU9250 I2C Address
#define OLED_ADD 0x3C // Connected I2C OLED Address
// Incase You Are Using Arduino MEGA
#ifdef ARDUINO_AVR_MEGA2560
#define BLUETOOTH Serial1
Button button(52); // BUTTON ON PIN 2
#define LED_STRIP 53 // LED STRIP PIN NUMBER
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A2 // RANDOM NUMBER GENERATOR SOURCE
// Incase You Are Using Arduino Nano
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
//----------------------------------------------------------
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
#include <SoftwareSerial.h>
//----------------------------------------------------------
SoftwareSerial BLUETOOTH(10, 11); // RX, TX
Button button(2); // BUTTON ON PIN 2
#define LED_STRIP 8 // LED STRIP PIN NUMBER
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A3 // RANDOM NUMBER GENERATOR SOURCE
// if This Was The ESP32 Core
#elif ESP32
//----------------------------------------------------------
#include <BluetoothSerial.h>
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
//----------------------------------------------------------
// BLUETOOTH DEFINITION
BluetoothSerial BLUETOOTH;
// BUTTONS
Button button(2); // BUTTON ON PIN 2
// PIEZO SENSOR PIN
#define SENSOR_PIN 39 // IMPACT SENSOR
// LED STRIP PIN SET
#define LED_STRIP 26 // LED STRIP PIN NUMBER
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
// Battery To 5V Level Booster Setup & Control
#define BOOST_PIN 14
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
// Battery Level Monitoring
#define BATTERY (float)(((analogRead(35) * (3.3 / 4096)) * 2) + 0.28)
#define CHARGE mapf(BATTERY, 3.27, 4.31, 0, 100)
// End Of Arduino Selection ARDUINO_MEGA
#endif
// Float Mapping Function
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
// NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
//======================================================
// DEFINITION & DECLERATIONS
//======================================================
// Serial Flags
#define isBluetooth BLUETOOTH.available()
#define isTERMINAL TERMINAL.available()
//======================================================
// READING IMPACT POWER FROM ANALOG PINS
//======================================================
// READING THE IMPACT
int readImpact()
{
int value = abs(constrain(analogRead(SENSOR_PIN), VTH, 1023));
value = map(value, VTH, 1023, 0, 1023);
return value;
}
//======================================================
// MAIN HARDWARE SETUP
//======================================================
void setup()
{
// Communications
TERMINAL.begin(9600);
// Oled Display
oled_init();
// Make Sure Of The Core
#ifdef ESP32
BOOST_SETUP;
BOOST_OFF;
BLUETOOTH.begin("KICKER"); //Bluetooth device name
#else
BLUETOOTH.begin(9600);
#endif
// I/O
button.begin(); // Button
pixels.begin(); // Neo Pixel
LED_CLEAR(); // Turn Off All LED
// The Random Number Source
randomSeed(analogRead(RANDOM_SOURCE));
// Battery Managment
if(BATTERY <= 3.7) {
// Display Battery Low
dualcomm("Battery Low");
// Display Battery Voltage
while(BATTERY <= 3.7) { Serial.println(BATTERY); drawProgressBarDemo(CHARGE); oled_show(); delay(5000); }
// Clearing The Screen
oled_clear();
oled_show();
}
// POWER UP MESSGAE
dualcomm(POWERUP);
// TURN BOOSTER ON
BOOST_ON;
// Blue, Red And Green
colorWipe(pixels.Color(0, 0, 255), 15); // Blue
delay(100);
colorWipe(pixels.Color(255, 0, 0), 15); // Red
delay(100);
colorWipe(pixels.Color(0, 255, 0), 15); // Green
// Delay 1 Sec
delay(500);
// Red FadeOut
LED_GREEN_FADEOUT();
// Display Rainbow
LED_CLEAR();
// TURN BOOSTER ON
BOOST_OFF;
}
//======================================================
// MAIN PROGRAM LOOP
//======================================================
void loop()
{
// Reading From Bluetooth
if(BLUETOOTH.available())
{
// Reading Message From Bluetooth
String msg = BLUETOOTH.readString();
msg.trim();
// Display On Sertial
terminal(msg);
// Parsing Objects Message Objects
DynamicJsonDocument root(JSON_CAPACITY);
// Deserialize the JSON document
DeserializationError error = deserializeJson(root, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
dualcomm(UNDERSTOOD);
// Reading Game Name & Settings
String game = root["gm"];
String settings = root["set"];
// Clearing JSON Buffer
root.clear();
// Entering To Game Selector
game_selector(game, settings);
}
else
{
// Display The Error Message
terminal(JSON_ERROR);
}
// Clearing Buffer
BLUETOOTH.flush();
}
}
//======================================================
// END OF PROGRAM
//======================================================
+29
View File
@@ -0,0 +1,29 @@
//======================================================
// TERMINAL WINDOW - NATIVE USB
//======================================================
void terminal(String msg)
{
msg += "\n";
TERMINAL.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void bluetooth(String msg)
{
msg += "\n";
BLUETOOTH.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void dualcomm(String msg)
{
terminal(msg);
bluetooth(msg);
}
+206
View File
@@ -0,0 +1,206 @@
//======================================================
// MAIN COUNTER GAME LOOP
//======================================================
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
* --------------------------------------
*
* FORMAT :
* --------
* {"le": false, "lm": 10}
*
* MEANNING :
* ----------
* ct : count
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* WHAT DATA TO BE COLLECTED :
* ---------------------------
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISPLAY AND TIMESTAMP
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
*
* CALCULATING RESULTS :
* ---------------------
* No calculation required, Its directly the count
*/
void game_counter(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// CONVERTING GAME TEXT TO JSON
DynamicJsonDocument play(JSON_CAPACITY); // building JSON Buffer
// Deserialize the JSON document
DeserializationError error = deserializeJson(play, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t limit = play["lm"]; // Kick Target Limit
bool limitEnable = play["le"]; // Enable Kick Target Limit
// Clearing Buffer
play.clear();
// Kick Counter
uint16_t counter = 0;
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// Display Welcome Message
// TERMINAL("");
// TERMINAL("==================================================");
// TERMINAL(" -->> Counter Game Settings");
// TERMINAL("--------------------------------------------------");
// TERMINAL("Strike Limit : " + String(limit) + " Strikes");
// TERMINAL("Limits Enable : " + String(limitEnable));
// TERMINAL("--------------------------------------------------");
// TERMINAL("2 Seconds To Start Get Ready & Good Luck !!");
// TERMINAL("==================================================");
// TERMINAL("");
// Game Start Lights
Counter_Start();
// staring Of time stamp
unsigned long startStamp = millis();
while(1)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = BLUETOOTH.readString();
msg.trim();
if(msg == CM_STOP)
{
// TERMINAL("");
// TERMINAL("---------------------------------------------------");
dualcomm(GAME_OVER);
// TERMINAL("===================================================");
// TERMINAL("");
Counter_End();
// Grean Light In
//LED_GREEN_FADEOUT();
// RESET
return;
}
else if(msg == CM_RESET)
{
Counter_Reset();
counter = 0;
startStamp = millis();
timeStamp = startStamp;
}
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
// TERMINAL("");
// TERMINAL("---------------------------------------------------");
dualcomm(GAME_OVER);
// TERMINAL("===================================================");
// TERMINAL("");
// Celebration
Counter_Celebration();
// RESET
return;
}
// Read Impact
if(readImpact() > PWR)
{
counter++;
dualcomm(counter_data_json(counter, timeStamp));
delay(100);
}
}
}
//======================================================
// COUNTER DATA JSON -> To Send Back To Server
//======================================================
String counter_data_json(unsigned int ct, unsigned int st)
{
// Building The Buffer
DynamicJsonDocument data(JSON_CAPACITY);
// Convert Int To Float
float stamp = st;
stamp /= 1000;
// Assignning Dataset
data["ct"] = ct;
data["st"] = String(stamp, 3).toFloat();
String output;
serializeJson(data, output);
data.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void Counter_Start()
{
// LightUp
LED_WHITE_CROSSFADE(2);
// Grean Light In
LED_GREEN();
}
//======================================================
// REACTION GAME END SINGNAL LED SIGNAL
//======================================================
void Counter_End()
{
LED_RED_BLINK(2);
LED_RED_FADEOUT();
}
//======================================================
// REACTION GAME START LED CELEBRATION
//======================================================
void Counter_Celebration()
{
// LightUp
rainbowCycle(2);
// Grean Light OUT
LED_GREEN_FADEOUT();
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void Counter_Reset()
{
//
LED_BLUE();
delay(250);
LED_BLUE_FADEOUT();
}
+237
View File
@@ -0,0 +1,237 @@
//======================================================
// REACTION GAME MAIN ROUTINE
//======================================================
/* REACTION GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tr": 10, "mn": 1, "mx": 2}
*
* MEANNING :
* ----------
* tr : trials pre counter
* mn : minimum delay, between trials
* mx : maximum delay, between trials
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tr" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
*/
//======================================================
void game_reaction(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// CONVERTING GAME TEXT TO JSON
DynamicJsonDocument play(JSON_CAPACITY);
// Deserialize the JSON document
DeserializationError error = deserializeJson(play, settings);
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint8_t minDelay = play["mn"];
uint8_t maxDelay = play["mx"];
uint16_t trials = play["lm"];
uint16_t temp = trials;
// Clearing Buffer
play.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// Display Welcome Message
// TERMINAL("");
// TERMINAL("==================================================");
// TERMINAL(" -->> Reaction Game Settings");
// TERMINAL("--------------------------------------------------");
// TERMINAL("trials : " + String(trials) + " Strikes");
// TERMINAL("try delay : " + String(minDelay) + " to " + String(maxDelay) + " Seconds");
// TERMINAL("--------------------------------------------------");
// TERMINAL("2 Seconds To Start Get Ready & Good Luck !!");
// TERMINAL("==================================================");
// TERMINAL("");
// Ready Signal
Reaction_Start();
// Main Variables
uint16_t sdelay = 0;
uint16_t power = 0;
uint16_t response = 0;
unsigned long startTime = 0;
unsigned long stopTime = 0;
// Processing Results
for(int i=0; i<trials; i++)
{
// Reading Kick Data
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
terminal(" -> Get Ready !!");
// Set Random Delay Time
sdelay = random(minDelay, (maxDelay + 1));
sdelay *= 1000;
delay(sdelay);
// Light Up Green
rgbLED(0, 150, 0);
// Start Timer
startTime = millis();
// Sensing Strike Power
while(power < PWR)
{
// Reading The Strike
power = readImpact();
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = BLUETOOTH.readString();
msg.trim();
if(msg == CM_STOP) {
dualcomm(GAME_OVER);
Reaction_End();
// LightUp
//LED_RED();
//delay(2000);
// Red FadeOut
//LED_RED_FADEOUT();
// RESET
return;
}
else if(msg == CM_RESET) {
trials = temp;
break;
}
}
}
// Stop Timer
stopTime = millis();
// Stop Light
rgbLED(150, 0, 0);
// Calculating Response Time
response = stopTime - startTime - 1;
// Create Json Data
String msg = reaction_data_json(i+1, power, response, sdelay);
// Print To TERMINAL
dualcomm(msg);
// Clear All
sdelay = 0;
power = 0;
response = 0;
}
// Red Light Delay
delay(500);
// END GAME
// TERMINAL("");
// TERMINAL("---------------------------------------------------");
dualcomm(GAME_OVER);
// TERMINAL("===================================================");
// TERMINAL("");
// Celebration
Reaction_Celebration();
// Blink Red
//Reaction_End();
// Return To Game Selector
return;
}
//======================================================
// REACTION DATA JSON -> To Send Back To Server
//======================================================
String reaction_data_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
{
// Building The Buffer
DynamicJsonDocument data(JSON_CAPACITY);
// Convert To Seconds Unit
float re = response;
re /= 1000;
// Asignning Values
data["ct"] = count; // Strike Number
data["pw"] = power; // Strike Power In Analog Read
data["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
data["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
String output;
serializeJson(data, output);
data.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void Reaction_Start()
{
LED_WHITE_CROSSFADE(3);
LED_RED_FADEIN();
}
//======================================================
// REACTION GAME END SINGNAL LED SIGNAL
//======================================================
void Reaction_End()
{
LED_RED_BLINK(2);
LED_RED_FADEOUT();
}
//======================================================
// REACTION GAME START LED CELEBRATION
//======================================================
void Reaction_Celebration()
{
// LightUp
rainbowCycle(2);
// Grean Light OUT
LED_GREEN_FADEOUT();
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void Reaction_Reset()
{
LED_BLUE();
delay(250);
LED_BLUE_FADEOUT();
}
+37
View File
@@ -0,0 +1,37 @@
//======================================================
// MAIN PROGRAM LOOP
//======================================================
/* game selector is the main function that tell the game groutine
* which game to be played and at what parameters
*/
void game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal(GM_COUNTER);
game_counter(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal(GM_TATTACK);
game_timeAttack(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal(GM_REACTION);
game_reaction(settings);
return;
}
// Unknown Game
else {
dualcomm(UNKNOWN_GAME);
return;
}
}
@@ -0,0 +1,261 @@
//======================================================
// TIME ATTACK GAME MAIN ROUTINE
//======================================================
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tm": 10, "le": false, "lm": 10}
*
* tm : count down timer starting value
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tm" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
*
* RETURNNING DATA FORMAT :
* ------------------------
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
*
* tm : timer count in Sec
* ct : strike counter (number of kicks)
* dl : delay between strikes
* st : time stampe of the strike in milli Seconds
*/
void game_timeAttack(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// CONVERTING GAME TEXT TO JSON
DynamicJsonDocument play(JSON_CAPACITY); // building JSON Buffer
// Deserialize the JSON document
DeserializationError error = deserializeJson(play, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t time = play["tm"]; // Time Window To Play
uint16_t timer = time;
uint16_t limit = play["lm"]; // Kick Target Limit
bool limitEnable = play["le"]; // Enable Kick Target Limit
// Clearing Buffer
play.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// Display Welcome Message
// TERMINAL("");
// TERMINAL("==================================================");
// TERMINAL(" -->> Time Attack Game Settings");
// TERMINAL("--------------------------------------------------");
// TERMINAL("Timer : " + String(time) + " Seconds");
// TERMINAL("Strike Limit : " + String(limit));
// TERMINAL("Limit Enabled : " + String(limitEnable));
// TERMINAL("--------------------------------------------------");
// TERMINAL("2 Seconds To Start Get Ready & Good Luck !!");
// TERMINAL("==================================================");
// TERMINAL("");
// Send Initial Display
dualcomm(timeAttack_data_json(timer, 0, 0, 0));
// Start LED Signal
TimeAttack_Start();
// Building Timers 1000mSec -> 1Sec
TimeTrigger sec_tick(1000);
// Kick Counter
uint16_t counter = 0;
// staring Of time stamp
unsigned long startStamp = millis();
// store the time of the previous kick
unsigned long lastStamp = 0;
// reseting time ticker
sec_tick.Reset();
// While The Game Is Still On
while(timer != 0)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = BLUETOOTH.readString();
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_GREEN_FADEOUT();
// Return
return;
}
else if(msg == CM_RESET)
{
timer = time;
counter = 0;
startStamp = millis();
timeStamp = startStamp;
lastStamp = timeStamp;
sec_tick.Reset();
dualcomm(timeAttack_data_json(timer, counter, lastStamp, timeStamp));
}
}
// Every Kick ---------------------------->>>
if(readImpact() > 100)
{
counter++;
dualcomm(timeAttack_data_json(timer, counter, lastStamp, timeStamp));
lastStamp = timeStamp;
delay(100);
}
// Every Second ---------------------------->>>
if(sec_tick.Trigger())
{
timer--;
dualcomm(timeAttack_data_json(timer, counter, 0, 0));
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
// TERMINAL("");
// TERMINAL("---------------------------------------------------");
dualcomm(GAME_OVER);
// TERMINAL("===================================================");
// TERMINAL("");
// LightUp
rainbowCycle(2);
// Grean Light In
LED_GREEN_FADEOUT();
// Return
return;
}
}
// Send End Game Signal To Smart Phone
// TERMINAL("");
// TERMINAL("---------------------------------------------------");
dualcomm(GAME_OVER);
// TERMINAL("===================================================");
// TERMINAL("");
// LightUp
LED_RED_FADEIN(); // RED Color
delay(2000); // Delay 2000
LED_CLEAR(); // CLEAR OFF
// Return
return;
}
//======================================================
// TIME ATTACK KICK DATA JSON -> To Send Back To Server
//======================================================
String timeAttack_data_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
{
// Building The Buffer
DynamicJsonDocument data(JSON_CAPACITY);
data["tm"] = RunningTime;
data["ct"] = KickCount;
// Calculations
if(TimeStamp > 0 )
{
// Calculate Time Stamp In Seconds
float st = TimeStamp;
st /= 1000;
data["st"] = String(st, 3).toFloat();
// Calculate Strike Delay In Seconds
float dl = TimeStamp - LastStamp;
dl /= 1000;
data["dl"] = String(dl, 3).toFloat();
}
String output;
serializeJson(data, output);
data.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void TimeAttack_Start()
{
// LightUp
LED_WHITE_CROSSFADE(3);
// Grean Light In
LED_GREEN();
}
//======================================================
// REACTION GAME END SINGNAL LED SIGNAL
//======================================================
void TimeAttack_End()
{
// Grean Light In
LED_GREEN_FADEOUT();
// Red Light In
LED_RED_FADEIN();
// Wait For 2 Sec
delay(2000);
// Red Light Out
LED_RED_FADEOUT();
}
//======================================================
// REACTION GAME START LED CELEBRATION
//======================================================
void TimeAttack_Celebration()
{
// LightUp
rainbowCycle(2);
// Grean Light OUT
LED_GREEN_FADEOUT();
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void TimeAttack_Reset()
{
LED_BLUE();
delay(250);
LED_BLUE_FADEOUT();
}
+450
View File
@@ -0,0 +1,450 @@
#define BETWEEN_FADE 15
#define FADE_RATE 15
#define BLINK_RATE 250
//======================================================
// SET STRIP COLOR
//======================================================
void rgbLED(int red, int green, int blue)
{
#ifdef ESP32
BOOST_ON;
#endif
for(int i=0; i<NUM_PIXELS; i++)
{
pixels.setPixelColor(i, pixels.Color(red,green,blue));
}
pixels.show();
}
//======================================================
// CLEAR SIGNAL LED COLOR : NO COLOR
//======================================================
void LED_CLEAR()
{
rgbLED(0, 0, 0);
}
//======================================================
// RED
//======================================================
void LED_RED()
{
#ifdef ESP32
BOOST_ON;
#endif
rgbLED(255, 0, 0);
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_RED_BLINK(int times)
{
#ifdef ESP32
BOOST_ON;
#endif
for(int i=0; i<times; i++)
{
LED_RED();
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// FADEIN
//------------------------------------------------------
void LED_RED_FADEIN()
{
#ifdef ESP32
BOOST_ON;
#endif
// Fade In Red Indicate That You Enter Battle
for(int i=0; i<=255; i=i+5)
{
rgbLED(i, 0, 0);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// FADEOUT
//------------------------------------------------------
void LED_RED_FADEOUT()
{
// Fade In Red Indicate That You Enter Battle
for(int i=255; i>=0; i=i-5)
{
rgbLED(i, 0, 0);
delay(FADE_RATE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// CROSS FADE
//------------------------------------------------------
void LED_RED_CROSSFADE(int times)
{
#ifdef ESP32
BOOST_ON;
#endif
for(int i=0; i<times; i++)
{
LED_RED_FADEIN();
delay(BETWEEN_FADE);
LED_RED_FADEOUT();
delay(BETWEEN_FADE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//======================================================
// GREEN
//======================================================
void LED_GREEN()
{
#ifdef ESP32
BOOST_ON;
#endif
rgbLED(0, 255, 0);
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_GREEN_BLINK(int times)
{
#ifdef ESP32
BOOST_ON;
#endif
for(int i=0; i<times; i++)
{
LED_GREEN();
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// FADEIN
//------------------------------------------------------
void LED_GREEN_FADEIN()
{
#ifdef ESP32
BOOST_ON;
#endif
// Fade In Red Indicate That You Enter Battle
for(int i=0; i<=255; i=i+5)
{
rgbLED(0, i, 0);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// FADEOUT
//------------------------------------------------------
void LED_GREEN_FADEOUT()
{
// Fade In Red Indicate That You Enter Battle
for(int i=255; i>=0; i=i-5)
{
rgbLED(0, i, 0);
delay(FADE_RATE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// CROSS FADE
//------------------------------------------------------
void LED_GREEN_CROSSFADE(int times)
{
#ifdef ESP32
BOOST_ON;
#endif
for(int i=0; i<times; i++)
{
LED_GREEN_FADEIN();
delay(BETWEEN_FADE);
LED_GREEN_FADEOUT();
delay(BETWEEN_FADE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//======================================================
// BLUE
//======================================================
void LED_BLUE()
{
#ifdef ESP32
BOOST_ON;
#endif
rgbLED(0, 0, 255);
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_BLUE_BLINK(int times)
{
#ifdef ESP32
BOOST_ON;
#endif
for(int i=0; i<times; i++)
{
LED_BLUE();
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// FADEIN
//------------------------------------------------------
void LED_BLUE_FADEIN()
{
#ifdef ESP32
BOOST_ON;
#endif
// Fade In Red Indicate That You Enter Battle
for(int i=0; i<=255; i=i+5)
{
rgbLED(0, 0, i);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// FADEOUT
//------------------------------------------------------
void LED_BLUE_FADEOUT()
{
#ifdef ESP32
BOOST_ON;
#endif
// Fade In Red Indicate That You Enter Battle
for(int i=255; i>=0; i=i-5)
{
rgbLED(0, 0, i);
delay(FADE_RATE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// CROSS FADE
//------------------------------------------------------
void LED_BLUE_CROSSFADE(int times)
{
#ifdef ESP32
BOOST_ON;
#endif
for(int i=0; i<times; i++)
{
LED_BLUE_FADEIN();
delay(BETWEEN_FADE);
LED_BLUE_FADEOUT();
delay(BETWEEN_FADE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//======================================================
// WHITE
//======================================================
void LED_WHITE()
{
#ifdef ESP32
BOOST_ON;
#endif
rgbLED(255, 255, 255);
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_WHITE_BLINK(int times)
{
#ifdef ESP32
BOOST_ON;
#endif
for(int i=0; i<times; i++)
{
LED_WHITE();
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// FADEIN
//------------------------------------------------------
void LED_WHITE_FADEIN()
{
#ifdef ESP32
BOOST_ON;
#endif
// Fade In Red Indicate That You Enter Battle
for(int i=0; i<=255; i=i+5)
{
rgbLED(i, i, i);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// FADEOUT
//------------------------------------------------------
void LED_WHITE_FADEOUT()
{
// Fade In Red Indicate That You Enter Battle
for(int i=255; i>=0; i=i-5)
{
rgbLED(i, i, i);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// CROSS FADE
//------------------------------------------------------
void LED_WHITE_CROSSFADE(int times)
{
for(int i=0; i<times; i++)
{
LED_WHITE_FADEIN();
delay(BETWEEN_FADE);
LED_WHITE_FADEOUT();
delay(BETWEEN_FADE);
}
}
//======================================================
// COLOR WHIPE
//======================================================
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait)
{
for(uint16_t i=0; i<NUM_PIXELS; i++)
{
pixels.setPixelColor(i, c);
pixels.show();
delay(wait);
}
}
//======================================================
// END GAME LIGHTING SIGNAL
//======================================================
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait)
{
uint16_t i, j;
for(j=0; j<256*5; j++)
{ // 5 cycles of all colors on wheel
for(i=0; i< pixels.numPixels(); i++)
{
pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
}
pixels.show();
delay(wait);
}
}
//======================================================
// END GAME LIGHTING SIGNAL
//======================================================
// 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)
{
WheelPos = 255 - WheelPos;
if(WheelPos < 85)
{
return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170)
{
WheelPos -= 85;
return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
+84
View File
@@ -0,0 +1,84 @@
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
#include <SSD1306Wire.h> // legacy include: `#include "SSD1306.h"
// Display Instance
SSD1306Wire display(0x3c, 21, 22);
void oled_init() {
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
display.clear();
display.display();
}
void drawTextFlowDemo(String Text) {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawStringMaxWidth(0, 0, 128, Text);
}
void drawTextAlignmentDemo() {
// Text alignment demo
display.setFont(ArialMT_Plain_10);
// The coordinates define the left starting point of the text
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 10, "Left aligned (0,10)");
// The coordinates define the center of the text
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 22, "Center aligned (64,22)");
// The coordinates define the right end of the text
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.drawString(128, 33, "Right aligned (128,33)");
}
void drawRectDemo() {
// Draw a pixel at given position
for (int i = 0; i < 10; i++) {
display.setPixel(i, i);
display.setPixel(10 - i, i);
}
display.drawRect(12, 12, 20, 20);
// Fill the rectangle
display.fillRect(14, 14, 17, 17);
// Draw a line horizontally
display.drawHorizontalLine(0, 40, 20);
// Draw a line horizontally
display.drawVerticalLine(40, 0, 20);
}
void drawCircleDemo() {
for (int i=1; i < 8; i++) {
display.setColor(WHITE);
display.drawCircle(32, 32, i*3);
if (i % 2 == 0) {
display.setColor(BLACK);
}
display.fillCircle(96, 32, 32 - i* 3);
}
}
void drawProgressBarDemo(int Value) {
int progress = Value;
// draw the progress bar
display.drawProgressBar(0, 50, 120, 10, progress);
// draw the percentage as String
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 35, String(progress) + "%");
}
void oled_clear() {
display.clear();
}
void oled_show() {
display.display();
}
+40
View File
@@ -0,0 +1,40 @@
//======================================================
// COMMUNICATION PORTS FUNCTIONS
//======================================================
// TERMINAL WINDOW - NATIVE USB
//------------------------------------------------------
void terminal(String msg)
{
msg += "\n";
Terminal.print(msg);
}
//------------------------------------------------------
// BLUETOOTH WINDOW - NATIVE
//------------------------------------------------------
void bluetooth(String msg)
{
msg += "\n";
Bluetooth.print(msg);
}
//------------------------------------------------------
// BLUETOOTH CONNECTION STATUS
//------------------------------------------------------
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
if(event == ESP_SPP_SRV_OPEN_EVT) {
BLUETOOTH_STATUS = true;
terminal(BLUETOOTH_CONNECTED);
}
if(event == ESP_SPP_CLOSE_EVT ) {
BLUETOOTH_STATUS = false;
terminal(BLUETOOTH_DISCONNECTED);
}
}
//------------------------------------------------------
// TERMINAL & BLUETOOTH WINDOW - NATIVE
//------------------------------------------------------
void dualcomm(String msg)
{
terminal(msg);
bluetooth(msg);
}
+22
View File
@@ -0,0 +1,22 @@
//======================================================
// THIS PAGE IS FOR GENERAL FUNCTIONS AND METHODES
//======================================================
// Floting Point Mapping
//------------------------------------------------------
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
//------------------------------------------------------
// MONITOR THE CENTER BUTTON RELEASE STATE
//------------------------------------------------------
void DETECT_LONG_PRESS() {
// Resetting The Timer For Long Press
POWER_PRESS.Reset();
// Loop If the Person Didnt Release The Button
while(!BTN_CENTER.released()) {
if(POWER_PRESS.Trigger()) {
OLED_POWERING_DOWN();
}
}
}
+196
View File
@@ -0,0 +1,196 @@
//======================================================
// MAIN COUNTER GAME LOOP
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : game_counter_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : game_counter_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// THIS IS THE STAND ALONE CALL FOR THE GAME
//======================================================
void game_counter_standalone()
{
// Instantiate eeprom objects with parameter/argument names and sizes
EEPROMClass game_counter_limit("eeprom0", 0x500);
EEPROMClass game_counter_limit_enable("eeprom1", 0x200);
EEPROMClass game_counter_result("eeprom2", 0x100);
if(!game_counter_limit.begin(game_counter_limit.length())) {
}
if(!game_counter_limit_enable.begin(game_counter_limit_enable.length())) {
}
if(!game_counter_result.begin(game_counter_result.length())) {
}
// Variables Of The Game
uint16_t limit = 0;
bool limitEnable = 0;
// Play The Game
game_counter(limit, limitEnable);
}
//======================================================
// THIS IS THE BLUETOOTH CALL FOR THE GAME
//======================================================
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
* --------------------------------------
*
* FORMAT :
* --------
* {"le": false, "lm": 10}
*
* MEANNING :
* ----------
* ct : count
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* WHAT JSON TO BE COLLECTED :
* ---------------------------
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
*
* CALCULATING RESULTS :
* ---------------------
* No calculation required, Its directly the count
*/
void game_counter_bluetooth(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
// Play The Game
game_counter(limit, limitEnable);
}
//======================================================
// COUNTER JSON JSON -> To Send Back To Server
//======================================================
void game_counter(uint16_t limit, bool limitEnable)
{
// Kick Counter
uint16_t counter = 0;
// Game Start Lights
//LED_SIGNAL_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// staring Of time stamp
unsigned long startStamp = millis();
while(1)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
//LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET)
{
counter = 0;
startStamp = millis();
timeStamp = startStamp;
//LED_SIGNAL_RESET();
}
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebration
//LED_SIGNAL_CELEBRATION();
// RESET
return;
}
// Read Impact
if(PIEZO_MAP >= VTH)
{
counter++;
GAME_COUNTER_DISPLAY(counter);
dualcomm(counter_JSON_json(counter, timeStamp));
delay(100);
}
}
}
//======================================================
// COUNTER JSON -> To Send Back To Mobile
//======================================================
String counter_JSON_json(unsigned int ct, unsigned int st)
{
// Convert Int To Float
float stamp = st;
stamp /= 1000;
// Assignning JSONset
JSON["ct"] = ct;
JSON["st"] = String(stamp, 3).toFloat();
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
+273
View File
@@ -0,0 +1,273 @@
//======================================================
// REACTION GAME MAIN ROUTINE
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : game_reaction_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : game_reaction_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
// Game Reaction DataType
struct grdt {
uint8_t trials = 0; // Number Of Strike Trials
uint8_t minDelay = 0; // Minimum Seconds Delay Between Signals
uint8_t maxDelay = 0; // Maximum Seconds Delay Between Signals
};
//======================================================
// Request From Stand Alone Buttons
//======================================================
void game_reaction_standalone()
{
// Variables
uint8_t minDelay = 0;
uint8_t maxDelay = 0;
uint8_t trials = 0;
// Display Screen Menu And Button Actions
// If The Menu Number 1 -> We Set The Value Of Min Delay
// If The Menu Number 2 -> We Set The Value Of Max Delay
// If The Menu Number 3 -> We Set The Number Of Trials
// Call the Game Play
play_reaction(minDelay, maxDelay, trials);
}
//======================================================
// Request From Bluetooth Via JSON
//======================================================
/* REACTION GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tr": 10, "mn": 1, "mx": 2}
*
* MEANNING :
* ----------
* tr : trials pre counter
* mn : minimum delay, between trials
* mx : maximum delay, between trials
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tr" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
*/
void game_reaction_bluetooth(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings);
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint8_t minDelay = JSON["mn"];
uint8_t maxDelay = JSON["mx"];
uint16_t trials = JSON["lm"];
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
// Play The Game
play_reaction(minDelay, maxDelay, trials);
}
//======================================================
// Play The Game
//======================================================
void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
{
// PUBLIC VARIABLES
uint16_t temp = trials;
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// DisJSON Welcome Message
terminal("");
terminal("trials : " + String(trials) + " Strikes");
terminal("minDelay : " + String(minDelay) + " Seconds");
terminal("maxDelay : " + String(maxDelay) + " Seconds");
terminal("2 Seconds To Start Get Ready & Good Luck !!");
terminal("");
// Main Variables
uint16_t sdelay = 0;
uint16_t power = 0;
uint16_t response = 0;
unsigned long startTime = 0;
unsigned long stopTime = 0;
// Ready Signal
//LED_SIGNAL_REACTION_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// Processing Results
for(int i=0; i<trials; i++)
{
// Reading Kick JSON
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
terminal(" -> Get Ready !!");
// Set Random Delay Time
sdelay = random(minDelay, maxDelay);
sdelay *= 1000;
delay(sdelay);
// Light Up Green
//LED_SET_COLOR(0, 255, 0, 255);
// Start Timer
startTime = millis();
// Sensing Strike Power
while(power < VTH)
{
// Reading The Strike
power = PIEZO_MAP;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP) {
dualcomm(GAME_OVER);
// LightUp
//LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET) {
//LED_SIGNAL_REACTION_RESET();
trials = temp;
break;
}
}
}
// Stop Timer
stopTime = millis();
// Stop Light
//LED_SET_COLOR(255, 0, 0, 255);
// Calculating Response Time
response = stopTime - startTime - 1;
// Create Json JSON
String msg = reaction_JSON_json(i+1, power, response, sdelay);
// Print To Terminal
dualcomm(msg);
// Clear All
sdelay = 0;
power = 0;
response = 0;
}
// Red Light Delay
delay(500);
// END GAME
dualcomm(GAME_OVER);
// Blink Red
//LED_SIGNAL_CELEBRATION();
// Return To Game Selector
return;
}
//======================================================
// REACTION JSON -> To Send Back To Mobile Device
//======================================================
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
{
// Convert To Seconds Unit
float re = response;
re /= 1000;
// Asignning Values
JSON["ct"] = count; // Strike Number
JSON["pw"] = power; // Strike Power In Analog Read
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void LED_SIGNAL_REACTION_START()
{
// Cross fade the white signal to get ready
//LED_CROSS_FADE(255, 255, 255, 3);
// Set the LED strip color to red
//LED_SET_COLOR(255, 0, 0, 255);
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void LED_SIGNAL_REACTION_RESET()
{
// Light Bright Blue
//LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
//delay(250);
// Fade Out The Blue
//LED_SET_COLOR(0, 255, 0, 255);
}
+103
View File
@@ -0,0 +1,103 @@
//======================================================
// MAIN PROGRAM LOOP
//======================================================
/* game selector is the main function that tell the game groutine
* which game to be JSONed and at what parameters
*/
void bluetooth_game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal(GM_COUNTER);
game_counter_bluetooth(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal(GM_TATTACK);
time_attack_bluetooth(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal(GM_REACTION);
game_reaction_bluetooth(settings);
return;
}
// Unknown Game
else {
dualcomm(UNKNOWN_GAME);
return;
}
}
//======================================================
// GAME SELECTOR CODE
//======================================================
// SELECTOR ROUTINE
//------------------------------------------------------
void standalone_game_selector()
{
// Check Bluetooth
if(isBluetooth)
{
// Reading The Message From Bluetooth
String message = Bluetooth.readStringUntil('\n');
// Cleaning Bluetooth Receive Buffer
flushBluetooth;
// Cleaning The Message
message.trim();
// Cleaning JSON Document
JSON.clear();
}
}
//------------------------------------------------------
// DISPLAY MENU TITLE FUNCTION
//------------------------------------------------------
void GAME_TITLE_DISPLAY(uint8_t Number, String Title)
{
// Starting The First Code
OLED_CLEAR();
drawTextCenter(128/2, 5, 1, "MODE " + String(Number + 1));
drawTextCenter(128/2, 22, 2, " - " + Title + " - ");
drawTextCenter(128/2, 43, 1, "<< SELECT >>");
OLED_SHOW();
DISPLAY_CHANGED = true;
}
//------------------------------------------------------
// OLED DISPLAY - GAME COUNTER
//------------------------------------------------------
void GAME_COUNTER_DISPLAY(uint16_t count)
{
OLED_CLEAR();
drawTextCenter(128/2, 0, 2, "KICKS");
drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
OLED_SHOW();
}
//------------------------------------------------------
// OLED DISPLAY - GAME TIMEATTACK
//------------------------------------------------------
void GAME_TIMEATTACK_DISPLAY(uint16_t count)
{
OLED_CLEAR();
drawTextCenter(128/2, 0, 2, "KICKS");
drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
OLED_SHOW();
}
//------------------------------------------------------
// OLED DISPLAY - GAME REACTION
//------------------------------------------------------
void GAME_REACTION_DISPLAY(uint16_t count)
{
OLED_CLEAR();
drawTextCenter(128/2, 0, 2, "KICKS");
drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
OLED_SHOW();
}
+239
View File
@@ -0,0 +1,239 @@
//======================================================
// TIME ATTACK GAME MAIN ROUTINE
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : time_attack_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : time_attack_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
// Game Time Attack DataType
struct gtdt {
uint16_t time = 30; // Max Time Of The Game In Sec
uint16_t limit = 0; // Max Kick Count
bool limit_ena = false; // Enable End Game If Max Kicks Meet
float kicksPerSecond = 0; // Game Time Attack Result
};
//======================================================
// Request From Stand Alone Buttons
//======================================================
void time_attack_standalone()
{
// Variables
uint16_t time = 0;
uint16_t timer = 0;
uint16_t limit = 0;
bool limitEnable = 0;
// Display Screen Menu And Button Actions
// If The Menu Number 1 -> We Set The Value Of Min Delay
// If The Menu Number 2 -> We Set The Value Of Max Delay
// If The Menu Number 3 -> We Set The Number Of Trials
// Call the Game Play
game_timeAttack(time, timer, limit, limitEnable);
}
//======================================================
// Request From Bluetooth Via JSON
//======================================================
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tm": 10, "le": false, "lm": 10}
*
* tm : count down timer starting value
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tm" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
*
* RETURNNING JSON FORMAT :
* ------------------------
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
*
* tm : timer count in Sec
* ct : strike counter (number of kicks)
* dl : delay between strikes
* st : time stampe of the strike in milli Seconds
*/
void time_attack_bluetooth(String settings)
{
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t time = JSON["tm"]; // Time Window To JSON
uint16_t timer = time;
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
// Play The Game
game_timeAttack(time, timer, limit, limitEnable);
}
//======================================================
// Play Time Atack Game
//======================================================
void game_timeAttack(uint16_t time, uint16_t timer, uint16_t limit, bool limitEnable)
{
// Building Timers 1000mSec -> 1Sec
TimeTrigger sec_tick(1000);
// Kick Counter
uint16_t counter = 0;
// Start LED Signal
//LED_SIGNAL_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// Send Initial DisJSON
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
// staring Of time stamp
unsigned long startStamp = millis();
// store the time of the previous kick
unsigned long lastStamp = 0;
// reseting time ticker
sec_tick.Reset();
// While The Game Is Still On
while(timer != 0)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
//LED_SIGNAL_END();
// Return
return;
}
else if(msg == CM_RESET)
{
timer = time;
counter = 0;
startStamp = millis();
timeStamp = startStamp;
lastStamp = timeStamp;
sec_tick.Reset();
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
//LED_SIGNAL_RESET();
}
}
// Every Kick ---------------------------->>>
if(PIEZO_MAP > VTH)
{
counter++;
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
lastStamp = timeStamp;
delay(100);
}
// Every Second ---------------------------->>>
if(sec_tick.Trigger())
{
timer--;
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebrate
//LED_SIGNAL_CELEBRATION();
// Return
return;
}
}
// Send End Game Signal To Smart Phone
dualcomm(GAME_OVER);
// LightUp
//LED_FADEIN(255, 0, 0); // RED Color
delay(2000); // Delay 2000
//LED_CLEAR(); // CLEAR OFF
// Return
return;
}
//======================================================
// TIME ATTACK KICK JSON -> To Send Back To Mobile
//======================================================
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
{
// Building The Buffer
JSON["tm"] = RunningTime;
JSON["ct"] = KickCount;
// Calculations
if(TimeStamp > 0)
{
// Calculate Time Stamp In Seconds
float st = TimeStamp;
st /= 1000;
JSON["st"] = String(st, 3).toFloat();
// Calculate Strike Delay In Seconds
float dl = TimeStamp - LastStamp;
dl /= 1000;
JSON["dl"] = String(dl, 3).toFloat();
}
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
+305
View File
@@ -0,0 +1,305 @@
/* ===============================================
* - THIS IS TAKEONE ESP32 BOARD -
* ===============================================
* MPU9250 Address : 0X69 (ADDRESS)
* OLED 128x64 Address : 0X3C (ADDRESS)
* -----------------------------------------------
* Description : PIN GPIO#
* -----------------------------------------------
* NEOPIXEL LED STRIP : A0/GPIO 26
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
* BUTTONS : TLB (35), BLB (15), CB (33), BRB (27), TRB(12)
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
* LED PIN : 13 (DIGITAL)
* BATTERY MONITOR PIN : 35 (ANALOG)
* -----------------------------------------------
* BUTTONS PINOUTS : PIN GPIO
* -----------------------------------------------
* TOP LEFT BUTTON : 15 - SWITCH PREVIOUS MENU / CHANGE PARAMETER
* TOP RIGHT BUTTON : 12 - SWITCH NEXT MENU / CHANGE PARAMETER
* BOTTOM LEFT BUTTON : 32 - POWER INC & BACK & INC PARAMETER
* BOTTOM RIGHT BUTTON : 27 - POWER DEC & SAVE & DEC PARAMETER
* CENTER BUTTON : 33 - POWER ON & SELECT
* -----------------------------------------------
* Exclusive Features Of TAKEONE BOARD
* -----------------------------------------------
* ESP32 TAKEONE Board has some unique hardware features
* 1. Battery Voltage Level Monitoring Via Analog Pin 35
* 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery
* 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom
* 4. SPI : SDCARD Reader */
//======================================================
// LIBRARIES
//======================================================
#include <Wire.h>
#include <EEPROM.h>
#include <Button.h>
#include <TimeTrigger.h>
#include <ArduinoJson.h>
#include <NeoPixelBus.h>
#include <BluetoothSerial.h>
//======================================================
// PUBLIC VARIABLES
//======================================================
uint8_t MENU_COUNT = 0;
bool BLUETOOTH_STATUS = false;
bool CHARGE_STATE = false;
bool DISPLAY_CHANGED = false;
//======================================================
// HARDWARE DEFINITIONS
//======================================================
// Nessesary Definition For Bluetooth Library
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
//------------------------------------------------------
// Serial Terminal
//------------------------------------------------------
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
//------------------------------------------------------
// Bluetooth Terminal
//------------------------------------------------------
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
//------------------------------------------------------
// Buttons
//------------------------------------------------------
Button BTN_PREVIOUS(15); // TL : 15 - SWITCH PREVIOUS MENU / CHANGE PARAMETER
Button BTN_NEXT(12); // TR : 12 - SWITCH NEXT MENU / CHANGE PARAMETER
Button BTN_CENTER(33); // CT : 33 - POWER INC & BACK & INC PARAMETER
Button BTN_INCREASE(32); // BL : 32 - POWER DEC & SAVE & DEC PARAMETER
Button BTN_DECREASE(27); // BR : 27 - POWER ON & SELECT
//------------------------------------------------------
// Boost 3V3 To 5V
//------------------------------------------------------
#define BOOST_PIN 14
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
#define BOOST_STU digitalRead(BOOST_PIN)
//------------------------------------------------------
// Keep Power On
//------------------------------------------------------
#define POWER_PIN 13
#define POWER_SETUP pinMode(POWER_PIN, OUTPUT)
#define POWER_OFF digitalWrite(POWER_PIN, LOW)
#define POWER_ON digitalWrite(POWER_PIN, HIGH)
TimeTrigger POWER_PRESS(4000); // The Interval In mSeconds
//------------------------------------------------------
// Piezo Transducer
//------------------------------------------------------
#define VTH 5 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define PIEZO_PIN 34 // IMPACT SENSOR
#define RANDOM_SOURCE 39 // RANDOM NUMBER GENERATOR SOURCE
#define PIEZO_READ analogRead(PIEZO_PIN)
#define PIEZO_MAP map(PIEZO_READ, VTH, 4095, 0, 100)
//------------------------------------------------------
// Battery Level Monitoring
//------------------------------------------------------
#define BATTERY_PIN 35
#define BATTERY (float)(((analogRead(BATTERY_PIN) * (3.3 / 4096)) * 2) + 0.31)
#define CHARGE round(mapf(BATTERY, 3.27, 4.31, 0, 100), 1)
//------------------------------------------------------
// Power Charging Status
//------------------------------------------------------
#define STAT_PIN 25
#define STAT_SETUP pinMode(STAT_PIN, INPUT)
#define STAT_READ digitalRead(STAT_PIN)
//------------------------------------------------------
// Neo Pixel LED Strip
//------------------------------------------------------
#define PIXEL_COUNT 21 // make sure to set this to the number of pixels in your strip
#define PIXEL_PIN 26 // make sure to set this to the correct pin, ignored for Esp8266
// three element pixels, in different order and speeds
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> PIXEL_STRIP(PIXEL_COUNT, PIXEL_PIN);
//------------------------------------------------------
// JSON Object & Memory
//------------------------------------------------------
#define CAPACITY 200
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// FIXED OPERATION MODE MESSAGES ~~~~~~~~~~~~~~~~~~~~~~
#define BLUETOOTH_START "{\"status\":\"BLUETOOTH STARTED\"}"
#define BLUETOOTH_FAIL "{\"status\":\"BLUETOOTH FAILED\"}"
#define BLUETOOTH_CONNECTED "{\"status\":\"BLUETOOTH CONNECTED\"}"
#define BLUETOOTH_DISCONNECTED "{\"status\":\"BLUETOOTH DISCONNECTED\"}"
#define STAND_ALONE_MODE "{\"status\":\"STAND ALONE MODE\"}"
// FIXED MESSAGES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define POWERUP "{\"status\":\"POWER UP\"}"
#define POWEROFF "{\"status\":\"POWER OFF\"}"
#define UNDERSTOOD "{\"status\":\"OK\"}"
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
// GAME NAMES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
#define GM_REACTION "{\"gm\":\"REACTION\"}"
#define GM_DECISION "{\"gm\":\"DECISION\"}"
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
// COMMAND LIST ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CM_START "{\"cm\":\"START\"}"
#define CM_RESET "{\"cm\":\"RESET\"}"
#define CM_STOP "{\"cm\":\"STOP\"}"
#define CM_EXIT "{\"cm\":\"EXIT\"}"
//======================================================
// MAIN SETUP
//======================================================
void setup()
{
// Power Hold
POWER_SETUP;
POWER_ON;
// Turn On Booster
BOOST_SETUP;
BOOST_OFF;
// Charging Status Pin
STAT_SETUP;
// I2C Module & OLED
Wire.begin();
delay(5);
OLED_INIT();
OLED_CLEAR();
OLED_SHOW();
// Start Buttons Function
BTN_PREVIOUS.begin();
BTN_NEXT.begin();
BTN_CENTER.begin();
BTN_INCREASE.begin();
BTN_DECREASE.begin();
// Communication Ports
Terminal.begin(9600); Terminal.println();
// To Detect Connection / Disconnection Event
Bluetooth.register_callback(callback);
// Starting Bluetooth Wireless With Name (KICKER)
if(!Bluetooth.begin("KICKER")) {
terminal(POWERUP);
terminal(BLUETOOTH_FAIL);
} else {
dualcomm(POWERUP);
dualcomm(BLUETOOTH_START);
}
// The Random Number Source
randomSeed(analogRead(RANDOM_SOURCE));
// Display Welcome Screen
KICKER_LOGO();
delay(2000);
}
//======================================================
// MAIN PROGRAM LOOP
//======================================================
void loop()
{
// This Is For Bluetooth Mode
if(BLUETOOTH_STATUS == true) {
OLED_BLUETOOTH_MODE();
while(BLUETOOTH_STATUS == true) {
ListenToBluetooth(); // Reading Only From Bluetooth
}
OLED_BLUETOOTH_MODE();
delay(1000);
terminal(STAND_ALONE_MODE);
}
// This Is For Stand Alone Mode
else {
OLED_STANDALONE_MODE();
while(BLUETOOTH_STATUS == false) {
ListenToStandAlone();
}
OLED_BLUETOOTH_MODE();
delay(1000);
}
}
//------------------------------------------------------
// LISTEN TO BLUETOOTH
//------------------------------------------------------
void ListenToBluetooth()
{
if(isBluetooth)
{
// Reading Message From Bluetooth
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
// Display On Serial Monitor For Debuging
terminal(msg);
// If It Was A Command To Power OFf
if(msg == POWEROFF) {
OLED_POWERING_DOWN();
}
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
dualcomm(UNDERSTOOD);
// Reading Game Name & Settings
String game = JSON["gm"];
String settings = JSON["set"];
// Clearing JSON Buffer
JSON.clear();
// Entering To Game Selector
bluetooth_game_selector(game, settings);
}
else
{
terminal(JSON_ERROR);
}
}
}
//------------------------------------------------------
// LISTEN TO STAND ALONE
//------------------------------------------------------
void ListenToStandAlone()
{
// SHIFT TO PREVIOUS GAME MENU
if(BTN_PREVIOUS.pressed())
{
DISPLAY_CHANGED = false;
MENU_COUNT-=1;
}
// SHIFT TO NEXT GAME MENU
else if(BTN_NEXT.pressed())
{
MENU_COUNT+=1;
}
// SELECT CURRENT DISPLAYED MENU
else if(BTN_CENTER.pressed())
{
DETECT_LONG_PRESS(); // IF LONG PRESS POWER OFF
}
switch(MENU_COUNT) {
case 1:
case 2:
case 3:
else :
}
}
+295
View File
@@ -0,0 +1,295 @@
////======================================================
//// NEO PIXEL LED STRIP
////======================================================
//// PUBLIC DEFINITIONS
////------------------------------------------------------
// #define BETWEEN_FADE 15
// #define FADE_RATE 15
// #define BLINK_RATE 250
// #define ColorSaturation 128
////------------------------------------------------------
//// PURE COLOR
////------------------------------------------------------
// RgbColor red(colorSaturation, 0, 0);
// RgbColor green(0, colorSaturation, 0);
// RgbColor blue(0, 0, colorSaturation);
// RgbColor white(colorSaturation);
// RgbColor black(0);
////------------------------------------------------------
//// HSL COLOR
////------------------------------------------------------
// HslColor hslRed(red);
// HslColor hslGreen(green);
// HslColor hslBlue(blue);
// HslColor hslWhite(white);
// HslColor hslBlack(black);
////------------------------------------------------------
//// Clearing The LED Strip
////------------------------------------------------------
// void LED_CLEAR()
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Clear The Strip Color
// PIXEL_STRIP.clear();
//
// // Show On LED Strip
// LED_SHOW();
// }
////------------------------------------------------------
//// DISPLAY ON STRIP
////------------------------------------------------------
// void LED_SHOW()
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Pass It To The LED Strip
// PIXEL_STRIP.show();
// }
////------------------------------------------------------
//// Set LED Brightness
////------------------------------------------------------
// void LED_SET_BRIGHTNESS(uint8_t Value)
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Set The Brightness
// PIXEL_STRIP.setBrightness(Value);
// }
////------------------------------------------------------
//// Set LED Color
////------------------------------------------------------
// void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Set Intensity
// LED_SET_BRIGHTNESS(Intensity);
//
// // Loop
// for(int i=0; i<NUM_PIXELS; i++) {
// PIXEL_STRIP.setPixelColor(i, PIXEL_STRIP.Color(R, G, B));
// }
//
// // Show The Colors On LED Strip
// LED_SHOW();
// }
////------------------------------------------------------
//// BLINK
////------------------------------------------------------
// void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
// {
// for(int i=0; i<Times; i++)
// {
// LED_SET_COLOR(R, G, B, 255);
// delay(BLINK_RATE);
// LED_CLEAR();
// delay(BLINK_RATE);
// }
// }
////------------------------------------------------------
//// COLOR WHIPE
////------------------------------------------------------
// // Fill the dots one after the other with a color
// void LED_COLOR_WIPE(uint32_t c, uint8_t wait)
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Work Loop
// for(uint16_t i=0; i<NUM_PIXELS; i++)
// {
// PIXEL_STRIP.setPixelColor(i, c);
// LED_SHOW();
// delay(wait);
// }
// }
////------------------------------------------------------
//// END GAME LIGHTING SIGNAL
////------------------------------------------------------
// // Slightly different, this makes the rainbow equally distributed throughout
// void LED_RAINBOW_CYCLE(uint8_t wait)
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Loop Variables
// uint16_t i, j;
//
// // The Loop
// for(j=0; j<256*5; j++)
// {
// // 5 cycles of all colors on WHEEL
// for(i=0; i< PIXEL_STRIP.numPixels(); i++)
// {
// PIXEL_STRIP.setPixelColor(i, LED_COLOR_WHEEL(((i * 256 / PIXEL_STRIP.numPixels()) + j) & 255));
// }
//
// LED_SHOW();
// delay(wait);
// }
// }
////------------------------------------------------------
//// END GAME LIGHTING SIGNAL
////------------------------------------------------------
// // Input a value 0 to 255 to get a color value.
// // The colours are a transition r - g - b - back to r.
// uint32_t LED_COLOR_WHEEL(byte WHEELPos)
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Wheel Sequance
// WHEELPos = 255 - WHEELPos;
//
// if(WHEELPos < 85)
// {
// return PIXEL_STRIP.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
// }
// if(WHEELPos < 170)
// {
// WHEELPos -= 85;
// return PIXEL_STRIP.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
// }
// WHEELPos -= 170;
// return PIXEL_STRIP.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
// }
////------------------------------------------------------
//// Set Color Fade In
////------------------------------------------------------
// void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Loop For Fade
// for(int i=0; i<=255; i++)
// {
// PIXEL_STRIP.setBrightness(i);
// for(int j=0; j<NUM_PIXELS; j++)
// {
// PIXEL_STRIP.setPixelColor(j, PIXEL_STRIP.Color(R, G, B));
// }
//
// LED_SHOW();
// delay(4);
// }
// }
////------------------------------------------------------
//// Set Color Fade Out
////------------------------------------------------------
// void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// // Loop For Fade Out
// for(int i=255; i>=0; i--)
// {
// PIXEL_STRIP.setBrightness(i);
// for(int j=0; j<NUM_PIXELS; j++)
// {
// PIXEL_STRIP.setPixelColor(j, PIXEL_STRIP.Color(R, G, B));
// }
//
// LED_SHOW();
// delay(4);
// }
// }
////------------------------------------------------------
//// Set LED Color Cross Fade
////------------------------------------------------------
// void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
// {
// // Make Sure Boost Is On
// BOOST_ON;
//
// for(int i=0; i<Times; i++)
// {
// LED_FADEIN(R, G, B);
// LED_FADEOUT(R, G, B);
// delay(BETWEEN_FADE);
// }
// }
////------------------------------------------------------
//// REACTION GAME START LED SIGNAL
////------------------------------------------------------
// void LED_SIGNAL_START()
// {
// // Cross Fade White Color To Get ready 3 Times
// LED_CROSS_FADE(255, 255, 255, 3);
//
// // Set Strip Color Green
// LED_SET_COLOR(0, 255, 0, 255);
// }
////------------------------------------------------------
//// REACTION GAME END SINGNAL LED SIGNAL
////------------------------------------------------------
// void LED_SIGNAL_END()
// {
// // Blink Red Twice
// LED_BLINK(255, 0, 0, 2);
//
// // Fade The Red Color To Nothing
// LED_FADEOUT(255, 0, 0);
// }
////------------------------------------------------------
//// REACTION GAME START LED CELEBRATION
////------------------------------------------------------
// void LED_SIGNAL_CELEBRATION()
// {
// // Display Rainbow Twice
// LED_RAINBOW_CYCLE(2);
//
// // Grean Light OUT
// LED_FADEOUT(0, 255, 0);
// }
////------------------------------------------------------
//// REACTION GAME RESET LED SIGNAL
////------------------------------------------------------
// void LED_SIGNAL_RESET()
// {
// // Light Bright Blue
// LED_BLINK(0, 0, 255, 2);
//
// // Wait For 1/4 Second
// delay(250);
//
// // Fade Out The Blue
// LED_SET_COLOR(0, 255, 0, 255);
//
// // Set Strip Color Green
// LED_SET_COLOR(0, 255, 0, 255);
// }
////------------------------------------------------------
//// DISPLAY BAHRAIN FLAG
////------------------------------------------------------
// void LED_BAHRAIN_FLAG()
// {
// BOOST_ON;
// LED_SET_BRIGHTNESS(255);
// LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 255, 255), 30); // White
// delay(250);
// LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 0, 0), 30); // Red
// delay(250);
// LED_FADEOUT(255, 0, 0);
// }
////------------------------------------------------------
//// DISPLAY COLOMBIA FLAG
////------------------------------------------------------
// void LED_COLOMBIA_FLAG()
// {
// BOOST_ON;
// LED_SET_BRIGHTNESS(255);
// LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 255, 0), 30); // Yellow
// delay(250);
// LED_COLOR_WIPE(PIXEL_STRIP.Color(0, 0, 255), 30); // Blue
// delay(250);
// LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 0, 0), 30); // Red
// delay(250);
// LED_FADEOUT(255, 0, 0);
// }
+272
View File
@@ -0,0 +1,272 @@
//======================================================
// OLED DISPLAY
//======================================================
// LIBRARY INCLUDE
//------------------------------------------------------
// Include Libraries
#include <Wire.h>
#include <SSD1306Wire.h>
// Display Instance
SSD1306Wire display(0x3c, 21, 22);
//------------------------------------------------------
// OLED INITIALIZATION
//------------------------------------------------------
void OLED_INIT() {
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
}
//------------------------------------------------------
// OLED CLEAR DISPLAY
//------------------------------------------------------
void OLED_CLEAR() {
display.clear();
}
//------------------------------------------------------
// OLED CLEAN DISPLAY
//------------------------------------------------------
void OLED_CLEAN() {
OLED_CLEAR();
OLED_SHOW();
}
//------------------------------------------------------
// OLED SHOW NEW DATA
//------------------------------------------------------
void OLED_SHOW() {
display.display();
}
//------------------------------------------------------
// OLED DISPLAY KICKER WELCOME MESSAGE
//------------------------------------------------------
void KICKER_LOGO() {
// Starting The First Code
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "TAKEONE");
drawTextCenter(128/2, 30, 1, " - T E C H N O L O G Y - ");
drawTextCenter(128/2, 43, 2, "<< KICKER >>");
OLED_SHOW();
}
//------------------------------------------------------
// OLED DISPLAY KICKER POWERING OFF MESSAGE
//------------------------------------------------------
void OLED_POWERING_DOWN() {
dualcomm(POWEROFF);
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "POWER");
drawTextCenter(128/2, 30, 1, "- T U R N I N G O F F -");
drawTextCenter(128/2, 43, 2, "SEE YOU AGAIN");
OLED_SHOW();
BOOST_OFF;
delay(2000);
OLED_CLEAN();
delay(250);
POWER_OFF;
}
//------------------------------------------------------
// OLED Display Text
//------------------------------------------------------
void drawTextFlowDemo(String Text) {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawStringMaxWidth(0, 0, 128, Text);
}
//------------------------------------------------------
// OLED LEFT TEXT Display
//------------------------------------------------------
void drawTextLeft() {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 10, "Left aligned (0,10)");
}
//------------------------------------------------------
// OLED CENTER TEXT Display
//------------------------------------------------------
void drawTextCenter(int X, int Y, int Size, String Text) {
//display.setFont(ArialMT_Plain_10);
if(Size == 1) {
display.setFont(ArialMT_Plain_10);
} else if(Size == 2) {
display.setFont(ArialMT_Plain_16);
} else if(Size == 3) {
display.setFont(ArialMT_Plain_24);
} else {
display.setFont(ArialMT_Plain_10);
}
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(X, Y, Text);
}
//------------------------------------------------------
// OLED RIGHT TEXT DISPLAY
//------------------------------------------------------
// OLED Display
void drawTextRight() {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.drawString(128, 33, "Right aligned (128,33)");
}
//------------------------------------------------------
// OLED DRAW RECTANGLE
//------------------------------------------------------
void drawRectDemo() {
// Draw a pixel at given position
for (int i = 0; i < 10; i++) {
display.setPixel(i, i);
display.setPixel(10 - i, i);
}
display.drawRect(12, 12, 20, 20);
// Fill the rectangle
display.fillRect(14, 14, 17, 17);
// Draw a line horizontally
display.drawHorizontalLine(0, 40, 20);
// Draw a line horizontally
display.drawVerticalLine(40, 0, 20);
}
//------------------------------------------------------
// OLED DRAW CIRCLE
//------------------------------------------------------
void drawCircleDemo() {
for (int i=1; i < 8; i++) {
display.setColor(WHITE);
display.drawCircle(32, 32, i*3);
if (i % 2 == 0) {
display.setColor(BLACK);
}
display.fillCircle(96, 32, 32 - i* 3);
}
}
//------------------------------------------------------
// OLED DRAW PROGRESS BAR
//------------------------------------------------------
void drawProgressBarDemo(int Value) {
int progress = Value;
// draw the progress bar
display.drawProgressBar(0, 50, 120, 10, progress);
// draw the percentage as String
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 35, String(progress) + "%");
}
//------------------------------------------------------
// I2C DECIVES SCANNER
//------------------------------------------------------
void scanI2C()
{
byte error, address;
int nDevices;
Serial.println(" -> Scanning I2C Devices ...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print(" --> Device Found At Address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print(" --> Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println(" --> No I2C devices found\n");
else
Serial.println(" --> done");
}
//------------------------------------------------------
// WAITING FOR BLUETOOTH CONNECTION
//------------------------------------------------------
void OLED_BLUETOOTH_MODE()
{
// Starting The First Code
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "KICKER");
drawTextCenter(128/2, 30, 1, " - B L U E T O O T H - ");
if(BLUETOOTH_STATUS == true) {
drawTextCenter(128/2, 43, 2, "< CONNECTED >");
} else {
drawTextCenter(128/2, 43, 2, "< WAITING >");
}
OLED_SHOW();
}
//------------------------------------------------------
// WAITING FOR BLUETOOTH CONNECTION
//------------------------------------------------------
void OLED_STANDALONE_MODE()
{
// Starting The First Code
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "KICKER");
drawTextCenter(128/2, 30, 1, " - S T A N D A L O N E - ");
drawTextCenter(128/2, 43, 2, "< MODE >");
OLED_SHOW();
}
//------------------------------------------------------
// GAME SLIDER SELECTOR
//------------------------------------------------------
void GAME_PAGE(uint8_t MenuNumber, String Title) {
if(DISPLAY_CHANGED == false) {
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "< GAME #" + String(MenuNumber) >);
drawTextCenter(128/2, 30, 1, " - " + Title + " - ");
drawTextCenter(128/2, 43, 2, "<< SELECT >>");
OLED_SHOW();
DISPLAY_CHANGED = true;
}
}
+53
View File
@@ -0,0 +1,53 @@
//====================================================================
// GENERAL FUNCTION SECTION
//====================================================================
// I2C DECIVES SCANNER
//--------------------------------------------------------------------
void scanI2C()
{
byte error, address;
int nDevices;
Serial.println(" -> Scanning I2C Devices ...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print(" --> Device Found At Address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print(" --> Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println(" --> No I2C devices found\n");
else
Serial.println(" --> done");
}
//--------------------------------------------------------------------
// Float Number Mapping Function
//--------------------------------------------------------------------
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
+41
View File
@@ -0,0 +1,41 @@
//====================================================================
// COUNTER GAME PROGRAM PAGE
//====================================================================
// GAME COUNTER - MENU
//--------------------------------------------------------------------
void game_counter_menu()
{
menu_display("COUNTER");
}
//--------------------------------------------------------------------
// GAME COUNTER - SETTINGS DISPLAY
//--------------------------------------------------------------------
void game_counter_settings()
{
}
//--------------------------------------------------------------------
// GAME COUNTER - GAME PLAY
//--------------------------------------------------------------------
void game_counter_play()
{
oled_clear();
drawTextCenter(128/2, 0, 2, "KICKS");
//drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
oled_show();
}
//--------------------------------------------------------------------
// GAME COUNTER - GAME FINAL RESULT
//--------------------------------------------------------------------
void game_counter_results()
{
}
+41
View File
@@ -0,0 +1,41 @@
//====================================================================
// DECISION GAME PROGRAM PAGE
//====================================================================
// GAME DECISION - MENU
//--------------------------------------------------------------------
void game_decision_menu()
{
menu_display("DECISION");
}
//--------------------------------------------------------------------
// GAME DECISION - SETTINGS DISPLAY
//--------------------------------------------------------------------
void game_decision_settings()
{
}
//--------------------------------------------------------------------
// GAME DECISION - GAME PLAY
//--------------------------------------------------------------------
void game_decision_play()
{
oled_clear();
drawTextCenter(128/2, 0, 2, "KICKS");
//drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
oled_show();
}
//--------------------------------------------------------------------
// GAME DECISION - GAME FINAL RESULT
//--------------------------------------------------------------------
void game_decision_results()
{
}
+42
View File
@@ -0,0 +1,42 @@
//====================================================================
// FOUCSE GAME PROGRAM PAGE
//====================================================================
// GAME FOUCSE - MENU
//--------------------------------------------------------------------
void game_foucse_menu()
{
menu_display("FOCUSE");
}
//--------------------------------------------------------------------
// GAME FOUCSE - SETTINGS DISPLAY
//--------------------------------------------------------------------
void game_foucse_settings()
{
}
//--------------------------------------------------------------------
// GAME FOUCSE - GAME PLAY
//--------------------------------------------------------------------
void game_foucse_play()
{
oled_clear();
drawTextCenter(128/2, 0, 2, "KICKS");
//drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
oled_show();
}
//--------------------------------------------------------------------
// GAME FOUCSE - GAME FINAL RESULT
//--------------------------------------------------------------------
void game_foucse_results()
{
}
+42
View File
@@ -0,0 +1,42 @@
//====================================================================
// REACTION GAME PROGRAM PAGE
//====================================================================
// GAME REACTION - MENU
//--------------------------------------------------------------------
void game_reaction_menu()
{
menu_display("REACTION");
}
//--------------------------------------------------------------------
// GAME REACTION - SETTINGS DISPLAY
//--------------------------------------------------------------------
void game_reaction_settings()
{
}
//--------------------------------------------------------------------
// GAME REACTION - GAME PLAY
//--------------------------------------------------------------------
void game_reaction_play()
{
oled_clear();
drawTextCenter(128/2, 0, 2, "KICKS");
//drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
oled_show();
}
//--------------------------------------------------------------------
// GAME REACTION - GAME FINAL RESULT
//--------------------------------------------------------------------
void game_reaction_results()
{
}
+41
View File
@@ -0,0 +1,41 @@
//====================================================================
// STAMINA GAME PROGRAM PAGE
//====================================================================
// GAME STAMINA - MENU
//--------------------------------------------------------------------
void game_stamina_menu()
{
menu_display("STAMINA");
}
//--------------------------------------------------------------------
// GAME STAMINA - SETTINGS DISPLAY
//--------------------------------------------------------------------
void game_stamina_settings()
{
}
//--------------------------------------------------------------------
// GAME STAMINA - GAME PLAY
//--------------------------------------------------------------------
void game_stamina_play()
{
oled_clear();
drawTextCenter(128/2, 0, 2, "KICKS");
//drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
oled_show();
}
//--------------------------------------------------------------------
// GAME STAMINA - GAME FINAL RESULT
//--------------------------------------------------------------------
void game_stamina_results()
{
}
+41
View File
@@ -0,0 +1,41 @@
//====================================================================
// TIMEATTACK GAME PROGRAM PAGE
//====================================================================
// GAME TIMEATTACK - MENU
//--------------------------------------------------------------------
void game_timeattack_menu()
{
menu_display("TIMEATTACK");
}
//--------------------------------------------------------------------
// GAME TIMEATTACK - SETTINGS DISPLAY
//--------------------------------------------------------------------
void game_timeattack_settings()
{
}
//--------------------------------------------------------------------
// GAME TIMEATTACK - GAME PLAY
//--------------------------------------------------------------------
void game_timeattack_play()
{
oled_clear();
drawTextCenter(128/2, 0, 2, "KICKS");
//drawTextCenter(128/2, 20, 3, String(count));
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
oled_show();
}
//--------------------------------------------------------------------
// GAME TIMEATTACK - GAME FINAL RESULT
//--------------------------------------------------------------------
void game_timeattack_results()
{
}
+58
View File
@@ -0,0 +1,58 @@
//====================================================================
// COUNTER GAME PROGRAM PAGE
//====================================================================
// DISPLAY MENU TITLE FUNCTION
//--------------------------------------------------------------------
void menu_display(String Title)
{
// Starting The First Code
oled_clear();
drawTextCenter(128/2, 5, 1, "MODE " + String(menu_count + 1));
drawTextCenter(128/2, 22, 2, " - " + Title + " - ");
drawTextCenter(128/2, 43, 1, "<< SELECT >>");
oled_show();
display_changed = true;
}
//--------------------------------------------------------------------
// SWITCH GAME MENUS
//--------------------------------------------------------------------
void switch_menu()
{
if(menu_count == 0 && display_changed == false) {
game_counter_menu();
} else if(menu_count == 1 && display_changed == false) {
game_timeattack_menu();
} else if(menu_count == 2 && display_changed == false) {
game_reaction_menu();
} else if(menu_count == 3 && display_changed == false) {
game_decision_menu();
} else if(menu_count == 4 && display_changed == false) {
game_stamina_menu();
} else if(menu_count == 5 && display_changed == false) {
game_foucse_menu();
}
}
//--------------------------------------------------------------------
// SELECT A GAME
//--------------------------------------------------------------------
void select_game()
{
if(menu_count == 0 && CB.pressed()) {
} else if(menu_count == 1 && CB.pressed()) {
} else if(menu_count == 2 && CB.pressed()) {
} else if(menu_count == 3 && CB.pressed()) {
} else if(menu_count == 4 && CB.pressed()) {
} else if(menu_count == 5 && CB.pressed()) {
}
}
+61
View File
@@ -0,0 +1,61 @@
//====================================================================
// ADAFRUITE NEO PIXEL
//====================================================================
// INCLUDE LIBRARY
//--------------------------------------------------------------------
// Neo Pixel Library
#include <Adafruit_NeoPixel.h>
// When setting up the NeoPixel library, we tell it how many pixels,
// and which pin to use to send signals. Note that for older NeoPixel
Adafruit_NeoPixel pixels(NUMPIXELS, NEOPIXEL, NEO_GRB + NEO_KHZ800);
//--------------------------------------------------------------------
// INITIALIZE LED STRIP OBJECT (REQUIRED)
//--------------------------------------------------------------------
void neo_init() {
BOOST_ON;
delay(5);
pixels.begin();
pixels.clear();
pixels.show();
delay(5);
BOOST_OFF;
}
//--------------------------------------------------------------------
// TURNON LED STRIP - FOR WELCOME
//--------------------------------------------------------------------
void neo_welcome() {
}
//--------------------------------------------------------------------
// TURNON LED STRIP WITH COLOR
//--------------------------------------------------------------------
void neo_color(uint8_t R, uint8_t G, uint8_t B) {
BOOST_ON;
delay(1);
pixels.clear();
for(int i=0; i<NUMPIXELS; i++)
{
pixels.setPixelColor(i, pixels.Color(R, G, B));
}
pixels.setBrightness(50);
delay(2);
pixels.show();
}
//--------------------------------------------------------------------
// TURNOFF LED STRIP
//--------------------------------------------------------------------
void neo_turnoff() {
pixels.clear();
pixels.show();
BOOST_OFF;
}
+175
View File
@@ -0,0 +1,175 @@
//====================================================================
// OLED DISPLAY
//====================================================================
// LIBRARY INCLUDE
//--------------------------------------------------------------------
// Include Libraries
#include <Wire.h>
#include <SSD1306Wire.h>
// Display Instance
SSD1306Wire display(0x3c, 21, 22);
//--------------------------------------------------------------------
// OLED Initialization
//--------------------------------------------------------------------
void oled_init() {
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
}
//--------------------------------------------------------------------
// OLED Display Text
//--------------------------------------------------------------------
void drawTextFlowDemo(String Text) {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawStringMaxWidth(0, 0, 128, Text);
}
//--------------------------------------------------------------------
// OLED LEFT TEXT Display
//--------------------------------------------------------------------
void drawTextLeft() {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 10, "Left aligned (0,10)");
}
//--------------------------------------------------------------------
// OLED CENTER TEXT Display
//--------------------------------------------------------------------
void drawTextCenter(int X, int Y, int Size, String Text) {
//display.setFont(ArialMT_Plain_10);
if(Size == 1) {
display.setFont(ArialMT_Plain_10);
} else if(Size == 2) {
display.setFont(ArialMT_Plain_16);
} else if(Size == 3) {
display.setFont(ArialMT_Plain_24);
} else {
display.setFont(ArialMT_Plain_10);
}
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(X, Y, Text);
}
//--------------------------------------------------------------------
// OLED RIGHT TEXT DISPLAY
//--------------------------------------------------------------------
// OLED Display
void drawTextRight() {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.drawString(128, 33, "Right aligned (128,33)");
}
//--------------------------------------------------------------------
// OLED DRAW RECTANGLE
//--------------------------------------------------------------------
void drawRectDemo() {
// Draw a pixel at given position
for (int i = 0; i < 10; i++) {
display.setPixel(i, i);
display.setPixel(10 - i, i);
}
display.drawRect(12, 12, 20, 20);
// Fill the rectangle
display.fillRect(14, 14, 17, 17);
// Draw a line horizontally
display.drawHorizontalLine(0, 40, 20);
// Draw a line horizontally
display.drawVerticalLine(40, 0, 20);
}
//--------------------------------------------------------------------
// OLED DRAW CIRCLE
//--------------------------------------------------------------------
void drawCircleDemo() {
for (int i=1; i < 8; i++) {
display.setColor(WHITE);
display.drawCircle(32, 32, i*3);
if (i % 2 == 0) {
display.setColor(BLACK);
}
display.fillCircle(96, 32, 32 - i* 3);
}
}
//--------------------------------------------------------------------
// OLED DRAW PROGRESS BAR
//--------------------------------------------------------------------
void drawProgressBarDemo(int Value) {
int progress = Value;
// draw the progress bar
display.drawProgressBar(0, 50, 120, 10, progress);
// draw the percentage as String
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 35, String(progress) + "%");
}
//--------------------------------------------------------------------
// OLED CLEAR DISPLAY
//--------------------------------------------------------------------
void oled_clear() {
display.clear();
}
//--------------------------------------------------------------------
// OLED SHOW NEW DATA
//--------------------------------------------------------------------
void oled_show() {
display.display();
}
//--------------------------------------------------------------------
// OLED DISPLAY KICKER WELCOME MESSAGE
//--------------------------------------------------------------------
void kicker_logo() {
// Starting The First Code
oled_clear();
drawTextCenter(128/2, 5, 3, "TAKEONE");
drawTextCenter(128/2, 30, 1, " - T E C H N O L O G Y - ");
drawTextCenter(128/2, 43, 2, "<< KICKER >>");
oled_show();
}
//--------------------------------------------------------------------
// OLED DISPLAY BATTERY LEVEL
//--------------------------------------------------------------------
void battery_level_display() {
// Counting Time
timetick = millis();
// Taking Action Based On Time Count
if(timetick - prevtick >= 5000)
{
prevtick = timetick;
String BV = String(BATTERY,2);
String BC = String(CHARGE, 0);
oled_clear();
drawTextFlowDemo("Battery Level : " + BV + " V Charge Level : " + BC + "%");
drawProgressBarDemo(BC.toInt());
oled_show();
}
}
+240
View File
@@ -0,0 +1,240 @@
//====================================================================
// SDCARD READER FUNCTIONS
//====================================================================
// LIST DIRECTORIES
//--------------------------------------------------------------------
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("Failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.println(file.name());
if(levels){
listDir(fs, file.name(), levels -1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
//--------------------------------------------------------------------
// CREATE DIRECTORY
//--------------------------------------------------------------------
void createDir(fs::FS &fs, const char * path){
Serial.printf("Creating Dir: %s\n", path);
if(fs.mkdir(path)){
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
//--------------------------------------------------------------------
// REMOVE DIRECTORIES
//--------------------------------------------------------------------
void removeDir(fs::FS &fs, const char * path){
Serial.printf("Removing Dir: %s\n", path);
if(fs.rmdir(path)){
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
//--------------------------------------------------------------------
// READ FILE
//--------------------------------------------------------------------
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if(!file){
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while(file.available()){
Serial.write(file.read());
}
file.close();
}
//--------------------------------------------------------------------
// WRITE TO A FILE / CREATE A NEW FILE
//--------------------------------------------------------------------
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
//--------------------------------------------------------------------
// WRITE TO THE BOTTOM OF A FILE / CONTINUE WRITING
//--------------------------------------------------------------------
void appendFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)){
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
//--------------------------------------------------------------------
// RENAME A FILE / CHNAGE THE NAME OF A FILE
//--------------------------------------------------------------------
void renameFile(fs::FS &fs, const char * path1, const char * path2){
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
//--------------------------------------------------------------------
// DELETE A FILE
//--------------------------------------------------------------------
void deleteFile(fs::FS &fs, const char * path){
Serial.printf("Deleting file: %s\n", path);
if(fs.remove(path)){
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
//--------------------------------------------------------------------
// SDCARD TEST ROUTINE
//--------------------------------------------------------------------
void testFileIO(fs::FS &fs, const char * path){
File file = fs.open(path);
static uint8_t buf[512];
size_t len = 0;
uint32_t start = millis();
uint32_t end = start;
if(file){
len = file.size();
size_t flen = len;
start = millis();
while(len){
size_t toRead = len;
if(toRead > 512){
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
end = millis() - start;
Serial.printf("%u bytes read for %u ms\n", flen, end);
file.close();
} else {
Serial.println("Failed to open file for reading");
}
file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
size_t i;
start = millis();
for(i=0; i<2048; i++){
file.write(buf, 512);
}
end = millis() - start;
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
file.close();
}
//--------------------------------------------------------------------
// STARTING SDCARD READER
//--------------------------------------------------------------------
void sdcard_init(){
if(!SD.begin()){
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
//listDir(SD, "/", 0);
//createDir(SD, "/mydir");
//listDir(SD, "/", 0);
//removeDir(SD, "/mydir");
//listDir(SD, "/", 2);
writeFile(SD, "/battery.txt", "Battery Monitoring");
//appendFile(SD, "/hello.txt", "World!\n");
//readFile(SD, "/hello.txt");
//deleteFile(SD, "/foo.txt");
//renameFile(SD, "/hello.txt", "/foo.txt");
//readFile(SD, "/foo.txt");
//testFileIO(SD, "/test.txt");
//Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
//Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
}
+379
View File
@@ -0,0 +1,379 @@
/* ===============================================
* - THIS IS TAKEONE BOARD -
* ===============================================
* MPU9250 Address : 0X69 (ADDRESS)
* OLED 128x64 Address : 0X3C (ADDRESS)
* -----------------------------------------------
* Description : PIN GPIO#
* -----------------------------------------------
* NEOPIXEL LED STRIP : A0/GPIO 26
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
* BUTTONS : TLB (35), BLB (15), CB (33), BRB (27), TRB(12)
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
* LED PIN : 13 (DIGITAL)
* BATTERY MONITOR PIN : 35 (ANALOG)
* -----------------------------------------------
* BUTTONS PINOUTS : PIN GPIO
* -----------------------------------------------
* TOP LEFT BUTTON : 15 - SWITCH PREVIOUS MENU / CHANGE PARAMETER
* TOP RIGHT BUTTON : 12 - SWITCH NEXT MENU / CHANGE PARAMETER
* BOTTOM LEFT BUTTON : 32 - POWER INC & BACK & INC PARAMETER
* BOTTOM RIGHT BUTTON : 27 - POWER DEC & SAVE & DEC PARAMETER
* CENTER BUTTON : 33 - POWER ON & SELECT
*/
// Include Library
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <Button.h>
#include <ArduinoJson.h>
#include <BluetoothSerial.h>
#include <Adafruit_NeoPixel.h>
//----------------------------------------------------------------
// Communication Models
//----------------------------------------------------------------
// Serial Port As Terminal
#define terminal Serial
// Clearing Terminal Remainning
#define flush_terminal while(terminal.available()) { terminal.read(); }
// Bluetooth Object
BluetoothSerial bluetooth;
// Bluetooth Connection Status
bool bluetooth_conn = false;
// Clearing Bluetooth Remainning
#define flush_bluetooth while(bluetooth.available()) { bluetooth.read(); }
// Fixed JSON Strings
#define POWERUP "{\"status\":\"POWER UP\"}"
#define UNDERSTOOD "{\"status\":\"OK\"}"
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
// GAME NAMES
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
#define GM_REACTION "{\"gm\":\"REACTION\"}"
#define GM_DECISION "{\"gm\":\"DECISION\"}"
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
// COMMAND LIST
#define CM_START "{\"cm\":\"START\"}"
#define CM_RESET "{\"cm\":\"RESET\"}"
#define CM_STOP "{\"cm\":\"STOP\"}"
#define CM_EXIT "{\"cm\":\"EXIT\"}"
// JSON CAPACITY
#define capacity 250
//----------------------------------------------------------------
// TAKEONE BOARD HARDWARE DEFINITIONS
//----------------------------------------------------------------
// On Board MPU9250 I2C Address
#define MPU_ADD 0x69
// Connected I2C OLED Address
#define OLED_ADD 0x3C
// Connected I2C LCD Address
#define LCD_ADD 0x2C
// Define Impact Sensor
#define PIEZO analogRead(34)
#define VOLTS mapf(PIEZO, 0, 4095, 0, 3.3)
// Panel Push Buttons Pin Assignment Sections
Button TLB(32); // Top Left Button
Button BLB(15); // Bottom Left Button
Button CB(33); // Center Button
Button BRB(27); // Bottom Right Button
Button TRB(12); // Top Right Button 33
// Panel Push Buttons Command Assignment
#define PrvMenu TLB.pressed()
#define NxtMenu TRB.pressed()
#define SelMenu CB.pressed()
#define IncBtn BLB.pressed()
#define DecBtn BRB.pressed()
// NEO Pixel Strip Section
#define NEOPIXEL 26 // Define Pin Number
#define NUMPIXELS 22 // Define Number Of LED's
// Battery Level Monitoring
#define BATTERY (float)(((analogRead(35) * (3.3 / 4096)) * 2) + 0.31)
#define CHARGE mapf(BATTERY, 3.27, 4.31, 0, 100)
// Power Latch Holder Pin
#define POWER_PIN 14
#define POWER_SETUP pinMode(POWER_PIN, OUTPUT)
#define POWER_ON digitalWrite(POWER_PIN, HIGH)
#define POWER_OFF digitalWrite(POWER_PIN, LOW)
// Battery To 5V Level Booster Setup & Control
#define BOOST_PIN 14
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
// On Board LED Setup & Control
#define LED_PIN 13
#define LED_SETUP pinMode(LED_PIN, OUTPUT)
#define LED_ON digitalWrite(LED_PIN, HIGH)
#define LED_OFF digitalWrite(LED_PIN, LOW)
// For Timming
unsigned long timetick = 0;
unsigned long prevtick = 0;
/* Display Change Flag Explaination
* This flag is used to prevent continous writing to the oled display
* once a change has happened we drive the display_changed to false this will tell
* the micro controller that a need to write new data is needed, after writing the new data to display
* then we drive the display_changed to true that means the nessary changes has been written
*/
bool display_changed = false;
uint8_t menu_count = 0;
//--------------------------------------------------------------------
// Bluetooth Connection Status Call Back
//--------------------------------------------------------------------
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
if(event == ESP_SPP_SRV_OPEN_EVT){
//Serial.println("Client Connected");
bluetooth_conn = true;
}
if(event == ESP_SPP_CLOSE_EVT ){
//Serial.println("Client disconnected");
bluetooth_conn = false;
}
}
//--------------------------------------------------------------------
// CHIP MAIN SETUP
//--------------------------------------------------------------------
void setup()
{
// Starting Serial Communications
terminal.begin(115200); // Starting Main USB UART Communication Interface
terminal.println(); // New Line Seperator 1
terminal.println(); // New Line Seperator 2
// Starting The Bluetooth Module
if(!bluetooth.begin("KICKER")) {
terminal.println("An error occurred initializing Bluetooth");
} else {
terminal.println("Bluetooth initialized");
}
// Checking The Connection Status
bluetooth.register_callback(callback);
// Pin Assignments
BOOST_SETUP; // Boost Converter Pin Setup
LED_SETUP; // OnBoard LED Pin Setup
// Turn Off The Pins
BOOST_OFF; // Turn Off The Booster
LED_OFF; // Turn Off The LED
// The Five Panel Buttons
TLB.begin(); // Setup The Top Left Panel Button
BLB.begin(); // Setup The Bottom Left Panel Button
BRB.begin(); // Setup The Bottom Right Panel Button
TRB.begin(); // Setup The Top Right Panel Button
CB.begin(); // Setup The Center Panel Button
// I2C Section
Wire.begin(); // Starting I2C Communication Interface
scanI2C(); // Starting I2C Communicatable Devices Detection
oled_init(); // Starting OLED Display I2C Communications
kicker_logo(); // Display Kicker Main Logo Display
// Starting SDCARD Interface
sdcard_init(); // Starting SDCARD Reader Communication Protocol
// Neo Pixel Section
neo_init(); // Starting Neo Pixel
neo_color(0, 0, 0); // Clear All LED's
delay(10); // Delay 10 Milli Seconds
neo_color(255, 0, 0); // Display RED LED Strip
delay(1000); // Delay 1 Second
neo_color(0, 255, 0); // Display GREEN LED Strip
delay(1000); // Delay 1 Second
neo_color(0, 0, 255); // Display BLUE LED Strip
delay(1000); // Delay 1 Second
neo_turnoff(); // Power Off Neo Pixels & Their Power
// THE PROGRAM STATE = MENU
display_changed = false; // Allow Display Change
}
//--------------------------------------------------------------------
// CHIP MAIN PROGRAM
//--------------------------------------------------------------------
void loop()
{
// Checking The Bluetooth Connection
bluetooth.register_callback(callback);
// Condition The Preiority Is For The Bluetooth
if(bluetooth_conn == true)
{
// Wait For Game JSON String
read_game_json();
}
// Condition To Stand Alone Mode - Manual Mode
else
{
// Previous Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(TLB.pressed()) {
if(menu_count == 0) {
menu_count = 4;
} else {
menu_count--;
}
display_changed = false;
}
// Next Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(TRB.pressed()) {
if(menu_count == 4) {
menu_count = 0;
} else {
menu_count++;
}
display_changed = false;
}
// Select A Game ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(CB.pressed()) {
select_game();
}
// Increase Power ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(BLB.pressed()) {
}
// Decrease Power ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(BRB.pressed()) {
}
// Display Target Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~
switch_menu();
}
}
//======================================================
// Read Game JSON String Command From Mobile
//======================================================
void read_game_json()
{
// Reading From Bluetooth
if(bluetooth.available())
{
// Reading Message From Bluetooth
String msg = bluetooth.readStringUntil('\n');
// Clearing The Receive Buffer
flush_bluetooth;
// Clean The Message
msg.trim();
// Display On Sertial
terminal.println(msg);
// Parsing Objects Message Objects
DynamicJsonDocument root(capacity);
// Deserialize the JSON document
DeserializationError error = deserializeJson(root, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
terminal.println(UNDERSTOOD);
bluetooth.println(UNDERSTOOD);
// Reading Game Name & Settings
String game = root["gm"];
String settings = root["set"];
// Clearing JSON Document Buffer
root.clear();
// Entering To Game Selector
game_selector(game, settings);
}
else
{
// Display On Serial
terminal.println(JSON_ERROR);
}
// Bluetooth Serial RXD Flush
flush_bluetooth;
}
}
//======================================================
// Game Selector Function
//======================================================
void game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal.println(GM_COUNTER);
//game_counter(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal.println(GM_TATTACK);
//game_timeAttack(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal.println(GM_REACTION);
//game_reaction(settings);
return;
}
// Unknown Game
else {
terminal.println(UNKNOWN_GAME);
bluetooth.println(UNKNOWN_GAME);
return;
}
}
@@ -0,0 +1,29 @@
//======================================================
// TERMINAL WINDOW - NATIVE USB
//======================================================
void terminal(String msg)
{
msg += "\n";
Terminal.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void bluetooth(String msg)
{
msg += "\n";
Bluetooth.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void dualcomm(String msg)
{
terminal(msg);
bluetooth(msg);
}
+192
View File
@@ -0,0 +1,192 @@
//======================================================
// MAIN COUNTER GAME LOOP
//======================================================
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
* --------------------------------------
*
* FORMAT :
* --------
* {"le": false, "lm": 10}
*
* MEANNING :
* ----------
* ct : count
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* WHAT DATA TO BE COLLECTED :
* ---------------------------
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISPLAY AND TIMESTAMP
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
*
* CALCULATING RESULTS :
* ---------------------
* No calculation required, Its directly the count
*/
void game_counter(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// CONVERTING GAME TEXT TO JSON
DynamicJsonDocument play(capacity); // building JSON Buffer
// Deserialize the JSON document
DeserializationError error = deserializeJson(play, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t limit = play["lm"]; // Kick Target Limit
bool limitEnable = play["le"]; // Enable Kick Target Limit
// Clearing Buffer
play.clear();
// Trying To Delete The Document
//play.delete();
// Kick Counter
uint16_t counter = 0;
// Game Start Lights
Counter_Start();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// staring Of time stamp
unsigned long startStamp = millis();
while(1)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readString();
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_GREEN_FADEOUT();
// RESET
return;
}
else if(msg == CM_RESET)
{
Counter_Reset();
counter = 0;
startStamp = millis();
timeStamp = startStamp;
}
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebration
Counter_Celebration();
// RESET
return;
}
// Read Impact
if(readImpact() > PWR)
{
counter++;
dualcomm(counter_data_json(counter, timeStamp));
delay(100);
}
}
}
//======================================================
// COUNTER DATA JSON -> To Send Back To Server
//======================================================
String counter_data_json(unsigned int ct, unsigned int st)
{
// Building The Buffer
DynamicJsonDocument data(capacity);
// Convert Int To Float
float stamp = st;
stamp /= 1000;
// Assignning Dataset
data["ct"] = ct;
data["st"] = String(stamp, 3).toFloat();
String output;
serializeJson(data, output);
data.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void Counter_Start()
{
// LightUp
LED_WHITE_CROSSFADE(2);
// Grean Light In
LED_GREEN();
}
//======================================================
// REACTION GAME END SINGNAL LED SIGNAL
//======================================================
void Counter_End()
{
// LightUp
LED_RED();
delay(2000);
// Red FadeOut
LED_RED_FADEOUT();
}
//======================================================
// REACTION GAME START LED CELEBRATION
//======================================================
void Counter_Celebration()
{
// LightUp
rainbowCycle(2);
// Grean Light OUT
LED_GREEN_FADEOUT();
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void Counter_Reset()
{
//
LED_BLUE();
delay(250);
LED_BLUE_FADEOUT();
}
@@ -0,0 +1,225 @@
//======================================================
// REACTION GAME MAIN ROUTINE
//======================================================
/* REACTION GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tr": 10, "mn": 1, "mx": 2}
*
* MEANNING :
* ----------
* tr : trials pre counter
* mn : minimum delay, between trials
* mx : maximum delay, between trials
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tr" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
*/
//======================================================
void game_reaction(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// CONVERTING GAME TEXT TO JSON
DynamicJsonDocument play(capacity);
// Deserialize the JSON document
DeserializationError error = deserializeJson(play, settings);
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint8_t minDelay = play["mx"];
uint8_t maxDelay = play["mn"];
uint16_t trials = play["lm"];
uint16_t temp = trials;
// Clearing Buffer
play.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// Display Welcome Message
terminal("");
terminal("trials : " + String(trials) + " Strikes");
terminal("minDelay : " + String(minDelay) + " Seconds");
terminal("maxDelay : " + String(maxDelay) + " Seconds");
terminal("2 Seconds To Start Get Ready & Good Luck !!");
terminal("");
// Ready Signal
Reaction_Start();
// Main Variables
uint16_t sdelay = 0;
uint16_t power = 0;
uint16_t response = 0;
unsigned long startTime = 0;
unsigned long stopTime = 0;
// Processing Results
for(int i=0; i<trials; i++)
{
// Reading Kick Data
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
terminal(" -> Get Ready !!");
// Set Random Delay Time
sdelay = random(minDelay, maxDelay);
sdelay *= 1000;
delay(sdelay);
// Light Up Green
rgbLED(0, 150, 0);
// Start Timer
startTime = millis();
// Sensing Strike Power
while(power < PWR)
{
// Reading The Strike
power = readImpact();
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readString();
msg.trim();
if(msg == CM_STOP) {
dualcomm(GAME_OVER);
// LightUp
LED_RED();
delay(2000);
// Red FadeOut
LED_RED_FADEOUT();
// RESET
return;
}
else if(msg == CM_RESET) {
trials = temp;
break;
}
}
}
// Stop Timer
stopTime = millis();
// Stop Light
rgbLED(150, 0, 0);
// Calculating Response Time
response = stopTime - startTime - 1;
// Create Json Data
String msg = reaction_data_json(i+1, power, response, sdelay);
// Print To Terminal
dualcomm(msg);
// Clear All
sdelay = 0;
power = 0;
response = 0;
}
// Red Light Delay
delay(500);
// END GAME
dualcomm(GAME_OVER);
// Blink Red
Reaction_End();
// Return To Game Selector
return;
}
//======================================================
// REACTION DATA JSON -> To Send Back To Server
//======================================================
String reaction_data_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
{
// Building The Buffer
DynamicJsonDocument data(capacity);
// Convert To Seconds Unit
float re = response;
re /= 1000;
// Asignning Values
data["ct"] = count; // Strike Number
data["pw"] = power; // Strike Power In Analog Read
data["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
data["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
String output;
serializeJson(data, output);
data.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void Reaction_Start()
{
LED_WHITE_CROSSFADE(3);
LED_RED_FADEIN();
}
//======================================================
// REACTION GAME END SINGNAL LED SIGNAL
//======================================================
void Reaction_End()
{
LED_RED_BLINK(2);
LED_RED_FADEOUT();
}
//======================================================
// REACTION GAME START LED CELEBRATION
//======================================================
void Reaction_Celebration()
{
// LightUp
rainbowCycle(2);
// Grean Light OUT
LED_GREEN_FADEOUT();
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void Reaction_Reset()
{
LED_BLUE();
delay(250);
LED_BLUE_FADEOUT();
}
@@ -0,0 +1,37 @@
//======================================================
// MAIN PROGRAM LOOP
//======================================================
/* game selector is the main function that tell the game groutine
* which game to be played and at what parameters
*/
void game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal(GM_COUNTER);
game_counter(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal(GM_TATTACK);
game_timeAttack(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal(GM_REACTION);
game_reaction(settings);
return;
}
// Unknown Game
else {
dualcomm(UNKNOWN_GAME);
return;
}
}
@@ -0,0 +1,239 @@
//======================================================
// TIME ATTACK GAME MAIN ROUTINE
//======================================================
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tm": 10, "le": false, "lm": 10}
*
* tm : count down timer starting value
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tm" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
*
* RETURNNING DATA FORMAT :
* ------------------------
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
*
* tm : timer count in Sec
* ct : strike counter (number of kicks)
* dl : delay between strikes
* st : time stampe of the strike in milli Seconds
*/
void game_timeAttack(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// CONVERTING GAME TEXT TO JSON
DynamicJsonDocument play(capacity); // building JSON Buffer
// Deserialize the JSON document
DeserializationError error = deserializeJson(play, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t time = play["tm"]; // Time Window To Play
uint16_t timer = time;
uint16_t limit = play["lm"]; // Kick Target Limit
bool limitEnable = play["le"]; // Enable Kick Target Limit
// Clearing Buffer
play.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// Send Initial Display
dualcomm(timeAttack_data_json(timer, 0, 0, 0));
// Start LED Signal
TimeAttack_Start();
// Building Timers 1000mSec -> 1Sec
TimeTrigger sec_tick(1000);
// Kick Counter
uint16_t counter = 0;
// staring Of time stamp
unsigned long startStamp = millis();
// store the time of the previous kick
unsigned long lastStamp = 0;
// reseting time ticker
sec_tick.Reset();
// While The Game Is Still On
while(timer != 0)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readString();
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_GREEN_FADEOUT();
// Return
return;
}
else if(msg == CM_RESET)
{
timer = time;
counter = 0;
startStamp = millis();
timeStamp = startStamp;
lastStamp = timeStamp;
sec_tick.Reset();
dualcomm(timeAttack_data_json(timer, counter, lastStamp, timeStamp));
}
}
// Every Kick ---------------------------->>>
if(readImpact() > 100)
{
counter++;
dualcomm(timeAttack_data_json(timer, counter, lastStamp, timeStamp));
lastStamp = timeStamp;
delay(100);
}
// Every Second ---------------------------->>>
if(sec_tick.Trigger())
{
timer--;
dualcomm(timeAttack_data_json(timer, counter, 0, 0));
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// LightUp
rainbowCycle(2);
// Grean Light In
LED_GREEN_FADEOUT();
// Return
return;
}
}
// Send End Game Signal To Smart Phone
dualcomm(GAME_OVER);
// LightUp
LED_RED_FADEIN(); // RED Color
delay(2000); // Delay 2000
LED_CLEAR(); // CLEAR OFF
// Return
return;
}
//======================================================
// TIME ATTACK KICK DATA JSON -> To Send Back To Server
//======================================================
String timeAttack_data_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
{
// Building The Buffer
DynamicJsonDocument data(capacity);
data["tm"] = RunningTime;
data["ct"] = KickCount;
// Calculations
if(TimeStamp > 0 )
{
// Calculate Time Stamp In Seconds
float st = TimeStamp;
st /= 1000;
data["st"] = String(st, 3).toFloat();
// Calculate Strike Delay In Seconds
float dl = TimeStamp - LastStamp;
dl /= 1000;
data["dl"] = String(dl, 3).toFloat();
}
String output;
serializeJson(data, output);
data.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void TimeAttack_Start()
{
// LightUp
LED_WHITE_CROSSFADE(2);
// Grean Light In
LED_GREEN_FADEIN();
}
//======================================================
// REACTION GAME END SINGNAL LED SIGNAL
//======================================================
void TimeAttack_End()
{
// Grean Light In
LED_GREEN_FADEOUT();
// Red Light In
LED_RED_FADEIN();
// Wait For 2 Sec
delay(2000);
// Red Light Out
LED_RED_FADEOUT();
}
//======================================================
// REACTION GAME START LED CELEBRATION
//======================================================
void TimeAttack_Celebration()
{
// LightUp
rainbowCycle(2);
// Grean Light OUT
LED_GREEN_FADEOUT();
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void TimeAttack_Reset()
{
LED_BLUE();
delay(250);
LED_BLUE_FADEOUT();
}
+209
View File
@@ -0,0 +1,209 @@
//======================================================
// LIBRARIES
//======================================================
#include <Button.h>
#include <ArduinoJson.h>
#include <TimeTrigger.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
// MODE SELECTION VARIABLES
int mode;
bool flagChange = false;
// FIXED MESSAGES
#define POWERUP "{\"status\":\"POWER UP\"}"
#define UNDERSTOOD "{\"status\":\"OK\"}"
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
// GAME NAMES
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
#define GM_REACTION "{\"gm\":\"REACTION\"}"
#define GM_DECISION "{\"gm\":\"DECISION\"}"
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
// COMMAND LIST
#define CM_START "{\"cm\":\"START\"}"
#define CM_RESET "{\"cm\":\"RESET\"}"
#define CM_STOP "{\"cm\":\"STOP\"}"
#define CM_EXIT "{\"cm\":\"EXIT\"}"
// JSON CAPACITY
#define capacity 250
//======================================================
// HARDWARE SELECTION
//======================================================
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define VTH 65 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define PWR 65 // MIN THRESHOLD VOLTAGE FROM ZERO POINT TO BE ACCOUNTED AS KICK
#define NUM_PIXELS 24 // NUMBER OF LED'S IN NEO PIXEL STRIP
// Incase You Are Using Arduino MEGA
#ifdef ARDUINO_AVR_MEGA2560
#define Bluetooth Serial1
Button button(52); // BUTTON ON PIN 2
#define LED_STRIP 53 // LED STRIP PIN NUMBER
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
// Incase You Are Using Arduino Nano
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
//----------------------------------------------------------
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
#include <SoftwareSerial.h>
//----------------------------------------------------------
SoftwareSerial Bluetooth(10, 11); // RX, TX
Button button(2); // BUTTON ON PIN 2
#define LED_STRIP A1 // LED STRIP PIN NUMBER
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A4 // RANDOM NUMBER GENERATOR SOURCE
// if This Was The ESP32 Core
#elif ESP32
//----------------------------------------------------------
#include <BluetoothSerial.h>
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
//----------------------------------------------------------
BluetoothSerial Bluetooth;
Button button(2); // BUTTON ON PIN 2
#define LED_STRIP 33 // LED STRIP PIN NUMBER
#define SENSOR_PIN 39 // IMPACT SENSOR
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
// End Of Arduino Selection ARDUINO_MEGA
#endif
// NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
//======================================================
// DEFINITION & DECLERATIONS
//======================================================
// Serial Flags
#define isBluetooth Bluetooth.available()
#define isTerminal Terminal.available()
//======================================================
// READING IMPACT POWER FROM ANALOG PINS
//======================================================
// READING THE IMPACT
int readImpact()
{
int value = abs(constrain(analogRead(SENSOR_PIN), VTH, 1023));
value = map(value, VTH, 1023, 0, 1023);
return value;
}
//======================================================
// MAIN HARDWARE SETUP
//======================================================
void setup()
{
// Communications
Terminal.begin(9600);
// Make Sure Of The Core
#ifdef ESP32
Bluetooth.begin("KICKER"); //Bluetooth device name
#else
Bluetooth.begin(9600);
#endif
// I/O
button.begin(); // Button
pixels.begin(); // Neo Pixel
LED_CLEAR(); // Turn Off All LED
// The Random Number Source
randomSeed(analogRead(RANDOM_SOURCE));
// POWER UP MESSGAE
dualcomm(POWERUP);
// Display Color Wipe
colorWipe(pixels.Color(255, 255, 255), 15); // White
delay(100);
colorWipe(pixels.Color(0, 0, 255), 15); // Blue
delay(100);
colorWipe(pixels.Color(255, 0, 0), 15); // Red
delay(100);
colorWipe(pixels.Color(0, 255, 0), 15); // Green
// Delay 1 Sec
delay(500);
// Red FadeOut
LED_GREEN_FADEOUT();
// Display Rainbow
LED_CLEAR();
}
//======================================================
// MAIN PROGRAM LOOP
//======================================================
void loop()
{
// Reading From Bluetooth
if(Bluetooth.available())
{
// Reading Message From Bluetooth
String msg = Bluetooth.readString();
msg.trim();
// Display On Sertial
terminal(msg);
// Parsing Objects Message Objects
DynamicJsonDocument root(capacity);
// Deserialize the JSON document
DeserializationError error = deserializeJson(root, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
dualcomm(UNDERSTOOD);
// Reading Game Name & Settings
String game = root["gm"];
String settings = root["set"];
// Clearing JSON Buffer
root.clear();
// Entering To Game Selector
game_selector(game, settings);
}
else
{
terminal(JSON_ERROR);
}
Bluetooth.flush();
}
}
//======================================================
// END OF PROGRAM
//======================================================
+350
View File
@@ -0,0 +1,350 @@
#define BETWEEN_FADE 15
#define FADE_RATE 15
#define BLINK_RATE 250
//======================================================
// SET STRIP COLOR
//======================================================
void rgbLED(int red, int green, int blue)
{
for(int i=0; i<NUM_PIXELS; i++)
{
pixels.setPixelColor(i, pixels.Color(red,green,blue));
}
pixels.show();
}
//======================================================
// CLEAR SIGNAL LED COLOR : NO COLOR
//======================================================
void LED_CLEAR()
{
rgbLED(0, 0, 0);
}
//======================================================
// RED
//======================================================
void LED_RED()
{
rgbLED(255, 0, 0);
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_RED_BLINK(int times)
{
for(int i=0; i<times; i++)
{
LED_RED();
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
}
//------------------------------------------------------
// FADEIN
//------------------------------------------------------
void LED_RED_FADEIN()
{
// Fade In Red Indicate That You Enter Battle
for(int i=0; i<=255; i=i+5)
{
rgbLED(i, 0, 0);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// FADEOUT
//------------------------------------------------------
void LED_RED_FADEOUT()
{
// Fade In Red Indicate That You Enter Battle
for(int i=255; i>=0; i=i-5)
{
rgbLED(i, 0, 0);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// CROSS FADE
//------------------------------------------------------
void LED_RED_CROSSFADE(int times)
{
for(int i=0; i<times; i++)
{
LED_RED_FADEIN();
delay(BETWEEN_FADE);
LED_RED_FADEOUT();
delay(BETWEEN_FADE);
}
}
//======================================================
// GREEN
//======================================================
void LED_GREEN()
{
rgbLED(0, 255, 0);
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_GREEN_BLINK(int times)
{
for(int i=0; i<times; i++)
{
LED_GREEN();
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
}
//------------------------------------------------------
// FADEIN
//------------------------------------------------------
void LED_GREEN_FADEIN()
{
// Fade In Red Indicate That You Enter Battle
for(int i=0; i<=255; i=i+5)
{
rgbLED(0, i, 0);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// FADEOUT
//------------------------------------------------------
void LED_GREEN_FADEOUT()
{
// Fade In Red Indicate That You Enter Battle
for(int i=255; i>=0; i=i-5)
{
rgbLED(0, i, 0);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// CROSS FADE
//------------------------------------------------------
void LED_GREEN_CROSSFADE(int times)
{
for(int i=0; i<times; i++)
{
LED_GREEN_FADEIN();
delay(BETWEEN_FADE);
LED_GREEN_FADEOUT();
delay(BETWEEN_FADE);
}
}
//======================================================
// BLUE
//======================================================
void LED_BLUE()
{
rgbLED(0, 0, 255);
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_BLUE_BLINK(int times)
{
for(int i=0; i<times; i++)
{
LED_BLUE();
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
}
//------------------------------------------------------
// FADEIN
//------------------------------------------------------
void LED_BLUE_FADEIN()
{
// Fade In Red Indicate That You Enter Battle
for(int i=0; i<=255; i=i+5)
{
rgbLED(0, 0, i);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// FADEOUT
//------------------------------------------------------
void LED_BLUE_FADEOUT()
{
// Fade In Red Indicate That You Enter Battle
for(int i=255; i>=0; i=i-5)
{
rgbLED(0, 0, i);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// CROSS FADE
//------------------------------------------------------
void LED_BLUE_CROSSFADE(int times)
{
for(int i=0; i<times; i++)
{
LED_BLUE_FADEIN();
delay(BETWEEN_FADE);
LED_BLUE_FADEOUT();
delay(BETWEEN_FADE);
}
}
//======================================================
// WHITE
//======================================================
void LED_WHITE()
{
rgbLED(255, 255, 255);
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_WHITE_BLINK(int times)
{
for(int i=0; i<times; i++)
{
LED_WHITE();
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
}
//------------------------------------------------------
// FADEIN
//------------------------------------------------------
void LED_WHITE_FADEIN()
{
// Fade In Red Indicate That You Enter Battle
for(int i=0; i<=255; i=i+5)
{
rgbLED(i, i, i);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// FADEOUT
//------------------------------------------------------
void LED_WHITE_FADEOUT()
{
// Fade In Red Indicate That You Enter Battle
for(int i=255; i>=0; i=i-5)
{
rgbLED(i, i, i);
delay(FADE_RATE);
}
}
//------------------------------------------------------
// CROSS FADE
//------------------------------------------------------
void LED_WHITE_CROSSFADE(int times)
{
for(int i=0; i<times; i++)
{
LED_WHITE_FADEIN();
delay(BETWEEN_FADE);
LED_WHITE_FADEOUT();
delay(BETWEEN_FADE);
}
}
//======================================================
// COLOR WHIPE
//======================================================
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait)
{
for(uint16_t i=0; i<NUM_PIXELS; i++)
{
pixels.setPixelColor(i, c);
pixels.show();
delay(wait);
}
}
//======================================================
// END GAME LIGHTING SIGNAL
//======================================================
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait)
{
uint16_t i, j;
for(j=0; j<256*5; j++)
{ // 5 cycles of all colors on wheel
for(i=0; i< pixels.numPixels(); i++)
{
pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
}
pixels.show();
delay(wait);
}
}
//======================================================
// END GAME LIGHTING SIGNAL
//======================================================
// 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)
{
WheelPos = 255 - WheelPos;
if(WheelPos < 85)
{
return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170)
{
WheelPos -= 85;
return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
@@ -0,0 +1,29 @@
//======================================================
// TERMINAL WINDOW - NATIVE USB
//======================================================
void terminal(String msg)
{
msg += "\n";
Terminal.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void bluetooth(String msg)
{
msg += "\n";
Bluetooth.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void dualcomm(String msg)
{
terminal(msg);
bluetooth(msg);
}
+137
View File
@@ -0,0 +1,137 @@
//======================================================
// MAIN COUNTER GAME LOOP
//======================================================
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
* --------------------------------------
*
* FORMAT :
* --------
* {"le": false, "lm": 10}
*
* MEANNING :
* ----------
* ct : count
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* WHAT JSON TO BE COLLECTED :
* ---------------------------
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
*
* CALCULATING RESULTS :
* ---------------------
* No calculation required, Its directly the count
*/
void game_counter(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
// Trying To Delete The Document
//JSON.delete();
// Kick Counter
uint16_t counter = 0;
// Game Start Lights
LED_SIGNAL_START();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// staring Of time stamp
unsigned long startStamp = millis();
while(1)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET)
{
counter = 0;
startStamp = millis();
timeStamp = startStamp;
LED_SIGNAL_RESET();
}
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebration
LED_SIGNAL_CELEBRATION();
// RESET
return;
}
// Read Impact
if(readImpact() > VTH)
{
counter++;
dualcomm(counter_JSON_json(counter, timeStamp));
delay(100);
}
}
}
//======================================================
// COUNTER JSON JSON -> To Send Back To Server
//======================================================
String counter_JSON_json(unsigned int ct, unsigned int st)
{
// Convert Int To Float
float stamp = st;
stamp /= 1000;
// Assignning JSONset
JSON["ct"] = ct;
JSON["st"] = String(stamp, 3).toFloat();
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
@@ -0,0 +1,203 @@
//======================================================
// REACTION GAME MAIN ROUTINE
//======================================================
/* REACTION GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tr": 10, "mn": 1, "mx": 2}
*
* MEANNING :
* ----------
* tr : trials pre counter
* mn : minimum delay, between trials
* mx : maximum delay, between trials
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tr" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
*/
//======================================================
void game_reaction(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings);
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint8_t minDelay = JSON["mn"];
uint8_t maxDelay = JSON["mx"];
uint16_t trials = JSON["lm"];
uint16_t temp = trials;
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// DisJSON Welcome Message
terminal("");
terminal("trials : " + String(trials) + " Strikes");
terminal("minDelay : " + String(minDelay) + " Seconds");
terminal("maxDelay : " + String(maxDelay) + " Seconds");
terminal("2 Seconds To Start Get Ready & Good Luck !!");
terminal("");
// Ready Signal
LED_SIGNAL_REACTION_START();
// Main Variables
uint16_t sdelay = 0;
uint16_t power = 0;
uint16_t response = 0;
unsigned long startTime = 0;
unsigned long stopTime = 0;
// Processing Results
for(int i=0; i<trials; i++)
{
// Reading Kick JSON
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
terminal(" -> Get Ready !!");
// Set Random Delay Time
sdelay = random(minDelay, maxDelay);
sdelay *= 1000;
delay(sdelay);
// Light Up Green
LED_SET_COLOR(0, 255, 0, 255);
// Start Timer
startTime = millis();
// Sensing Strike Power
while(power < VTH)
{
// Reading The Strike
power = readImpact();
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
msg.trim();
if(msg == CM_STOP) {
dualcomm(GAME_OVER);
// LightUp
LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET) {
LED_SIGNAL_REACTION_RESET();
trials = temp;
break;
}
}
}
// Stop Timer
stopTime = millis();
// Stop Light
LED_SET_COLOR(255, 0, 0, 255);
// Calculating Response Time
response = stopTime - startTime - 1;
// Create Json JSON
String msg = reaction_JSON_json(i+1, power, response, sdelay);
// Print To Terminal
dualcomm(msg);
// Clear All
sdelay = 0;
power = 0;
response = 0;
}
// Red Light Delay
delay(500);
// END GAME
dualcomm(GAME_OVER);
// Blink Red
LED_SIGNAL_CELEBRATION();
// Return To Game Selector
return;
}
//======================================================
// REACTION JSON JSON -> To Send Back To Server
//======================================================
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
{
// Convert To Seconds Unit
float re = response;
re /= 1000;
// Asignning Values
JSON["ct"] = count; // Strike Number
JSON["pw"] = power; // Strike Power In Analog Read
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void LED_SIGNAL_REACTION_START()
{
// Cross fade the white signal to get ready
LED_CROSS_FADE(255, 255, 255, 3);
// Set the LED strip color to red
LED_SET_COLOR(255, 0, 0, 255);
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void LED_SIGNAL_REACTION_RESET()
{
// Light Bright Blue
LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
delay(250);
// Fade Out The Blue
LED_SET_COLOR(0, 255, 0, 255);
}
@@ -0,0 +1,37 @@
//======================================================
// MAIN PROGRAM LOOP
//======================================================
/* game selector is the main function that tell the game groutine
* which game to be JSONed and at what parameters
*/
void game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal(GM_COUNTER);
game_counter(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal(GM_TATTACK);
game_timeAttack(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal(GM_REACTION);
game_reaction(settings);
return;
}
// Unknown Game
else {
dualcomm(UNKNOWN_GAME);
return;
}
}
@@ -0,0 +1,184 @@
//======================================================
// TIME ATTACK GAME MAIN ROUTINE
//======================================================
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tm": 10, "le": false, "lm": 10}
*
* tm : count down timer starting value
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tm" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
*
* RETURNNING JSON FORMAT :
* ------------------------
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
*
* tm : timer count in Sec
* ct : strike counter (number of kicks)
* dl : delay between strikes
* st : time stampe of the strike in milli Seconds
*/
void game_timeAttack(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t time = JSON["tm"]; // Time Window To JSON
uint16_t timer = time;
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// Send Initial DisJSON
dualcomm(timeAttack_JSON_json(timer, 0, 0, 0));
// Start LED Signal
LED_SIGNAL_START();
// Building Timers 1000mSec -> 1Sec
TimeTrigger sec_tick(1000);
// Kick Counter
uint16_t counter = 0;
// staring Of time stamp
unsigned long startStamp = millis();
// store the time of the previous kick
unsigned long lastStamp = 0;
// reseting time ticker
sec_tick.Reset();
// While The Game Is Still On
while(timer != 0)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_SIGNAL_END();
// Return
return;
}
else if(msg == CM_RESET)
{
timer = time;
counter = 0;
startStamp = millis();
timeStamp = startStamp;
lastStamp = timeStamp;
sec_tick.Reset();
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
LED_SIGNAL_RESET();
}
}
// Every Kick ---------------------------->>>
if(readImpact() > VTH)
{
counter++;
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
lastStamp = timeStamp;
delay(100);
}
// Every Second ---------------------------->>>
if(sec_tick.Trigger())
{
timer--;
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebrate
LED_SIGNAL_CELEBRATION();
// Return
return;
}
}
// Send End Game Signal To Smart Phone
dualcomm(GAME_OVER);
// LightUp
LED_FADEIN(255, 0, 0); // RED Color
delay(2000); // Delay 2000
LED_CLEAR(); // CLEAR OFF
// Return
return;
}
//======================================================
// TIME ATTACK KICK JSON JSON -> To Send Back To Server
//======================================================
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
{
// Building The Buffer
JSON["tm"] = RunningTime;
JSON["ct"] = KickCount;
// Calculations
if(TimeStamp > 0)
{
// Calculate Time Stamp In Seconds
float st = TimeStamp;
st /= 1000;
JSON["st"] = String(st, 3).toFloat();
// Calculate Strike Delay In Seconds
float dl = TimeStamp - LastStamp;
dl /= 1000;
JSON["dl"] = String(dl, 3).toFloat();
}
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
+197
View File
@@ -0,0 +1,197 @@
//======================================================
// LIBRARIES
//======================================================
#include <ArduinoJson.h>
#include <TimeTrigger.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
//======================================================
// JSON STRINGS AND DOCUMENT
//======================================================
// FIXED MESSAGES
#define POWERUP "{\"status\":\"POWER UP\"}"
#define UNDERSTOOD "{\"status\":\"OK\"}"
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
// GAME NAMES
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
#define GM_REACTION "{\"gm\":\"REACTION\"}"
#define GM_DECISION "{\"gm\":\"DECISION\"}"
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
// COMMAND LIST
#define CM_START "{\"cm\":\"START\"}"
#define CM_RESET "{\"cm\":\"RESET\"}"
#define CM_STOP "{\"cm\":\"STOP\"}"
#define CM_EXIT "{\"cm\":\"EXIT\"}"
// JSON CAPACITY
#define CAPACITY 100
// Public JSON Document
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
//======================================================
// HARDWARE SETUP & SELECTION
//======================================================
// Arduino Hardware Serial Port
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
// The Integer Value Of The Strike Is Exceeded Accept As A Point
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
// Number Of LED's In The Neo Pixel Strip
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
// Incase You Are Using Arduino MEGA
#ifdef ARDUINO_AVR_MEGA2560
#define Bluetooth Serial1 // We will Connect The HC-05 To Hardware Serial1 In Arduino Mega
#define LED_STRIP 53 // LED STRIP PIN NUMBER
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
// Incase You Are Using Arduino Nano
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
//----------------------------------------------------------
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
#include <SoftwareSerial.h>
//----------------------------------------------------------
SoftwareSerial Bluetooth(10, 11); // Pin 10 RX, Pin 11 TX
#define LED_STRIP 2 // LED STRIP PIN NUMBER
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A4 // RANDOM NUMBER GENERATOR SOURCE
// if This Was The ESP32 Core
#elif ESP32
//----------------------------------------------------------
#include <BluetoothSerial.h>
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
//----------------------------------------------------------
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
#define LED_STRIP 33 // LED STRIP PIN NUMBER
#define SENSOR_PIN 39 // IMPACT SENSOR
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
// End Of Arduino Selection ARDUINO_MEGA
#endif
// NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
//======================================================
// DEFINITION & DECLERATIONS
//======================================================
// Serial Flags
#define isBluetooth Bluetooth.available()
#define isTerminal Terminal.available()
//======================================================
// READING IMPACT POWER FROM ANALOG PINS
//======================================================
// READING THE IMPACT
int readImpact()
{
int value = analogRead(SENSOR_PIN);
return value;
}
//======================================================
// MAIN HARDWARE SETUP
//======================================================
void setup()
{
// Communications
Terminal.begin(9600);
// Make Sure Of The Core
#ifdef ESP32
Bluetooth.begin("KICKER"); //Bluetooth device name
#else
Bluetooth.begin(9600);
#endif
// I/O
pixels.begin(); // Neo Pixel
LED_CLEAR(); // Turn Off All LED
// The Random Number Source
randomSeed(analogRead(RANDOM_SOURCE));
// POWER UP MESSGAE
dualcomm(POWERUP);
// DISPLAY COMPANY COUNTRY FLAG
LED_BAHRAIN_FLAG(); // Bahrain Flag
LED_COLOMBIA_FLAG(); // Colombia Flag
// DisJSON Rainbow
LED_CLEAR();
}
//======================================================
// MAIN PROGRAM LOOP
//======================================================
void loop()
{
// Reading From Bluetooth
if(Bluetooth.available())
{
// Reading Message From Bluetooth
String msg = Bluetooth.readStringUntil('\n');
msg.trim();
// DisJSON On Sertial
terminal(msg);
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
dualcomm(UNDERSTOOD);
// Reading Game Name & Settings
String game = JSON["gm"];
String settings = JSON["set"];
// Clearing JSON Buffer
JSON.clear();
// Entering To Game Selector
game_selector(game, settings);
}
else
{
terminal(JSON_ERROR);
}
Bluetooth.flush();
}
}
//======================================================
// END OF PROGRAM
//======================================================
+244
View File
@@ -0,0 +1,244 @@
#define BETWEEN_FADE 15
#define FADE_RATE 15
#define BLINK_RATE 250
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
{
for(int i=0; i<Times; i++)
{
LED_SET_COLOR(R, G, B, 255);
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
}
//------------------------------------------------------
// COLOR WHIPE
//------------------------------------------------------
// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait)
{
for(uint16_t i=0; i<NUM_PIXELS; i++)
{
pixels.setPixelColor(i, c);
pixels.show();
delay(wait);
}
}
//------------------------------------------------------
// END GAME LIGHTING SIGNAL
//------------------------------------------------------
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait)
{
uint16_t i, j;
for(j=0; j<256*5; j++)
{ // 5 cycles of all colors on WHEEL
for(i=0; i< pixels.numPixels(); i++)
{
pixels.setPixelColor(i, WHEEL(((i * 256 / pixels.numPixels()) + j) & 255));
}
pixels.show();
delay(wait);
}
}
//------------------------------------------------------
// END GAME LIGHTING SIGNAL
//------------------------------------------------------
// 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)
{
WHEELPos = 255 - WHEELPos;
if(WHEELPos < 85)
{
return pixels.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
}
if(WHEELPos < 170)
{
WHEELPos -= 85;
return pixels.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
}
WHEELPos -= 170;
return pixels.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
}
//------------------------------------------------------
// Set LED Brightness
//------------------------------------------------------
void LED_SET_BRIGHTNESS(uint8_t Value)
{
pixels.setBrightness(Value);
}
//------------------------------------------------------
// Set LED Color
//------------------------------------------------------
void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
{
// Set Intensity
LED_SET_BRIGHTNESS(Intensity);
// Loop
for(int i=0; i<NUM_PIXELS; i++)
{
pixels.setPixelColor(i, pixels.Color(R, G, B));
}
pixels.show();
}
//------------------------------------------------------
// Set Color Fade In
//------------------------------------------------------
void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
{
for(int i=0; i<=255; i++)
{
pixels.setBrightness(i);
for(int j=0; j<NUM_PIXELS; j++)
{
pixels.setPixelColor(j, pixels.Color(R, G, B));
}
pixels.show();
delay(4);
}
}
//------------------------------------------------------
// Set Color Fade Out
//------------------------------------------------------
void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
{
for(int i=255; i>=0; i--)
{
pixels.setBrightness(i);
for(int j=0; j<NUM_PIXELS; j++)
{
pixels.setPixelColor(j, pixels.Color(R, G, B));
}
pixels.show();
delay(4);
}
}
//------------------------------------------------------
// Set LED Color Cross Fade
//------------------------------------------------------
void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
{
for(int i=0; i<Times; i++) {
LED_FADEIN(R, G, B);
LED_FADEOUT(R, G, B);
delay(BETWEEN_FADE);
}
}
//------------------------------------------------------
// Clearing The LED Strip
//------------------------------------------------------
void LED_CLEAR()
{
// Clear The Strip Color
pixels.clear();
// Show The Change
pixels.show();
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void LED_SIGNAL_START()
{
// Cross Fade White Color To Get ready 3 Times
LED_CROSS_FADE(255, 255, 255, 3);
// Set Strip Color Green
LED_SET_COLOR(0, 255, 0, 255);
}
//======================================================
// REACTION GAME END SINGNAL LED SIGNAL
//======================================================
void LED_SIGNAL_END()
{
// Blink Red Twice
LED_BLINK(255, 0, 0, 2);
// Fade The Red Color To Nothing
LED_FADEOUT(255, 0, 0);
}
//======================================================
// REACTION GAME START LED CELEBRATION
//======================================================
void LED_SIGNAL_CELEBRATION()
{
// Display Rainbow Twice
rainbowCycle(2);
// Grean Light OUT
LED_FADEOUT(0, 255, 0);
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void LED_SIGNAL_RESET()
{
// Light Bright Blue
LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
delay(250);
// Fade Out The Blue
LED_SET_COLOR(0, 255, 0, 255);
// Set Strip Color Green
LED_SET_COLOR(0, 255, 0, 255);
}
//======================================================
// DISPLAY BAHRAIN FLAG
//======================================================
void LED_BAHRAIN_FLAG()
{
LED_SET_BRIGHTNESS(255);
colorWipe(pixels.Color(255, 255, 255), 30); // White
delay(250);
colorWipe(pixels.Color(255, 0, 0), 30); // Red
delay(250);
LED_FADEOUT(255, 0, 0);
}
//======================================================
// DISPLAY COLOMBIA FLAG
//======================================================
void LED_COLOMBIA_FLAG()
{
LED_SET_BRIGHTNESS(255);
colorWipe(pixels.Color(255, 255, 0), 30); // Yellow
delay(250);
colorWipe(pixels.Color(0, 0, 255), 30); // Blue
delay(250);
colorWipe(pixels.Color(255, 0, 0), 30); // Red
delay(250);
LED_FADEOUT(255, 0, 0);
}
@@ -0,0 +1,29 @@
//======================================================
// TERMINAL WINDOW - NATIVE USB
//======================================================
void terminal(String msg)
{
msg += "\n";
Terminal.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void bluetooth(String msg)
{
msg += "\n";
Bluetooth.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void dualcomm(String msg)
{
terminal(msg);
bluetooth(msg);
}
+178
View File
@@ -0,0 +1,178 @@
//======================================================
// MAIN COUNTER GAME LOOP
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : game_counter_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : game_counter_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// THIS IS THE STAND ALONE CALL FOR THE GAME
//======================================================
void game_counter_standalone()
{
// Variables Of The Game
uint16_t limit = 0;
bool limitEnable = 0;
// Play The Game
game_counter(limit, limitEnable);
}
//======================================================
// THIS IS THE BLUETOOTH CALL FOR THE GAME
//======================================================
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
* --------------------------------------
*
* FORMAT :
* --------
* {"le": false, "lm": 10}
*
* MEANNING :
* ----------
* ct : count
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* WHAT JSON TO BE COLLECTED :
* ---------------------------
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
*
* CALCULATING RESULTS :
* ---------------------
* No calculation required, Its directly the count
*/
void game_counter_bluetooth(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
// Play The Game
game_counter(limit, limitEnable);
}
//======================================================
// COUNTER JSON JSON -> To Send Back To Server
//======================================================
void game_counter(uint16_t limit, bool limitEnable)
{
// Kick Counter
uint16_t counter = 0;
// Game Start Lights
LED_SIGNAL_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// staring Of time stamp
unsigned long startStamp = millis();
while(1)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET)
{
counter = 0;
startStamp = millis();
timeStamp = startStamp;
LED_SIGNAL_RESET();
}
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebration
LED_SIGNAL_CELEBRATION();
// RESET
return;
}
// Read Impact
if(readImpact() > VTH)
{
counter++;
dualcomm(counter_JSON_json(counter, timeStamp));
delay(100);
}
}
}
//======================================================
// COUNTER JSON -> To Send Back To Mobile
//======================================================
String counter_JSON_json(unsigned int ct, unsigned int st)
{
// Convert Int To Float
float stamp = st;
stamp /= 1000;
// Assignning JSONset
JSON["ct"] = ct;
JSON["st"] = String(stamp, 3).toFloat();
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
@@ -0,0 +1,266 @@
//======================================================
// REACTION GAME MAIN ROUTINE
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : game_reaction_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : game_reaction_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// Request From Stand Alone Buttons
//======================================================
void game_reaction_standalone()
{
// Variables
uint8_t minDelay = 0;
uint8_t maxDelay = 0;
uint8_t trials = 0;
// Display Screen Menu And Button Actions
// If The Menu Number 1 -> We Set The Value Of Min Delay
// If The Menu Number 2 -> We Set The Value Of Max Delay
// If The Menu Number 3 -> We Set The Number Of Trials
// Call the Game Play
play_reaction(minDelay, maxDelay, trials);
}
//======================================================
// Request From Bluetooth Via JSON
//======================================================
/* REACTION GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tr": 10, "mn": 1, "mx": 2}
*
* MEANNING :
* ----------
* tr : trials pre counter
* mn : minimum delay, between trials
* mx : maximum delay, between trials
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tr" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
*/
void game_reaction_bluetooth(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings);
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint8_t minDelay = JSON["mn"];
uint8_t maxDelay = JSON["mx"];
uint16_t trials = JSON["lm"];
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
// Play The Game
play_reaction(minDelay, maxDelay, trials);
}
//======================================================
// Play The Game
//======================================================
void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
{
// PUBLIC VARIABLES
uint16_t temp = trials;
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// DisJSON Welcome Message
terminal("");
terminal("trials : " + String(trials) + " Strikes");
terminal("minDelay : " + String(minDelay) + " Seconds");
terminal("maxDelay : " + String(maxDelay) + " Seconds");
terminal("2 Seconds To Start Get Ready & Good Luck !!");
terminal("");
// Main Variables
uint16_t sdelay = 0;
uint16_t power = 0;
uint16_t response = 0;
unsigned long startTime = 0;
unsigned long stopTime = 0;
// Ready Signal
LED_SIGNAL_REACTION_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// Processing Results
for(int i=0; i<trials; i++)
{
// Reading Kick JSON
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
terminal(" -> Get Ready !!");
// Set Random Delay Time
sdelay = random(minDelay, maxDelay);
sdelay *= 1000;
delay(sdelay);
// Light Up Green
LED_SET_COLOR(0, 255, 0, 255);
// Start Timer
startTime = millis();
// Sensing Strike Power
while(power < VTH)
{
// Reading The Strike
power = readImpact();
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP) {
dualcomm(GAME_OVER);
// LightUp
LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET) {
LED_SIGNAL_REACTION_RESET();
trials = temp;
break;
}
}
}
// Stop Timer
stopTime = millis();
// Stop Light
LED_SET_COLOR(255, 0, 0, 255);
// Calculating Response Time
response = stopTime - startTime - 1;
// Create Json JSON
String msg = reaction_JSON_json(i+1, power, response, sdelay);
// Print To Terminal
dualcomm(msg);
// Clear All
sdelay = 0;
power = 0;
response = 0;
}
// Red Light Delay
delay(500);
// END GAME
dualcomm(GAME_OVER);
// Blink Red
LED_SIGNAL_CELEBRATION();
// Return To Game Selector
return;
}
//======================================================
// REACTION JSON -> To Send Back To Mobile Device
//======================================================
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
{
// Convert To Seconds Unit
float re = response;
re /= 1000;
// Asignning Values
JSON["ct"] = count; // Strike Number
JSON["pw"] = power; // Strike Power In Analog Read
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void LED_SIGNAL_REACTION_START()
{
// Cross fade the white signal to get ready
LED_CROSS_FADE(255, 255, 255, 3);
// Set the LED strip color to red
LED_SET_COLOR(255, 0, 0, 255);
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void LED_SIGNAL_REACTION_RESET()
{
// Light Bright Blue
LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
delay(250);
// Fade Out The Blue
LED_SET_COLOR(0, 255, 0, 255);
}
@@ -0,0 +1,37 @@
//======================================================
// MAIN PROGRAM LOOP
//======================================================
/* game selector is the main function that tell the game groutine
* which game to be JSONed and at what parameters
*/
void game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal(GM_COUNTER);
game_counter_bluetooth(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal(GM_TATTACK);
game_reaction_bluetooth(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal(GM_REACTION);
game_reaction_bluetooth(settings);
return;
}
// Unknown Game
else {
dualcomm(UNKNOWN_GAME);
return;
}
}
@@ -0,0 +1,231 @@
//======================================================
// TIME ATTACK GAME MAIN ROUTINE
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : time_attack_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : time_attack_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// Request From Stand Alone Buttons
//======================================================
void time_attack_standalone()
{
// Variables
uint16_t time = 0;
uint16_t timer = 0;
uint16_t limit = 0;
bool limitEnable = 0;
// Display Screen Menu And Button Actions
// If The Menu Number 1 -> We Set The Value Of Min Delay
// If The Menu Number 2 -> We Set The Value Of Max Delay
// If The Menu Number 3 -> We Set The Number Of Trials
// Call the Game Play
game_timeAttack(time, timer, limit, limitEnable);
}
//======================================================
// Request From Bluetooth Via JSON
//======================================================
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tm": 10, "le": false, "lm": 10}
*
* tm : count down timer starting value
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tm" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
*
* RETURNNING JSON FORMAT :
* ------------------------
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
*
* tm : timer count in Sec
* ct : strike counter (number of kicks)
* dl : delay between strikes
* st : time stampe of the strike in milli Seconds
*/
void time_attack_bluetooth(String settings)
{
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t time = JSON["tm"]; // Time Window To JSON
uint16_t timer = time;
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
// Play The Game
game_timeAttack(time, timer, limit, limitEnable);
}
//======================================================
// Play Time Atack Game
//======================================================
void game_timeAttack(uint16_t time, uint16_t timer, uint16_t limit, bool limitEnable)
{
// Building Timers 1000mSec -> 1Sec
TimeTrigger sec_tick(1000);
// Kick Counter
uint16_t counter = 0;
// Start LED Signal
LED_SIGNAL_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// Send Initial DisJSON
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
// staring Of time stamp
unsigned long startStamp = millis();
// store the time of the previous kick
unsigned long lastStamp = 0;
// reseting time ticker
sec_tick.Reset();
// While The Game Is Still On
while(timer != 0)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_SIGNAL_END();
// Return
return;
}
else if(msg == CM_RESET)
{
timer = time;
counter = 0;
startStamp = millis();
timeStamp = startStamp;
lastStamp = timeStamp;
sec_tick.Reset();
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
LED_SIGNAL_RESET();
}
}
// Every Kick ---------------------------->>>
if(readImpact() > VTH)
{
counter++;
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
lastStamp = timeStamp;
delay(100);
}
// Every Second ---------------------------->>>
if(sec_tick.Trigger())
{
timer--;
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebrate
LED_SIGNAL_CELEBRATION();
// Return
return;
}
}
// Send End Game Signal To Smart Phone
dualcomm(GAME_OVER);
// LightUp
LED_FADEIN(255, 0, 0); // RED Color
delay(2000); // Delay 2000
LED_CLEAR(); // CLEAR OFF
// Return
return;
}
//======================================================
// TIME ATTACK KICK JSON -> To Send Back To Mobile
//======================================================
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
{
// Building The Buffer
JSON["tm"] = RunningTime;
JSON["ct"] = KickCount;
// Calculations
if(TimeStamp > 0)
{
// Calculate Time Stamp In Seconds
float st = TimeStamp;
st /= 1000;
JSON["st"] = String(st, 3).toFloat();
// Calculate Strike Delay In Seconds
float dl = TimeStamp - LastStamp;
dl /= 1000;
JSON["dl"] = String(dl, 3).toFloat();
}
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
+296
View File
@@ -0,0 +1,296 @@
//======================================================
// LIBRARIES
//======================================================
// Library Include
#include <ArduinoJson.h>
#include <TimeTrigger.h>
#include <Adafruit_NeoPixel.h>
//======================================================
// HARDWARE SETUP & SELECTION
//======================================================
// Arduino MEGA
#ifdef ARDUINO_AVR_MEGA2560
//------------------------------------------------------
// Library Nessesary
#ifdef __AVR__
#include <avr/power.h>
#endif
// Serial Terminal
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
// Bluetooth Terminal
#define Bluetooth Serial1 // We will Connect The HC-05 To Hardware Serial1 In Arduino Mega
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
// JSON Object & Memory
#define CAPACITY 100
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// LED Strip
#define LED_STRIP 53 // LED STRIP PIN NUMBER
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
// Impact Detection
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
//------------------------------------------------------
// Arduino Uno / Nano
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
//------------------------------------------------------
// Library Nessesary
#ifdef __AVR__
#include <avr/power.h>
#endif
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
#include <SoftwareSerial.h>
// Serial Terminal
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
// Bluetooth Terminal
SoftwareSerial Bluetooth(10, 11); // Pin 10 RX, Pin 11 TX
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
// JSON Object & Memory
#define CAPACITY 100
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// LED Strip
#define LED_STRIP 2 // LED STRIP PIN NUMBER
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
// Impact Detection
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A4 // RANDOM NUMBER GENERATOR SOURCE
//------------------------------------------------------
// ESP32 TAKEONE BOARD
#elif ESP32
//------------------------------------------------------
/* ===============================================
* - THIS IS TAKEONE BOARD -
* ===============================================
* MPU9250 Address : 0X69 (ADDRESS)
* OLED 128x64 Address : 0X3C (ADDRESS)
* -----------------------------------------------
* Description : PIN GPIO#
* -----------------------------------------------
* NEOPIXEL LED STRIP : A0/GPIO 26
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
* LED PIN : 13 (DIGITAL)
* BATTERY MONITOR PIN : 35 (ANALOG)
*/
/* ESP32 HAVE A NATIVE BLUETOOTH MODULE
SO WE USE BLUETOOTH SERIAL LIBRARY */
#include <BluetoothSerial.h>
// Nessesary Definition For Bluetooth Library
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
// Serial Terminal
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
// Bluetooth Terminal
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
// JSON Object & Memory
#define CAPACITY 100
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// LED Strip
#define LED_STRIP 33 // LED STRIP PIN NUMBER
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
// Impact Detection
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define SENSOR_PIN 39 // IMPACT SENSOR
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Exclusive Features Of TAKEONE BOARD
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* ESP32 TAKEONE Board has some unique hardware features
* 1. Battery Voltage Level Monitoring Via Analog Pin 35
* 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery
* 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom
* 4. SPI : SDCARD Reader */
// Boost Converter
#define BOOST_PIN 14
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
#define BOOST_STU digitalRead(BOOST_PIN)
// Battery Level Monitoring
#define BATTERY_PIN 35
#define BATTERY (float)(((analogRead(BATTERY_PIN) * (3.3 / 4096)) * 2) + 0.31)
#define CHARGE round(mapf(BATTERY, 3.27, 4.31, 0, 100), 1)
// Function To Make Sure The Pin Is ON
void LED_BOOST_CHK() {
if(BOOST_STU == LOW) {
BOOST_ON;
delay(1);
}
}
// Floting Point Mapping
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
#endif
//======================================================
// PREDEFINED JSON STRINGS MESSAGES
//======================================================
// FIXED MESSAGES
#define POWERUP "{\"status\":\"POWER UP\"}"
#define UNDERSTOOD "{\"status\":\"OK\"}"
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
// GAME NAMES
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
#define GM_REACTION "{\"gm\":\"REACTION\"}"
#define GM_DECISION "{\"gm\":\"DECISION\"}"
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
// COMMAND LIST
#define CM_START "{\"cm\":\"START\"}"
#define CM_RESET "{\"cm\":\"RESET\"}"
#define CM_STOP "{\"cm\":\"STOP\"}"
#define CM_EXIT "{\"cm\":\"EXIT\"}"
//======================================================
// READING IMPACT POWER FROM ANALOG PINS
//======================================================
// READING THE IMPACT
int readImpact()
{
int value = analogRead(SENSOR_PIN);
return value;
}
//======================================================
// MAIN HARDWARE SETUP
//======================================================
void setup()
{
// Communications
Terminal.begin(9600);
// Make Sure Of The Core
#ifdef ESP32
Bluetooth.begin("KICKER"); // Bluetooth device name
BOOST_SETUP; // Boost Pin Setup
BOOST_OFF; // Turn It Off
#else
Bluetooth.begin(9600); // Bluetooth HC-05 / HC-06
#endif
// I/O
pixels.begin(); // Neo Pixel
LED_CLEAR(); // Turn Off All LED
// The Random Number Source
randomSeed(analogRead(RANDOM_SOURCE));
// POWER UP MESSGAE
dualcomm(POWERUP);
// DISPLAY COMPANY COUNTRY FLAG
LED_BAHRAIN_FLAG(); // Bahrain Flag
LED_COLOMBIA_FLAG(); // Colombia Flag
// DisJSON Rainbow
LED_CLEAR();
}
//======================================================
// MAIN PROGRAM LOOP
//======================================================
void loop()
{
// Reading From Bluetooth
if(isBluetooth)
{
// Reading Message From Bluetooth
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
// Display On Serial Monitor For Debuging
terminal(msg);
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
dualcomm(UNDERSTOOD);
// Reading Game Name & Settings
String game = JSON["gm"];
String settings = JSON["set"];
// Clearing JSON Buffer
JSON.clear();
// Entering To Game Selector
game_selector(game, settings);
}
else
{
terminal(JSON_ERROR);
}
Bluetooth.flush();
}
}
//======================================================
// END OF PROGRAM
//======================================================
+345
View File
@@ -0,0 +1,345 @@
#define BETWEEN_FADE 15
#define FADE_RATE 15
#define BLINK_RATE 250
//------------------------------------------------------
// Clearing The LED Strip
//------------------------------------------------------
void LED_CLEAR()
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Clear The Strip Color
pixels.clear();
// Make Sure Of The Core
#ifdef ESP32
delay(1);
#endif
// Show On LED Strip
LED_SHOW();
// Make Sure Of The Core
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// DISPLAY ON STRIP
//------------------------------------------------------
void LED_SHOW()
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Pass It To The LED Strip
pixels.show();
}
//------------------------------------------------------
// Set LED Brightness
//------------------------------------------------------
void LED_SET_BRIGHTNESS(uint8_t Value)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Set The Brightness
pixels.setBrightness(Value);
}
//------------------------------------------------------
// Set LED Color
//------------------------------------------------------
void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Set Intensity
LED_SET_BRIGHTNESS(Intensity);
// Loop
for(int i=0; i<NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(R, G, B));
}
// Show The Colors On LED Strip
LED_SHOW();
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
{
for(int i=0; i<Times; i++)
{
LED_SET_COLOR(R, G, B, 255);
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
}
//------------------------------------------------------
// COLOR WHIPE
//------------------------------------------------------
// Fill the dots one after the other with a color
void LED_COLOR_WIPE(uint32_t c, uint8_t wait)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Work Loop
for(uint16_t i=0; i<NUM_PIXELS; i++)
{
pixels.setPixelColor(i, c);
LED_SHOW();
delay(wait);
}
}
//------------------------------------------------------
// END GAME LIGHTING SIGNAL
//------------------------------------------------------
// Slightly different, this makes the rainbow equally distributed throughout
void LED_RAINBOW_CYCLE(uint8_t wait)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Loop Variables
uint16_t i, j;
// The Loop
for(j=0; j<256*5; j++)
{
// 5 cycles of all colors on WHEEL
for(i=0; i< pixels.numPixels(); i++)
{
pixels.setPixelColor(i, LED_COLOR_WHEEL(((i * 256 / pixels.numPixels()) + j) & 255));
}
LED_SHOW();
delay(wait);
}
}
//------------------------------------------------------
// END GAME LIGHTING SIGNAL
//------------------------------------------------------
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t LED_COLOR_WHEEL(byte WHEELPos)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Wheel Sequance
WHEELPos = 255 - WHEELPos;
if(WHEELPos < 85)
{
return pixels.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
}
if(WHEELPos < 170)
{
WHEELPos -= 85;
return pixels.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
}
WHEELPos -= 170;
return pixels.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
}
//------------------------------------------------------
// Set Color Fade In
//------------------------------------------------------
void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Loop For Fade
for(int i=0; i<=255; i++)
{
pixels.setBrightness(i);
for(int j=0; j<NUM_PIXELS; j++)
{
pixels.setPixelColor(j, pixels.Color(R, G, B));
}
LED_SHOW();
delay(4);
}
}
//------------------------------------------------------
// Set Color Fade Out
//------------------------------------------------------
void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Loop For Fade Out
for(int i=255; i>=0; i--)
{
pixels.setBrightness(i);
for(int j=0; j<NUM_PIXELS; j++)
{
pixels.setPixelColor(j, pixels.Color(R, G, B));
}
LED_SHOW();
delay(4);
}
}
//------------------------------------------------------
// Set LED Color Cross Fade
//------------------------------------------------------
void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
for(int i=0; i<Times; i++)
{
LED_FADEIN(R, G, B);
LED_FADEOUT(R, G, B);
delay(BETWEEN_FADE);
}
}
//------------------------------------------------------
// REACTION GAME START LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_START()
{
// Cross Fade White Color To Get ready 3 Times
LED_CROSS_FADE(255, 255, 255, 3);
// Set Strip Color Green
LED_SET_COLOR(0, 255, 0, 255);
}
//------------------------------------------------------
// REACTION GAME END SINGNAL LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_END()
{
// Blink Red Twice
LED_BLINK(255, 0, 0, 2);
// Fade The Red Color To Nothing
LED_FADEOUT(255, 0, 0);
}
//------------------------------------------------------
// REACTION GAME START LED CELEBRATION
//------------------------------------------------------
void LED_SIGNAL_CELEBRATION()
{
// Display Rainbow Twice
LED_RAINBOW_CYCLE(2);
// Grean Light OUT
LED_FADEOUT(0, 255, 0);
}
//------------------------------------------------------
// REACTION GAME RESET LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_RESET()
{
// Light Bright Blue
LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
delay(250);
// Fade Out The Blue
LED_SET_COLOR(0, 255, 0, 255);
// Set Strip Color Green
LED_SET_COLOR(0, 255, 0, 255);
}
//------------------------------------------------------
// DISPLAY BAHRAIN FLAG
//------------------------------------------------------
void LED_BAHRAIN_FLAG()
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
LED_SET_BRIGHTNESS(255);
LED_COLOR_WIPE(pixels.Color(255, 255, 255), 30); // White
delay(250);
LED_COLOR_WIPE(pixels.Color(255, 0, 0), 30); // Red
delay(250);
LED_FADEOUT(255, 0, 0);
}
//------------------------------------------------------
// DISPLAY COLOMBIA FLAG
//------------------------------------------------------
void LED_COLOMBIA_FLAG()
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
LED_SET_BRIGHTNESS(255);
LED_COLOR_WIPE(pixels.Color(255, 255, 0), 30); // Yellow
delay(250);
LED_COLOR_WIPE(pixels.Color(0, 0, 255), 30); // Blue
delay(250);
LED_COLOR_WIPE(pixels.Color(255, 0, 0), 30); // Red
delay(250);
LED_FADEOUT(255, 0, 0);
}
@@ -0,0 +1,29 @@
//======================================================
// TERMINAL WINDOW - NATIVE USB
//======================================================
void terminal(String msg)
{
msg += "\n";
Terminal.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void bluetooth(String msg)
{
msg += "\n";
Bluetooth.print(msg);
}
//======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//======================================================
void dualcomm(String msg)
{
terminal(msg);
bluetooth(msg);
}
@@ -0,0 +1,178 @@
//======================================================
// MAIN COUNTER GAME LOOP
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : game_counter_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : game_counter_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// THIS IS THE STAND ALONE CALL FOR THE GAME
//======================================================
void game_counter_standalone()
{
// Variables Of The Game
uint16_t limit = 0;
bool limitEnable = 0;
// Play The Game
game_counter(limit, limitEnable);
}
//======================================================
// THIS IS THE BLUETOOTH CALL FOR THE GAME
//======================================================
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
* --------------------------------------
*
* FORMAT :
* --------
* {"le": false, "lm": 10}
*
* MEANNING :
* ----------
* ct : count
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* WHAT JSON TO BE COLLECTED :
* ---------------------------
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
*
* CALCULATING RESULTS :
* ---------------------
* No calculation required, Its directly the count
*/
void game_counter_bluetooth(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
// Play The Game
game_counter(limit, limitEnable);
}
//======================================================
// COUNTER JSON JSON -> To Send Back To Server
//======================================================
void game_counter(uint16_t limit, bool limitEnable)
{
// Kick Counter
uint16_t counter = 0;
// Game Start Lights
LED_SIGNAL_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// staring Of time stamp
unsigned long startStamp = millis();
while(1)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET)
{
counter = 0;
startStamp = millis();
timeStamp = startStamp;
LED_SIGNAL_RESET();
}
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebration
LED_SIGNAL_CELEBRATION();
// RESET
return;
}
// Read Impact
if(readImpact() > VTH)
{
counter++;
dualcomm(counter_JSON_json(counter, timeStamp));
delay(100);
}
}
}
//======================================================
// COUNTER JSON -> To Send Back To Mobile
//======================================================
String counter_JSON_json(unsigned int ct, unsigned int st)
{
// Convert Int To Float
float stamp = st;
stamp /= 1000;
// Assignning JSONset
JSON["ct"] = ct;
JSON["st"] = String(stamp, 3).toFloat();
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
@@ -0,0 +1,266 @@
//======================================================
// REACTION GAME MAIN ROUTINE
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : game_reaction_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : game_reaction_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// Request From Stand Alone Buttons
//======================================================
void game_reaction_standalone()
{
// Variables
uint8_t minDelay = 0;
uint8_t maxDelay = 0;
uint8_t trials = 0;
// Display Screen Menu And Button Actions
// If The Menu Number 1 -> We Set The Value Of Min Delay
// If The Menu Number 2 -> We Set The Value Of Max Delay
// If The Menu Number 3 -> We Set The Number Of Trials
// Call the Game Play
play_reaction(minDelay, maxDelay, trials);
}
//======================================================
// Request From Bluetooth Via JSON
//======================================================
/* REACTION GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tr": 10, "mn": 1, "mx": 2}
*
* MEANNING :
* ----------
* tr : trials pre counter
* mn : minimum delay, between trials
* mx : maximum delay, between trials
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tr" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
*/
void game_reaction_bluetooth(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings);
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint8_t minDelay = JSON["mn"];
uint8_t maxDelay = JSON["mx"];
uint16_t trials = JSON["lm"];
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
// Play The Game
play_reaction(minDelay, maxDelay, trials);
}
//======================================================
// Play The Game
//======================================================
void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
{
// PUBLIC VARIABLES
uint16_t temp = trials;
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// DisJSON Welcome Message
terminal("");
terminal("trials : " + String(trials) + " Strikes");
terminal("minDelay : " + String(minDelay) + " Seconds");
terminal("maxDelay : " + String(maxDelay) + " Seconds");
terminal("2 Seconds To Start Get Ready & Good Luck !!");
terminal("");
// Main Variables
uint16_t sdelay = 0;
uint16_t power = 0;
uint16_t response = 0;
unsigned long startTime = 0;
unsigned long stopTime = 0;
// Ready Signal
LED_SIGNAL_REACTION_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// Processing Results
for(int i=0; i<trials; i++)
{
// Reading Kick JSON
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
terminal(" -> Get Ready !!");
// Set Random Delay Time
sdelay = random(minDelay, maxDelay);
sdelay *= 1000;
delay(sdelay);
// Light Up Green
LED_SET_COLOR(0, 255, 0, 255);
// Start Timer
startTime = millis();
// Sensing Strike Power
while(power < VTH)
{
// Reading The Strike
power = readImpact();
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP) {
dualcomm(GAME_OVER);
// LightUp
LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET) {
LED_SIGNAL_REACTION_RESET();
trials = temp;
break;
}
}
}
// Stop Timer
stopTime = millis();
// Stop Light
LED_SET_COLOR(255, 0, 0, 255);
// Calculating Response Time
response = stopTime - startTime - 1;
// Create Json JSON
String msg = reaction_JSON_json(i+1, power, response, sdelay);
// Print To Terminal
dualcomm(msg);
// Clear All
sdelay = 0;
power = 0;
response = 0;
}
// Red Light Delay
delay(500);
// END GAME
dualcomm(GAME_OVER);
// Blink Red
LED_SIGNAL_CELEBRATION();
// Return To Game Selector
return;
}
//======================================================
// REACTION JSON -> To Send Back To Mobile Device
//======================================================
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
{
// Convert To Seconds Unit
float re = response;
re /= 1000;
// Asignning Values
JSON["ct"] = count; // Strike Number
JSON["pw"] = power; // Strike Power In Analog Read
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
//======================================================
// REACTION GAME START LED SIGNAL
//======================================================
void LED_SIGNAL_REACTION_START()
{
// Cross fade the white signal to get ready
LED_CROSS_FADE(255, 255, 255, 3);
// Set the LED strip color to red
LED_SET_COLOR(255, 0, 0, 255);
}
//======================================================
// REACTION GAME RESET LED SIGNAL
//======================================================
void LED_SIGNAL_REACTION_RESET()
{
// Light Bright Blue
LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
delay(250);
// Fade Out The Blue
LED_SET_COLOR(0, 255, 0, 255);
}
@@ -0,0 +1,37 @@
//======================================================
// MAIN PROGRAM LOOP
//======================================================
/* game selector is the main function that tell the game groutine
* which game to be JSONed and at what parameters
*/
void game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal(GM_COUNTER);
game_counter_bluetooth(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal(GM_TATTACK);
game_reaction_bluetooth(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal(GM_REACTION);
game_reaction_bluetooth(settings);
return;
}
// Unknown Game
else {
dualcomm(UNKNOWN_GAME);
return;
}
}
@@ -0,0 +1,231 @@
//======================================================
// TIME ATTACK GAME MAIN ROUTINE
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : time_attack_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : time_attack_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// Request From Stand Alone Buttons
//======================================================
void time_attack_standalone()
{
// Variables
uint16_t time = 0;
uint16_t timer = 0;
uint16_t limit = 0;
bool limitEnable = 0;
// Display Screen Menu And Button Actions
// If The Menu Number 1 -> We Set The Value Of Min Delay
// If The Menu Number 2 -> We Set The Value Of Max Delay
// If The Menu Number 3 -> We Set The Number Of Trials
// Call the Game Play
game_timeAttack(time, timer, limit, limitEnable);
}
//======================================================
// Request From Bluetooth Via JSON
//======================================================
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tm": 10, "le": false, "lm": 10}
*
* tm : count down timer starting value
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tm" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
*
* RETURNNING JSON FORMAT :
* ------------------------
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
*
* tm : timer count in Sec
* ct : strike counter (number of kicks)
* dl : delay between strikes
* st : time stampe of the strike in milli Seconds
*/
void time_attack_bluetooth(String settings)
{
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t time = JSON["tm"]; // Time Window To JSON
uint16_t timer = time;
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
// Play The Game
game_timeAttack(time, timer, limit, limitEnable);
}
//======================================================
// Play Time Atack Game
//======================================================
void game_timeAttack(uint16_t time, uint16_t timer, uint16_t limit, bool limitEnable)
{
// Building Timers 1000mSec -> 1Sec
TimeTrigger sec_tick(1000);
// Kick Counter
uint16_t counter = 0;
// Start LED Signal
LED_SIGNAL_START();
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// Send Initial DisJSON
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
// staring Of time stamp
unsigned long startStamp = millis();
// store the time of the previous kick
unsigned long lastStamp = 0;
// reseting time ticker
sec_tick.Reset();
// While The Game Is Still On
while(timer != 0)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
LED_SIGNAL_END();
// Return
return;
}
else if(msg == CM_RESET)
{
timer = time;
counter = 0;
startStamp = millis();
timeStamp = startStamp;
lastStamp = timeStamp;
sec_tick.Reset();
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
LED_SIGNAL_RESET();
}
}
// Every Kick ---------------------------->>>
if(readImpact() > VTH)
{
counter++;
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
lastStamp = timeStamp;
delay(100);
}
// Every Second ---------------------------->>>
if(sec_tick.Trigger())
{
timer--;
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// END GAME
dualcomm(GAME_OVER);
// Celebrate
LED_SIGNAL_CELEBRATION();
// Return
return;
}
}
// Send End Game Signal To Smart Phone
dualcomm(GAME_OVER);
// LightUp
LED_FADEIN(255, 0, 0); // RED Color
delay(2000); // Delay 2000
LED_CLEAR(); // CLEAR OFF
// Return
return;
}
//======================================================
// TIME ATTACK KICK JSON -> To Send Back To Mobile
//======================================================
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
{
// Building The Buffer
JSON["tm"] = RunningTime;
JSON["ct"] = KickCount;
// Calculations
if(TimeStamp > 0)
{
// Calculate Time Stamp In Seconds
float st = TimeStamp;
st /= 1000;
JSON["st"] = String(st, 3).toFloat();
// Calculate Strike Delay In Seconds
float dl = TimeStamp - LastStamp;
dl /= 1000;
JSON["dl"] = String(dl, 3).toFloat();
}
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
@@ -0,0 +1,326 @@
//======================================================
// LIBRARIES
//======================================================
// Library Include
#include <Button.h>
#include <ArduinoJson.h>
#include <TimeTrigger.h>
#include <Adafruit_NeoPixel.h>
//======================================================
// HARDWARE SETUP & SELECTION
//======================================================
// Arduino MEGA
#ifdef ARDUINO_AVR_MEGA2560
//------------------------------------------------------
// Library Nessesary
#ifdef __AVR__
#include <avr/power.h>
#endif
// Buttons Definitions
Button btn_prv(15); // TOP LEFT BUTTON
Button btn_nxt(12); // TOP RIGHT BUTTON
Button btn_sel(33); // CENTER BUTTON
Button btn_inc(32); // BOTTOM LEFT
Button btn_dec(27); // BOTTOM RIGHT
// Serial Terminal
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
// Bluetooth Terminal
#define Bluetooth Serial1 // We will Connect The HC-05 To Hardware Serial1 In Arduino Mega
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
// JSON Object & Memory
#define CAPACITY 100
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// LED Strip
#define LED_STRIP 53 // LED STRIP PIN NUMBER
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
// Impact Detection
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
//------------------------------------------------------
// Arduino Uno / Nano
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
//------------------------------------------------------
// Library Nessesary
#ifdef __AVR__
#include <avr/power.h>
#endif
// Buttons Definitions
Button btn_prv(15); // TOP LEFT BUTTON
Button btn_nxt(12); // TOP RIGHT BUTTON
Button btn_sel(33); // CENTER BUTTON
Button btn_inc(32); // BOTTOM LEFT
Button btn_dec(27); // BOTTOM RIGHT
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
#include <SoftwareSerial.h>
// Serial Terminal
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
// Bluetooth Terminal
SoftwareSerial Bluetooth(10, 11); // Pin 10 RX, Pin 11 TX
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
// JSON Object & Memory
#define CAPACITY 100
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// LED Strip
#define LED_STRIP 2 // LED STRIP PIN NUMBER
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
// Impact Detection
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A4 // RANDOM NUMBER GENERATOR SOURCE
//------------------------------------------------------
// ESP32 TAKEONE BOARD
#elif ESP32
//------------------------------------------------------
/* ===============================================
* - THIS IS TAKEONE BOARD -
* ===============================================
* MPU9250 Address : 0X69 (ADDRESS)
* OLED 128x64 Address : 0X3C (ADDRESS)
* -----------------------------------------------
* Description : PIN GPIO#
* -----------------------------------------------
* NEOPIXEL LED STRIP : A0/GPIO 26
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
* LED PIN : 13 (DIGITAL)
* BATTERY MONITOR PIN : 35 (ANALOG)
*/
/* ESP32 HAVE A NATIVE BLUETOOTH MODULE
SO WE USE BLUETOOTH SERIAL LIBRARY */
#include <BluetoothSerial.h>
// Nessesary Definition For Bluetooth Library
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
// Buttons Definitions
Button btn_prv(15); // TOP LEFT BUTTON
Button btn_nxt(12); // TOP RIGHT BUTTON
Button btn_sel(33); // CENTER BUTTON
Button btn_inc(32); // BOTTOM LEFT
Button btn_dec(27); // BOTTOM RIGHT
// Serial Terminal
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
// Bluetooth Terminal
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
// JSON Object & Memory
#define CAPACITY 100
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// LED Strip
#define LED_STRIP 26 // LED STRIP PIN NUMBER
#define NUM_PIXELS 22 // NUMBER OF LED'S IN NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
// Impact Detection
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define SENSOR_PIN 39 // IMPACT SENSOR
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Exclusive Features Of TAKEONE BOARD
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/* ESP32 TAKEONE Board has some unique hardware features
* 1. Battery Voltage Level Monitoring Via Analog Pin 35
* 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery
* 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom
* 4. SPI : SDCARD Reader */
// Boost Converter
#define BOOST_PIN 14
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
#define BOOST_STU digitalRead(BOOST_PIN)
// Battery Level Monitoring
#define BATTERY_PIN 35
#define BATTERY (float)(((analogRead(BATTERY_PIN) * (3.3 / 4096)) * 2) + 0.31)
#define CHARGE round(mapf(BATTERY, 3.27, 4.31, 0, 100), 1)
// Function To Make Sure The Pin Is ON
void LED_BOOST_CHK() {
if(BOOST_STU == LOW) {
BOOST_ON;
//delay(1);
}
}
// Floting Point Mapping
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
#endif
//======================================================
// PREDEFINED JSON STRINGS MESSAGES
//======================================================
// FIXED MESSAGES
#define POWERUP "{\"status\":\"POWER UP\"}"
#define UNDERSTOOD "{\"status\":\"OK\"}"
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
// GAME NAMES
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
#define GM_REACTION "{\"gm\":\"REACTION\"}"
#define GM_DECISION "{\"gm\":\"DECISION\"}"
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
// COMMAND LIST
#define CM_START "{\"cm\":\"START\"}"
#define CM_RESET "{\"cm\":\"RESET\"}"
#define CM_STOP "{\"cm\":\"STOP\"}"
#define CM_EXIT "{\"cm\":\"EXIT\"}"
//======================================================
// READING IMPACT POWER FROM ANALOG PINS
//======================================================
// READING THE IMPACT
int readImpact()
{
int value = analogRead(SENSOR_PIN);
return value;
}
//======================================================
// MAIN HARDWARE SETUP
//======================================================
void setup()
{
// Communications
Terminal.begin(9600);
Terminal.println();
// Begin Buttons
btn_prv.begin();
btn_nxt.begin();
btn_sel.begin();
btn_inc.begin();
btn_dec.begin();
// Make Sure Of The Core
#ifdef ESP32
Bluetooth.begin("KICKER"); // Bluetooth device name
BOOST_SETUP; // Boost Pin Setup
BOOST_OFF; // Turn It Off
#else
Bluetooth.begin(9600); // Bluetooth HC-05 / HC-06
#endif
// I/O
pixels.begin(); // Neo Pixel
LED_CLEAR(); // Turn Off All LED
// The Random Number Source
randomSeed(analogRead(RANDOM_SOURCE));
// POWER UP MESSGAE
dualcomm(POWERUP);
// DISPLAY COMPANY COUNTRY FLAG
LED_BAHRAIN_FLAG(); // Bahrain Flag
LED_COLOMBIA_FLAG(); // Colombia Flag
// DisJSON Rainbow
LED_CLEAR();
}
//======================================================
// MAIN PROGRAM LOOP
//======================================================
void loop()
{
// Reading From Bluetooth
if(isBluetooth)
{
// Reading Message From Bluetooth
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
// Display On Serial Monitor For Debuging
terminal(msg);
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
dualcomm(UNDERSTOOD);
// Reading Game Name & Settings
String game = JSON["gm"];
String settings = JSON["set"];
// Clearing JSON Buffer
JSON.clear();
// Entering To Game Selector
game_selector(game, settings);
}
else
{
terminal(JSON_ERROR);
}
Bluetooth.flush();
}
}
//======================================================
// END OF PROGRAM
//======================================================
+341
View File
@@ -0,0 +1,341 @@
#define BETWEEN_FADE 15
#define FADE_RATE 15
#define BLINK_RATE 250
//------------------------------------------------------
// Clearing The LED Strip
//------------------------------------------------------
void LED_CLEAR()
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Clear The Strip Color
pixels.clear();
// Show On LED Strip
LED_SHOW();
// Make Sure Of The Core
#ifdef ESP32
BOOST_OFF;
#endif
}
//------------------------------------------------------
// DISPLAY ON STRIP
//------------------------------------------------------
void LED_SHOW()
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
delay(1);
#endif
// Pass It To The LED Strip
pixels.show();
}
//------------------------------------------------------
// Set LED Brightness
//------------------------------------------------------
void LED_SET_BRIGHTNESS(uint8_t Value)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Set The Brightness
pixels.setBrightness(Value);
}
//------------------------------------------------------
// Set LED Color
//------------------------------------------------------
void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Set Intensity
LED_SET_BRIGHTNESS(Intensity);
// Loop
for(int i=0; i<NUM_PIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(R, G, B));
}
// Show The Colors On LED Strip
LED_SHOW();
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
{
for(int i=0; i<Times; i++)
{
LED_SET_COLOR(R, G, B, 255);
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
}
//------------------------------------------------------
// COLOR WHIPE
//------------------------------------------------------
// Fill the dots one after the other with a color
void LED_COLOR_WIPE(uint32_t c, uint8_t wait)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Work Loop
for(uint16_t i=0; i<NUM_PIXELS; i++)
{
pixels.setPixelColor(i, c);
LED_SHOW();
delay(wait);
}
}
//------------------------------------------------------
// END GAME LIGHTING SIGNAL
//------------------------------------------------------
// Slightly different, this makes the rainbow equally distributed throughout
void LED_RAINBOW_CYCLE(uint8_t wait)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Loop Variables
uint16_t i, j;
// The Loop
for(j=0; j<256*5; j++)
{
// 5 cycles of all colors on WHEEL
for(i=0; i< pixels.numPixels(); i++)
{
pixels.setPixelColor(i, LED_COLOR_WHEEL(((i * 256 / pixels.numPixels()) + j) & 255));
}
LED_SHOW();
delay(wait);
}
}
//------------------------------------------------------
// END GAME LIGHTING SIGNAL
//------------------------------------------------------
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t LED_COLOR_WHEEL(byte WHEELPos)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Wheel Sequance
WHEELPos = 255 - WHEELPos;
if(WHEELPos < 85)
{
return pixels.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
}
if(WHEELPos < 170)
{
WHEELPos -= 85;
return pixels.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
}
WHEELPos -= 170;
return pixels.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
}
//------------------------------------------------------
// Set Color Fade In
//------------------------------------------------------
void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Loop For Fade
for(int i=0; i<=255; i++)
{
pixels.setBrightness(i);
for(int j=0; j<NUM_PIXELS; j++)
{
pixels.setPixelColor(j, pixels.Color(R, G, B));
}
LED_SHOW();
delay(4);
}
}
//------------------------------------------------------
// Set Color Fade Out
//------------------------------------------------------
void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
// Loop For Fade Out
for(int i=255; i>=0; i--)
{
pixels.setBrightness(i);
for(int j=0; j<NUM_PIXELS; j++)
{
pixels.setPixelColor(j, pixels.Color(R, G, B));
}
LED_SHOW();
delay(4);
}
}
//------------------------------------------------------
// Set LED Color Cross Fade
//------------------------------------------------------
void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
for(int i=0; i<Times; i++)
{
LED_FADEIN(R, G, B);
LED_FADEOUT(R, G, B);
delay(BETWEEN_FADE);
}
}
//------------------------------------------------------
// REACTION GAME START LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_START()
{
// Cross Fade White Color To Get ready 3 Times
LED_CROSS_FADE(255, 255, 255, 3);
// Set Strip Color Green
LED_SET_COLOR(0, 255, 0, 255);
}
//------------------------------------------------------
// REACTION GAME END SINGNAL LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_END()
{
// Blink Red Twice
LED_BLINK(255, 0, 0, 2);
// Fade The Red Color To Nothing
LED_FADEOUT(255, 0, 0);
}
//------------------------------------------------------
// REACTION GAME START LED CELEBRATION
//------------------------------------------------------
void LED_SIGNAL_CELEBRATION()
{
// Display Rainbow Twice
LED_RAINBOW_CYCLE(2);
// Grean Light OUT
LED_FADEOUT(0, 255, 0);
}
//------------------------------------------------------
// REACTION GAME RESET LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_RESET()
{
// Light Bright Blue
LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
delay(250);
// Fade Out The Blue
LED_SET_COLOR(0, 255, 0, 255);
// Set Strip Color Green
LED_SET_COLOR(0, 255, 0, 255);
}
//------------------------------------------------------
// DISPLAY BAHRAIN FLAG
//------------------------------------------------------
void LED_BAHRAIN_FLAG()
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
LED_SET_BRIGHTNESS(255);
LED_COLOR_WIPE(pixels.Color(255, 255, 255), 30); // White
delay(250);
LED_COLOR_WIPE(pixels.Color(255, 0, 0), 30); // Red
delay(250);
LED_FADEOUT(255, 0, 0);
}
//------------------------------------------------------
// DISPLAY COLOMBIA FLAG
//------------------------------------------------------
void LED_COLOMBIA_FLAG()
{
// Make Sure Of The Core
#ifdef ESP32
LED_BOOST_CHK();
#endif
LED_SET_BRIGHTNESS(255);
LED_COLOR_WIPE(pixels.Color(255, 255, 0), 30); // Yellow
delay(250);
LED_COLOR_WIPE(pixels.Color(0, 0, 255), 30); // Blue
delay(250);
LED_COLOR_WIPE(pixels.Color(255, 0, 0), 30); // Red
delay(250);
LED_FADEOUT(255, 0, 0);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Loaded 100 of 176 files, more files were not shown because too many files have changed in this diff. Show more