Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8cdf95aec1 | |||
| b780cedae8 | |||
| 7eac4601f4 | |||
| 3c3f3a4657 | |||
| 2b6c2c59a9 | |||
| 223c49a21e | |||
| 138c5d91bc | |||
| ecbffd73dd | |||
| 6b0cd678c1 | |||
| b0086daea5 | |||
| 417b22e36e | |||
| 1302316362 | |||
| 29fe2f705c | |||
| 8fb3b3e0d2 | |||
| 84539fecfc | |||
| 46e0d169bc | |||
| 2b03e0641f | |||
| b67efc6d13 | |||
| 8b960ab1e4 | |||
| e63980f6b4 | |||
| 2a088af286 | |||
| 38794e59d8 | |||
| a4ec6f14f6 | |||
| 5b1fee6857 | |||
| 9f86415b9a | |||
| 33d6f41787 |
BIN
3D Model/Thumbs.db
Normal file
BIN
Datasheets/TXS0102.pdf
Normal file
BIN
Documents/MATERIALS PRICING LIST.xlsx
Normal file
BIN
Documents/Presentation.pptx
Normal file
BIN
Documents/pcba quotation.pdf
Normal file
@ -1,40 +0,0 @@
|
||||
//======================================================
|
||||
// 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(STAND_ALONE_MODE);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------
|
||||
// TERMINAL & BLUETOOTH WINDOW - NATIVE
|
||||
//------------------------------------------------------
|
||||
void dualcomm(String msg)
|
||||
{
|
||||
terminal(msg);
|
||||
bluetooth(msg);
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
//======================================================
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,264 +0,0 @@
|
||||
//======================================================
|
||||
// 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 = 10;
|
||||
bool limitEnable = true;
|
||||
|
||||
// Play The Game
|
||||
game_counter(limit, limitEnable);
|
||||
|
||||
// Give Permision To Change Display
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
//======================================================
|
||||
// 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);
|
||||
|
||||
// Give Permision To Change Display
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
//======================================================
|
||||
// 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();
|
||||
|
||||
// Display On OLED
|
||||
GAME_COUNTER_DISPLAY(0, limit);
|
||||
|
||||
//-------------------------
|
||||
// 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 Reset To Zero
|
||||
counter = 0;
|
||||
|
||||
// Starting Stamp From Now
|
||||
startStamp = millis();
|
||||
|
||||
// Time Stamp Is Now
|
||||
timeStamp = startStamp;
|
||||
|
||||
// LED STRIP LED STRIP RESET SIGNAL
|
||||
//LED_SIGNAL_RESET();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset The Counter
|
||||
if(BTN_INCREASE.pressed()) {
|
||||
counter = 0;
|
||||
startStamp = millis();
|
||||
timeStamp = startStamp;
|
||||
GAME_COUNTER_DISPLAY(counter, limit);
|
||||
}
|
||||
|
||||
// Will Exit The Game
|
||||
if(BTN_CENTER.pressed()) {
|
||||
// Send Game Over JSON Signal
|
||||
dualcomm(GAME_OVER);
|
||||
|
||||
// Give Permition To Change OLED
|
||||
DISPLAY_CHANGED = false;
|
||||
|
||||
// Return To Main Menu
|
||||
return;
|
||||
}
|
||||
|
||||
// If Limits Are Enabled And Meet
|
||||
if(limitEnable == true && counter == limit) {
|
||||
// END GAME
|
||||
dualcomm(GAME_OVER);
|
||||
|
||||
// Celebration
|
||||
//LED_SIGNAL_CELEBRATION();
|
||||
|
||||
// Display On OLED
|
||||
GAME_RESULT_DISPLAY(counter, limit);
|
||||
|
||||
// RESET
|
||||
return;
|
||||
}
|
||||
|
||||
// Read Impact
|
||||
if(PIEZO_MAP >= VTH)
|
||||
{
|
||||
counter++;
|
||||
GAME_COUNTER_DISPLAY(counter, limit);
|
||||
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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// OLED - GAME COUNTER PLAY
|
||||
//------------------------------------------------------
|
||||
|
||||
void GAME_COUNTER_DISPLAY(uint16_t count, uint16_t limit)
|
||||
{
|
||||
OLED_CLEAR();
|
||||
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||
drawTextCenter(128/2, 20, 3, String(count) + "/" + String(limit));
|
||||
|
||||
// Exit Button Command Only Via Stand Alone Mode
|
||||
if(BLUETOOTH_STATUS == false) {
|
||||
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||
}
|
||||
|
||||
OLED_SHOW();
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// OLED - GAME COUNTER RESULT
|
||||
//------------------------------------------------------
|
||||
|
||||
void GAME_RESULT_DISPLAY(uint16_t count, uint16_t limit)
|
||||
{
|
||||
OLED_CLEAR();
|
||||
drawTextCenter(128/2, 0, 2, "FINISHED");
|
||||
drawTextCenter(128/2, 20, 3, String(count) + "/" + String(limit));
|
||||
|
||||
// Exit Button Command Only Via Stand Alone Mode
|
||||
if(BLUETOOTH_STATUS == false) {
|
||||
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||
}
|
||||
|
||||
// Show Data On OLED
|
||||
OLED_SHOW();
|
||||
|
||||
// Waiting For Center Button To Move On
|
||||
while(1){
|
||||
if(BTN_CENTER.pressed()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,346 +0,0 @@
|
||||
//======================================================
|
||||
// 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 = 1;
|
||||
uint8_t maxDelay = 3;
|
||||
uint8_t trials = 10;
|
||||
|
||||
// Call the Game Play
|
||||
play_reaction(minDelay, maxDelay, trials);
|
||||
|
||||
// Give Permision To Change Display
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// 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);
|
||||
|
||||
// Give Permision To Change Display
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// Play The Game
|
||||
//------------------------------------------------------
|
||||
|
||||
void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
|
||||
{
|
||||
// PUBLIC VARIABLES
|
||||
double totalRes = 0.0;
|
||||
|
||||
// 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();
|
||||
|
||||
// Display On OLED
|
||||
GAME_REACTION_DISPLAY(0, 0);
|
||||
|
||||
//-------------------------
|
||||
// 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();
|
||||
i = 0;
|
||||
sdelay = 0;
|
||||
power = 0;
|
||||
response = 0;
|
||||
startTime = millis();
|
||||
stopTime = millis();
|
||||
totalRes = 0;
|
||||
DISPLAY_CHANGED = false;
|
||||
GAME_REACTION_DISPLAY(i, response);
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset The Counter
|
||||
if(BTN_INCREASE.pressed()) {
|
||||
//LED_SIGNAL_REACTION_RESET();
|
||||
i = 0;
|
||||
sdelay = 0;
|
||||
power = 0;
|
||||
response = 0;
|
||||
startTime = millis();
|
||||
stopTime = millis();
|
||||
totalRes = 0;
|
||||
DISPLAY_CHANGED = false;
|
||||
GAME_REACTION_DISPLAY(i, response);
|
||||
}
|
||||
|
||||
// Will Exit The Game
|
||||
if(BTN_CENTER.pressed()) {
|
||||
dualcomm(GAME_OVER);
|
||||
DISPLAY_CHANGED = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop Timer
|
||||
stopTime = millis();
|
||||
|
||||
// Stop Light
|
||||
//LED_SET_COLOR(255, 0, 0, 255);
|
||||
|
||||
// Calculating Response Time
|
||||
response = stopTime - startTime - 1;
|
||||
totalRes = totalRes + ((float)response/1000);
|
||||
|
||||
// Create Json JSON
|
||||
String msg = reaction_JSON_json(i+1, power, response, sdelay);
|
||||
|
||||
// Display On OLED
|
||||
GAME_REACTION_DISPLAY(i+1, response);
|
||||
|
||||
// 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();
|
||||
|
||||
// Display Result
|
||||
GAME_REACTION_RESULT(trials, totalRes);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// OLED GAME PLAY REACTION
|
||||
//------------------------------------------------------
|
||||
|
||||
void GAME_REACTION_DISPLAY(uint16_t count, float reatime)
|
||||
{
|
||||
OLED_CLEAR();
|
||||
drawTextCenter(128/2, 0, 2, "KICK : " + String(count));
|
||||
drawTextCenter(128/2, 20, 3, "TIME : " + String(((float)reatime/1000), 2));
|
||||
|
||||
// Exit Button Command Only Via Stand Alone Mode
|
||||
if(BLUETOOTH_STATUS == false) {
|
||||
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||
}
|
||||
|
||||
OLED_SHOW();
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// OLED - GAME TIMEATTACK RESULT
|
||||
//------------------------------------------------------
|
||||
|
||||
void GAME_REACTION_RESULT(uint16_t trials, uint16_t total_reaction)
|
||||
{
|
||||
OLED_CLEAR();
|
||||
float avgReaction = 0.0;
|
||||
avgReaction = (float)total_reaction/trials;
|
||||
drawTextCenter(128/2, 0, 2, "RESULT");
|
||||
drawTextCenter(128/2, 20, 2, String(avgReaction, 3) + " s");
|
||||
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||
OLED_SHOW();
|
||||
|
||||
// Waiting For Center Button To Move On
|
||||
while(1){
|
||||
if(BTN_CENTER.pressed()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
//======================================================
|
||||
// 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, "GAME #" + String(Number));
|
||||
drawTextCenter(128/2, 22, 2, " - " + Title + " - ");
|
||||
drawTextCenter(128/2, 43, 1, "<< SELECT >>");
|
||||
OLED_SHOW();
|
||||
DISPLAY_CHANGED = true;
|
||||
}
|
||||
@ -1,316 +0,0 @@
|
||||
//======================================================
|
||||
// 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 = 30;
|
||||
uint16_t limit = 10;
|
||||
bool limitEnable = true;
|
||||
|
||||
// Call the Game Play
|
||||
game_timeAttack(time, limit, limitEnable);
|
||||
|
||||
// Give Permision To Change Display
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
//======================================================
|
||||
// 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
|
||||
const uint16_t time = JSON["tm"]; // Time Window To JSON
|
||||
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, limit, limitEnable);
|
||||
|
||||
// Give Permision To Change Display
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
//======================================================
|
||||
// Play Time Atack Game
|
||||
//======================================================
|
||||
|
||||
void game_timeAttack(uint16_t time, uint16_t limit, bool limitEnable)
|
||||
{
|
||||
// Building Timers 1000mSec -> 1Sec
|
||||
TimeTrigger sec_tick(1000);
|
||||
|
||||
// Kick Counter
|
||||
uint16_t counter = 0; // This is what counts your kicks
|
||||
uint16_t timer = time; // This is what your running timer
|
||||
|
||||
// Start LED Signal
|
||||
//LED_SIGNAL_START();
|
||||
|
||||
// Initial Display Of Game Data Before Start
|
||||
GAME_TIMEATTACK_DISPLAY(timer, 0);
|
||||
|
||||
// Send Initial DisJSON
|
||||
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||
|
||||
//-------------------------
|
||||
// PREPARE FOR GAME START
|
||||
//-------------------------
|
||||
|
||||
// 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();
|
||||
GAME_TIMEATTACK_DISPLAY(counter, timer);
|
||||
//LED_SIGNAL_RESET();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset The Counter
|
||||
if(BTN_INCREASE.pressed()) {
|
||||
timer = time;
|
||||
counter = 0;
|
||||
startStamp = millis();
|
||||
timeStamp = startStamp;
|
||||
lastStamp = timeStamp;
|
||||
sec_tick.Reset();
|
||||
GAME_TIMEATTACK_DISPLAY(counter, timer);
|
||||
}
|
||||
|
||||
// Will Exit The Game
|
||||
if(BTN_CENTER.pressed()) {
|
||||
dualcomm(GAME_OVER);
|
||||
DISPLAY_CHANGED = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Every Kick ---------------------------->>>
|
||||
if(PIEZO_MAP > VTH)
|
||||
{
|
||||
// Count As A Strike
|
||||
counter++;
|
||||
|
||||
// Display On OLED
|
||||
GAME_TIMEATTACK_DISPLAY(counter, timer);
|
||||
|
||||
// Send JSON String Out
|
||||
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||
|
||||
// Time Snap Shot
|
||||
lastStamp = timeStamp;
|
||||
|
||||
// Wait For Analog Sampler To by pass the strike
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// Every Second ---------------------------->>>
|
||||
if(sec_tick.Trigger())
|
||||
{
|
||||
// Decrement Time After Every Second
|
||||
timer--;
|
||||
|
||||
// Display Time And Count Every Second
|
||||
GAME_TIMEATTACK_DISPLAY(counter, timer);
|
||||
|
||||
// Send JSON String Out
|
||||
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||
}
|
||||
|
||||
// If Limits Are Enabled And Meet
|
||||
if(limitEnable == true && counter == limit)
|
||||
{
|
||||
// END GAME
|
||||
dualcomm(GAME_OVER);
|
||||
|
||||
// Time Difference Between Start & Count Down Timer
|
||||
const uint16_t diff = time - timer;
|
||||
|
||||
// Display The Game Result
|
||||
GAME_TIMEATTACK_RESULT(counter, diff);
|
||||
|
||||
// Celebrate
|
||||
//LED_SIGNAL_CELEBRATION();
|
||||
|
||||
// Return
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Send End Game Signal To Smart Phone
|
||||
dualcomm(GAME_OVER);
|
||||
|
||||
// Display The Result
|
||||
GAME_TIMEATTACK_RESULT(counter, time);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// OLED - GAME TIMEATTACK PLAY
|
||||
//------------------------------------------------------
|
||||
|
||||
void GAME_TIMEATTACK_DISPLAY(uint16_t count, uint16_t time)
|
||||
{
|
||||
OLED_CLEAR();
|
||||
drawTextCenter(128/2, 0, 2, "TIME ( " + String(time) + " ) Sec");
|
||||
drawTextCenter(128/2, 20, 2, "KICKS ( " + String(count) + " )");
|
||||
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||
OLED_SHOW();
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// OLED - GAME TIMEATTACK RESULT
|
||||
//------------------------------------------------------
|
||||
|
||||
void GAME_TIMEATTACK_RESULT(uint16_t count, uint16_t time)
|
||||
{
|
||||
OLED_CLEAR();
|
||||
float avgSpeed = 0.0;
|
||||
avgSpeed = (float)count/time;
|
||||
drawTextCenter(128/2, 0, 2, "RESULT");
|
||||
drawTextCenter(128/2, 20, 2, String(avgSpeed, 2) + " K/s");
|
||||
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||
OLED_SHOW();
|
||||
|
||||
// Waiting For Center Button To Move On
|
||||
while(1){
|
||||
if(BTN_CENTER.pressed()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,370 +0,0 @@
|
||||
/* ===============================================
|
||||
* - 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 = 1;
|
||||
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 15 // 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) {
|
||||
// Initialization Of Bluetooth Connected Mode
|
||||
OLED_BLUETOOTH_MODE(); // Display Bluetooth Connected Mode
|
||||
DISPLAY_CHANGED = false; // Give Permition To Change The Content
|
||||
delay(3000); // Hold The Display Content For 3 Seconds
|
||||
|
||||
// While You Are On Bluetooth Connected Mode
|
||||
while(BLUETOOTH_STATUS == true) {
|
||||
ListenToBluetooth(); // Reading Only From Bluetooth
|
||||
}
|
||||
|
||||
// Give Permition To Change The Content
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// This Is For Stand Alone Mode
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
else {
|
||||
// Initialization Of Stand Alone Mode
|
||||
OLED_STANDALONE_MODE(); // Display Stand Alone Mode
|
||||
DISPLAY_CHANGED = false; // Give Permition To Change The Content
|
||||
delay(3000); // Hold The Display Content For 3 Seconds
|
||||
|
||||
// While You Are On Stand Alone Mode
|
||||
while(BLUETOOTH_STATUS == false) {
|
||||
ListenToStandAlone(); // Enter Listen To Stand Alone Buttons
|
||||
}
|
||||
|
||||
// Once The Stand Alone Mode Is Over
|
||||
DISPLAY_CHANGED = false; // Give Permition To Change The Display
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------
|
||||
// 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())
|
||||
{
|
||||
// Checking The Condition Of Order Number
|
||||
if(MENU_COUNT == 1 || MENU_COUNT < 1) {
|
||||
MENU_COUNT = 3; // If The Value Equals To Zero Then Roll Back To 4
|
||||
} else {
|
||||
MENU_COUNT -= 1;
|
||||
}
|
||||
|
||||
// Give Permition To Change The Screen
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
// SHIFT TO NEXT GAME MENU
|
||||
else if(BTN_NEXT.pressed())
|
||||
{
|
||||
// Checking The Condition Of Order Number
|
||||
if(MENU_COUNT == 3 || MENU_COUNT > 3)
|
||||
{
|
||||
MENU_COUNT = 1; // If The Value Exceeds 4 Then Roll Back To 1
|
||||
} else {
|
||||
MENU_COUNT += 1;
|
||||
}
|
||||
|
||||
// Give Permition To Change The Screen
|
||||
DISPLAY_CHANGED = false;
|
||||
}
|
||||
|
||||
// SELECT CURRENT DISPLAYED MENU
|
||||
else if(BTN_CENTER.pressed())
|
||||
{
|
||||
// IF LONG PRESS -> POWER OFF KICKER
|
||||
DETECT_LONG_PRESS();
|
||||
|
||||
// IF SHORT PRESS -> PLAY GAME CORESPONDING TO NUMBER
|
||||
switch(MENU_COUNT)
|
||||
{
|
||||
case 1: // Play Counter Game
|
||||
Terminal.println("SELECTED -> GAME COUNTER");
|
||||
game_counter_standalone();
|
||||
break;
|
||||
case 2: // Play Time Attack Game
|
||||
Terminal.println("SELECTED -> GAME TIME ATTACK");
|
||||
time_attack_standalone();
|
||||
break;
|
||||
case 3: // Play Reaction Game
|
||||
Terminal.println("SELECTED -> GAME REACTION");
|
||||
game_reaction_standalone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Display The Game Pages
|
||||
if(DISPLAY_CHANGED == false)
|
||||
{
|
||||
// IF Previous / Next Buttons Are Pressed -> Display Menu Selection On Terminal
|
||||
switch(MENU_COUNT)
|
||||
{
|
||||
case 1: // Play Counter Game
|
||||
//Terminal.println("MENU #" + String(MENU_COUNT) + " - " + "GAME COUNTER");
|
||||
GAME_TITLE_DISPLAY(MENU_COUNT, "COUNTER");
|
||||
break;
|
||||
case 2: // Play Time Attack Game
|
||||
//Terminal.println("MENU #" + String(MENU_COUNT) + " - " + "GAME TIME ATTACK");
|
||||
GAME_TITLE_DISPLAY(MENU_COUNT, "TIME ATTACK");
|
||||
break;
|
||||
case 3: // Play Reaction Game
|
||||
//Terminal.println("MENU #" + String(MENU_COUNT) + " - " + "GAME REACTION");
|
||||
GAME_TITLE_DISPLAY(MENU_COUNT, "REACTION");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,295 +0,0 @@
|
||||
////======================================================
|
||||
//// 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);
|
||||
// }
|
||||
@ -1,272 +0,0 @@
|
||||
//======================================================
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 133 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 161 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 2.7 MiB |
|
Before Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 450 KiB |
|
Before Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 207 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 1.5 MiB |
BIN
Pictures/Thumbs.db
Normal file
BIN
Pictures/components/Thumbs.db
Normal file
BIN
Pictures/contributers/Thumbs.db
Normal file
BIN
Pictures/the-app/Thumbs.db
Normal file
BIN
Pictures/v2/Thumbs.db
Normal file
|
Before Width: | Height: | Size: 1.2 MiB |
74
README.md
@ -1,2 +1,72 @@
|
||||
# Kicker
|
||||
TAKEONE Product Named Kicker
|
||||

|
||||
|
||||
TAKEONE Kicker, Hi-tech state of the art equipment, that will encourage you to be better to stay at the top of your game. equipped with modern design and digital electronics. Made to convert you into a champions.
|
||||
|
||||
## History Of Kicking Target
|
||||
Kicking target is originally used in TaeKwonDo martial arts for light training where its meant to increase your focus, timing and speed, However the targets was a piece of equipment compulsory like the heavy bag for boxers, they are just a target for striking without any intelligence. it could not tell anything about the striker not measure the capabilities. So TAKEONE team took the step forward to convert this target into a technological state of the art gadget to accurately measure and keep track of the performance of the athletes utilizing its high tech features. This gadget can work standalone or via Bluetooth operated by a phone with great visualization of striking data and archiving the history.
|
||||
|
||||

|
||||
|
||||
## The Science Behind TAKEONE Kicker
|
||||
since we have a striking sport that is going to use it, I would like to explain the methodology of kicker measurement by an example. lets begin,
|
||||
|
||||
#### imagine
|
||||
Just imagine with me, you are closing your eyes and suddenly you listen to a person knocking the door on a slow pace, then if you ignore the knock's, the person tries harder so he knock's back again harder and on a faster pace. if you com to think of it now how did your ears and brain differentiate between weak and slow, fast and hard knock's.
|
||||
|
||||
#### answer
|
||||
the answer is, that you ears listen to the knock's but your brain indirectly is measuring the knock's amplitude to differentiate weak or hard and the time space between every knock (slow rep knocking) or (fast rep knocking)
|
||||
|
||||
## The Science Behind The Kicker
|
||||
The science behind the kicker, is the basic understanding of martial arts training terminology and converting them to algorithms. Its based on registering the strikes magnitude and register their timestamp. This will open opportunities to calculate and measure the athletes capabilities and skills, not to mention that it can keep track of their progress. with the addition of an RGB interactive element it expands the possibilities to be able to measure skills that are related to your brain activity like reflex time, decision making and much more.
|
||||
|
||||
### Key Components
|
||||
|
||||
##### Strike Sensing
|
||||
Strikes are sensed with vibration sensor it gives an alternating voltage when struck and the amplitude increases proportionally with the force of the strike. how ever we don't measure the force of the strike accurately, so we give it a threshold in case this threshold is crossed that is considers a valid strike.
|
||||
|
||||
##### Interactive Indication
|
||||
Interactive indication is important so that user could understand the signals and knows what's going on. we use addressable RGB Neo Pixel Strip, to light up the strip with different patterns to signal the user to interact with the device.
|
||||
|
||||
##### Device Controller
|
||||
in order to do accurate timing and measuring of the event of the games and the capabilities of the athletes who are using the device, we need and powerful brain that's is accurate and reliable with expandable memory wireless connectivity and can run a display and manage power consumption intelligently and keep the battery in safe conditions that will expand its life span. that brain is [TAKEONE Board (ESP32)](https://github.com/GhassanYusuf/takeone-esp32-board)
|
||||
|
||||
##### Circuit Diagram
|
||||
=======
|
||||
#### conclusion
|
||||
therefore we conclude that if we register the amplitude of the strike power and time stamp of each strike hitting target. we get the following shape of data.
|
||||
|
||||
```
|
||||
{
|
||||
strike_number : 5, // This tells the current strike count
|
||||
amplitude : 50, // This tells how hard was it struck
|
||||
timestamp : 2.45 // This tells the time in seconds of the strike
|
||||
}
|
||||
```
|
||||
|
||||
#### Click The Picture For Live Demo
|
||||
|
||||
[](https://youtu.be/ycsHNqcLSlA)
|
||||
|
||||
## Circuit Diagram
|
||||
|
||||

|
||||
|
||||
### Key Components
|
||||
|
||||
#### Strike Sensing
|
||||
Strikes are sensed with vibration sensor it gives an alternating voltage when struck and the amplitude increases proportionally with the force of the strike. how ever we don't measure the force of the strike accurately, so we give it a threshold in case this threshold is crossed that is considers a valid strike.
|
||||
|
||||
<p align="center">
|
||||
<img src="./Pictures/components/piezodisk.jpg" alt="Image"/>
|
||||
</p>
|
||||
|
||||
#### Interactive Indication
|
||||
Interactive indication is important so that user could understand the signals and knows what's going on. we use addressable RGB Neo Pixel Strip, to light up the strip with different patterns to signal the user to interact with the device.
|
||||
|
||||

|
||||
|
||||
#### Device Controller
|
||||
in order to do accurate timing and measuring of the event of the games and the capabilities of the athletes who are using the device, we need and powerful brain that's is accurate and reliable with expandable memory wireless connectivity and can run a display and manage power consumption intelligently and keep the battery in safe conditions that will expand its life span. that brain is [TAKEONE Board (ESP32 Weroom)](https://github.com/GhassanYusuf/takeone-esp32-board)
|
||||
>>>>>>> 46e0d169bc8b2b8bc7dae1666a5a513553e98e19
|
||||
|
||||

|
||||
|
||||
225
SIGNALS.md
Normal file
@ -0,0 +1,225 @@
|
||||
# Kicker Signaling
|
||||
details about communication protocol between mobile phone app and kicker
|
||||
|
||||
## How To Connect To KICKER ?
|
||||
in order to connect to kicker, you need to enable ***Bluetooth*** connection. and try to connect via two methods
|
||||
|
||||
* Scan For Bluetooth Devices And Add Manually
|
||||
* Scan A QR Code With JSON Content
|
||||
|
||||
### QR Code JSON Content
|
||||
```
|
||||
{"request":"pair_kicker","device-name":"KICKER","device-mac":"98:D3:31:60:4E:A5"}
|
||||
```
|
||||
|
||||
### Fixed Messages, Responses, Commands
|
||||
Here we will discuss all sorts of fixed commands, messages, responses - what do they do and what do they mean, and how to use them in our firmware. Ghassan Yusuf built this protocol carefully for high accuracy data arbitration.
|
||||
|
||||
#### Game Selection Indicators
|
||||
When the user selects a game and the data is being sent to the kicker, the kicker confirms the selection and responses back with a message to indicate the game type selected.
|
||||
|
||||
*When counter game is selected*
|
||||
```
|
||||
{"gm":"COUNTER"}
|
||||
```
|
||||
|
||||
*When time attack game is selected*
|
||||
```
|
||||
{"gm":"TIME ATTACK"}
|
||||
```
|
||||
|
||||
*When reaction game is selected*
|
||||
```
|
||||
{"gm":"REACTION"}
|
||||
```
|
||||
|
||||
*When decision game is selected*
|
||||
```
|
||||
{"gm":"DECISION"}
|
||||
```
|
||||
|
||||
*When stamina game is selected*
|
||||
```
|
||||
{"gm":"STAMINA"}
|
||||
```
|
||||
|
||||
#### Messages
|
||||
These messages are for notifying the mobile device with the status of the events occurring within its firmware, like reporting back specific events.
|
||||
|
||||
*When you power on the first thing it does is to send the following signal informing the user that the kicker is on. (Note) at the moment of powering on the Bluetooth goes off to so its no longer connected this message will show on the serial terminal only.*
|
||||
```
|
||||
{"status":"POWER UP"}
|
||||
```
|
||||
|
||||
*When the user sends a game selection or command, if the signal was recognized and understood by the firmware it send back the following response*
|
||||
```
|
||||
{"status":"OK"}
|
||||
```
|
||||
|
||||
*When the user sends a game selection or command, if the signal JSON data get corrupted due to lack of memory or interference then it send back the following response*
|
||||
```
|
||||
{"status":"ERROR JSON"}
|
||||
```
|
||||
|
||||
*When the user playes a game and the game ends because the user didnt cach up with the limits he set or the user send a quit command {"cm":"STOP"}, Then it send the following command - it means you quit the game or you could not keep up with the game and ended in loss*
|
||||
```
|
||||
{"status":"GAME OVER"}
|
||||
```
|
||||
|
||||
*When the user sends a JSON formated signal in game selection routine, if the signal was not recognized or not understood by the firmware it send back the following response*
|
||||
```
|
||||
{"status":"UNKNOWN GAME"}
|
||||
```
|
||||
|
||||
#### Commands
|
||||
|
||||
*In some cases after passing the game type and parameters, the kicker waits for a start signal to start the game for playing, so by sending this json the game will start*
|
||||
```
|
||||
{"cm":"START"}
|
||||
```
|
||||
|
||||
*While the user is playing the game already - there are some odd casses they want to start all over again, so they send a reset json to start over the count and time*
|
||||
```
|
||||
{"cm":"RESET"}
|
||||
```
|
||||
|
||||
*When the user is playing a game and all of a sudden wanted to quit the game, he have to send this json to stop the game*
|
||||
```
|
||||
{"cm":"STOP"}
|
||||
```
|
||||
|
||||
<HR>
|
||||
|
||||
## Games Selection
|
||||
In order to select a specific game, the kicker should be not engaged with any running game, Then only it can receive game selection signal and pass the game parameters.
|
||||
|
||||
<HR>
|
||||
|
||||
### Counter Game
|
||||
* Open Counter
|
||||
* Close Counter With Count Trials
|
||||
|
||||
#### The JSON Format (setting is a nested JSON)
|
||||
```
|
||||
{"gm":"ct", "set": {"le":true, "lm": 10}}
|
||||
|
||||
ct : Kick Counter Game
|
||||
le : Previous Games Results (Action One Result, Action Two Result)
|
||||
lm : Kick Limit Amount
|
||||
```
|
||||
This mean that the player wants to play a counter game with limit feature enabled, limited number of kicks are 10, then the game stops counting.
|
||||
|
||||
#### Strike Signal
|
||||
```
|
||||
{"ct":1,"st":5.215}
|
||||
|
||||
ct : Kick Count
|
||||
st : Time Of The Kick In Milliseconds
|
||||
```
|
||||
|
||||
#### Result Calculations
|
||||
```
|
||||
number of kicks = maximum number of kicks the user made on the target
|
||||
```
|
||||
|
||||
<HR>
|
||||
|
||||
### Time Attack Game
|
||||
Open Kick Counter Limited By Time Window
|
||||
Closed Kick Counter Limited By Trials Count Or Time Window
|
||||
|
||||
#### The JSON Format (setting is a nested JSON)
|
||||
```
|
||||
{"gm":"ta", "set": {"tm": 60, "lm": 10, "le": true}}
|
||||
|
||||
ta : Decision Time Measurement Game
|
||||
tm : Game Play Time
|
||||
lm : Kick Trial Amount
|
||||
le : Enable End Game When Limits It Meet
|
||||
```
|
||||
This mean that the player wants to play a Time Attack game for 60s and enabled kick limits to 200 kicks.
|
||||
|
||||
#### Strike Signal
|
||||
```
|
||||
{"tm":5,"ct":2,"st":0.289,"dl":0.289}
|
||||
|
||||
tm : Count Down Display Time (in Seconds)
|
||||
ct : Kick Count (Number Of Kicks)
|
||||
st : Time Of Each Strike (In Milliseconds)
|
||||
dl : Diviation Between Kicks (In Milliseconds)
|
||||
```
|
||||
|
||||
#### Result Calculations
|
||||
```
|
||||
timeattack = (number of kicks)/(time taken to finish the game) = Kicks Per Second
|
||||
```
|
||||
|
||||
<HR>
|
||||
|
||||
### Reaction Game
|
||||
Open Reaction Game With No Trials Limit
|
||||
Open Reaction Game With No Trials Limit With Time Limit
|
||||
Closed Reaction Game With Trials Limit Without Time Limit
|
||||
|
||||
#### The JSON Format (setting is a nested JSON)
|
||||
```
|
||||
{"gm":"ra", "set": {"lm": 10, "mn": 1, "mx": 3}}
|
||||
|
||||
ra : Reaction/Reflex Measurement Game
|
||||
lm : Kick Trial Amount
|
||||
mn : Minimum Delay Between Signals
|
||||
mx : Maximum Delay Between Signals
|
||||
```
|
||||
This mean that the player wants to play a reaction game for a strike named “Front Kick” with enables trials of 10 kicks with delay spacing between trials (1s up to 3s) without time limits.
|
||||
|
||||
#### Strike Signal
|
||||
```
|
||||
{"ct":3,"pw":65467,"sd":3,"re":0.005}
|
||||
|
||||
ct : kick count
|
||||
pw : kick power
|
||||
sd : sconds delay between light trigger
|
||||
re : reaction time in milli seconds
|
||||
```
|
||||
|
||||
#### Result Calculations
|
||||
```
|
||||
avarage reaction= (sum of all reaction time (sum re))/(total number of trials (max〖ct)〗 )=milli seconds
|
||||
```
|
||||
|
||||
<HR>
|
||||
|
||||
### Decision Making Game
|
||||
( This game is locked & unlock only if you have records with different kinds of reaction trials with different actions )
|
||||
Closed Decision Making Game With Trials Limit
|
||||
Closed Decision Making Game With Time Limit
|
||||
|
||||
#### The JSON Format (setting is a nested JSON with action array)
|
||||
```
|
||||
{"gm":"de", "set":{“pr”: [<action1>, <action2>], "lm": 10, "mn": 1, "mx": 3}}
|
||||
|
||||
de : Decision Time Measurement Game
|
||||
pr : Previous Games Results (Action One Result, Action Two Result)
|
||||
lm : Kick Trial Amount
|
||||
mn : Minimum Delay Between Signals
|
||||
mx : Maximum Delay Between Signals
|
||||
```
|
||||
This mean that the player wants to play a reaction game for a strike named “Front Kick” with enables trials of 10 kicks with delay spacing between trials (1s up to 3s) without time limits.
|
||||
|
||||
<HR>
|
||||
|
||||
### Stamina Measurement Game
|
||||
* Open stamina measurement
|
||||
* Closed stamina measurement to Time Limit
|
||||
|
||||
#### The JSON Format (setting is a nested JSON with action array)
|
||||
```
|
||||
{"game":"st", "set":{“le”: true, “lm”: 20, “tm”: 30, "mx":120 }}
|
||||
|
||||
st : Stamina Measurement Game
|
||||
le : Enable Limit Number Of Kicks
|
||||
lm : Kick Limit Amount
|
||||
tm : Game Time In Seconds
|
||||
mx : Max Strike Deviation in Milliseconds (Spacing Between Strikes)
|
||||
```
|
||||
This mean that the player wants to play a stamina game for a strike named “Front Kick” with enables time limit of 120s.
|
||||
@ -18,11 +18,11 @@
|
||||
// Time Attack Game
|
||||
else if(game == "ta") {
|
||||
terminal(GM_TATTACK);
|
||||
game_reaction_bluetooth(settings);
|
||||
time_attack_bluetooth(settings);
|
||||
return;
|
||||
}
|
||||
|
||||
// Time Attack Game
|
||||
// Time Reaction Game
|
||||
else if(game == "ra") {
|
||||
terminal(GM_REACTION);
|
||||
game_reaction_bluetooth(settings);
|
||||
@ -87,7 +87,7 @@
|
||||
|
||||
// PUBLIC VARIABLES
|
||||
uint16_t time = JSON["tm"]; // Time Window To JSON
|
||||
uint16_t timer = time;
|
||||
uint16_t timer = time; // Time
|
||||
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||
|
||||
@ -10,42 +10,8 @@
|
||||
//======================================================
|
||||
// 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
|
||||
#ifdef ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
|
||||
//------------------------------------------------------
|
||||
|
||||
// Library Nessesary
|
||||
@ -68,13 +34,20 @@
|
||||
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
|
||||
|
||||
// JSON Object & Memory
|
||||
#define CAPACITY 100
|
||||
#define CAPACITY 150
|
||||
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);
|
||||
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
// Power Holding Pin
|
||||
#define POWER_PIN 13
|
||||
#define POWER_SETUP pinMode(POWER_PIN, OUTPUT)
|
||||
#define POWER_ON digitalWrite(POWER_PIN, HIGH)
|
||||
#define POWER_OFF digitalWrite(POWER_PIN, LOW)
|
||||
#define POWER_STU digitalRead(POWER_PIN)
|
||||
|
||||
// Impact Detection
|
||||
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||
@ -128,7 +101,7 @@
|
||||
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||
|
||||
// LED Strip
|
||||
#define LED_STRIP 33 // LED STRIP PIN NUMBER
|
||||
#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);
|
||||
|
||||
@ -154,6 +127,13 @@
|
||||
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
|
||||
#define BOOST_STU digitalRead(BOOST_PIN)
|
||||
|
||||
// Power Holding Pin
|
||||
#define POWER_PIN 13
|
||||
#define POWER_SETUP pinMode(POWER_PIN, OUTPUT)
|
||||
#define POWER_ON digitalWrite(POWER_PIN, HIGH)
|
||||
#define POWER_OFF digitalWrite(POWER_PIN, LOW)
|
||||
#define POWER_STU digitalRead(POWER_PIN)
|
||||
|
||||
// Battery Level Monitoring
|
||||
#define BATTERY_PIN 35
|
||||
#define BATTERY (float)(((analogRead(BATTERY_PIN) * (3.3 / 4096)) * 2) + 0.31)
|
||||
@ -182,9 +162,7 @@
|
||||
#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
|
||||
@ -198,7 +176,6 @@
|
||||
#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
|
||||
@ -223,6 +200,8 @@
|
||||
// Make Sure Of The Core
|
||||
#ifdef ESP32
|
||||
Bluetooth.begin("KICKER"); // Bluetooth device name
|
||||
POWER_SETUP; // Boost Pin Setup
|
||||
POWER_ON; // Turn Power On - And Keep On
|
||||
BOOST_SETUP; // Boost Pin Setup
|
||||
BOOST_OFF; // Turn It Off
|
||||
#else
|
||||
@ -274,7 +253,7 @@
|
||||
dualcomm(UNDERSTOOD);
|
||||
|
||||
// Reading Game Name & Settings
|
||||
String game = JSON["gm"];
|
||||
String game = JSON["gm"];
|
||||
String settings = JSON["set"];
|
||||
|
||||
// Clearing JSON Buffer
|
||||
@ -285,9 +264,12 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send Back A Signal
|
||||
terminal(JSON_ERROR);
|
||||
}
|
||||
Bluetooth.flush();
|
||||
|
||||
// Clear Bluetooth Buffer
|
||||
flushBluetooth;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,11 +8,6 @@
|
||||
|
||||
void LED_CLEAR()
|
||||
{
|
||||
// Make Sure Of The Core
|
||||
#ifdef ESP32
|
||||
LED_BOOST_CHK();
|
||||
#endif
|
||||
|
||||
// Clear The Strip Color
|
||||
pixels.clear();
|
||||
|
||||
@ -23,11 +18,6 @@
|
||||
|
||||
// Show On LED Strip
|
||||
LED_SHOW();
|
||||
|
||||
// Make Sure Of The Core
|
||||
#ifdef ESP32
|
||||
BOOST_OFF;
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
@ -36,11 +26,6 @@
|
||||
|
||||
void LED_SHOW()
|
||||
{
|
||||
// Make Sure Of The Core
|
||||
#ifdef ESP32
|
||||
LED_BOOST_CHK();
|
||||
#endif
|
||||
|
||||
// Pass It To The LED Strip
|
||||
pixels.show();
|
||||
}
|
||||
@ -51,11 +36,6 @@
|
||||
|
||||
void LED_SET_BRIGHTNESS(uint8_t Value)
|
||||
{
|
||||
// Make Sure Of The Core
|
||||
#ifdef ESP32
|
||||
LED_BOOST_CHK();
|
||||
#endif
|
||||
|
||||
// Set The Brightness
|
||||
pixels.setBrightness(Value);
|
||||
}
|
||||
@ -66,11 +46,6 @@
|
||||
|
||||
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);
|
||||
|
||||
@ -105,11 +80,6 @@
|
||||
// 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++)
|
||||
{
|
||||
@ -126,11 +96,6 @@
|
||||
// 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;
|
||||
|
||||
@ -156,11 +121,6 @@
|
||||
// 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;
|
||||
|
||||
@ -183,11 +143,6 @@
|
||||
|
||||
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++)
|
||||
{
|
||||
@ -208,11 +163,6 @@
|
||||
|
||||
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--)
|
||||
{
|
||||
@ -233,11 +183,6 @@
|
||||
|
||||
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);
|
||||
@ -310,11 +255,6 @@
|
||||
|
||||
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);
|
||||
@ -329,11 +269,6 @@
|
||||
|
||||
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);
|
||||
BIN
firmware/kicker_alejandro.zip
Normal file
BIN
images/components/newpixelstrip.jpg
Normal file
|
After Width: | Height: | Size: 415 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 112 KiB |
BIN
images/components/piezodisk.JPG
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
images/components/schematicv2.png
Normal file
|
After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
BIN
images/explanatory/kickingtarget.jpg
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
images/explanatory/kidstrainning.jpg
Normal file
|
After Width: | Height: | Size: 256 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 138 KiB |