Loaded Every Thing From My Work
BIN
3D Model/Battery.ipt
Normal file
BIN
3D Model/Bottom Electronic Box Cover.ipt
Normal file
BIN
3D Model/Button.ipt
Normal file
BIN
3D Model/Buttons Rubber.ipt
Normal file
BIN
3D Model/Center Button Cap.ipt
Normal file
BIN
3D Model/Circuit Board.ipt
Normal file
BIN
3D Model/Corner Button Cap.ipt
Normal file
BIN
3D Model/Electronic Board.ipt
Normal file
BIN
3D Model/FacePanel Assembly.iam
Normal file
BIN
3D Model/FaceTemplate.ipt
Normal file
BIN
3D Model/Kicker Body.iam
Normal file
BIN
3D Model/Kicker Electronics Box 2.iam
Normal file
BIN
3D Model/Kicker Electronics Box.iam
Normal file
BIN
3D Model/KickerEmbededCase.iam
Normal file
BIN
3D Model/KickerEmbededCase.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
3D Model/LED STRIP GUARD.ipt
Normal file
BIN
3D Model/LED Strip Protector Guide.ipt
Normal file
BIN
3D Model/LED2 Strip Protector Guide.ipt
Normal file
BIN
3D Model/Left Foam.ipt
Normal file
BIN
3D Model/Left Single Flap - Copy.ipt
Normal file
BIN
3D Model/OLED Display.ipt
Normal file
BIN
3D Model/Right Foam.ipt
Normal file
BIN
3D Model/Right Single Flap.ipt
Normal file
BIN
3D Model/Rubber Buttons Mold Assembly.iam
Normal file
BIN
3D Model/Rubber Buttons Mold.ipt
Normal file
BIN
3D Model/TopFace.ipt
Normal file
BIN
3D Model/TopFace2.ipt
Normal file
BIN
3D Model/TopFace22.ipt
Normal file
BIN
Datasheets/DS4812-07 - Buck Boost Converter Chip.pdf
Normal file
BIN
Datasheets/IRLML6402.pdf
Normal file
BIN
Datasheets/TPS27081A.pdf
Normal file
BIN
Documents/Kicker Matt - Game Result Calculation Formulas.docx
Normal file
BIN
Documents/Kicker Matt - Games Description.docx
Normal file
BIN
Documents/TAKEONE Kicker Games On Platform.docx
Normal file
BIN
Documents/TakeOne Kicker Matt Title.png
Normal file
|
After Width: | Height: | Size: 145 KiB |
BIN
Documents/TakeOne Kicker Matt Title.psd
Normal file
BIN
Documents/أداة تستخدم كـ هدف و تتمتع بمميزات إلكترونية ذكية.docx
Normal file
258
Firmware Code/KICKER_V2/KICKER_V2.ino
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
//======================================================
|
||||||
|
// LIBRARIES
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
#include <Button.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <TimeTrigger.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
#ifdef __AVR__
|
||||||
|
#include <avr/power.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// MODE SELECTION VARIABLES
|
||||||
|
int mode;
|
||||||
|
bool flagChange = false;
|
||||||
|
|
||||||
|
// FIXED MESSAGES
|
||||||
|
#define POWERUP "{\"status\":\"POWER UP\"}"
|
||||||
|
#define UNDERSTOOD "{\"status\":\"OK\"}"
|
||||||
|
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
|
||||||
|
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
|
||||||
|
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
|
||||||
|
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
|
||||||
|
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
|
||||||
|
|
||||||
|
// GAME NAMES
|
||||||
|
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
|
||||||
|
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
|
||||||
|
#define GM_REACTION "{\"gm\":\"REACTION\"}"
|
||||||
|
#define GM_DECISION "{\"gm\":\"DECISION\"}"
|
||||||
|
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
|
||||||
|
|
||||||
|
// COMMAND LIST
|
||||||
|
#define CM_START "{\"cm\":\"START\"}"
|
||||||
|
#define CM_RESET "{\"cm\":\"RESET\"}"
|
||||||
|
#define CM_STOP "{\"cm\":\"STOP\"}"
|
||||||
|
#define CM_EXIT "{\"cm\":\"EXIT\"}"
|
||||||
|
|
||||||
|
// JSON JSON_CAPACITY
|
||||||
|
#define JSON_CAPACITY 500
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// HARDWARE SELECTION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
#define TERMINAL Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define VTH 65 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define PWR 65 // MIN THRESHOLD VOLTAGE FROM ZERO POINT TO BE ACCOUNTED AS KICK
|
||||||
|
#define NUM_PIXELS 22 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
#define MPU_ADD 0x69 // On Board MPU9250 I2C Address
|
||||||
|
#define OLED_ADD 0x3C // Connected I2C OLED Address
|
||||||
|
|
||||||
|
// Incase You Are Using Arduino MEGA
|
||||||
|
#ifdef ARDUINO_AVR_MEGA2560
|
||||||
|
|
||||||
|
#define BLUETOOTH Serial1
|
||||||
|
Button button(52); // BUTTON ON PIN 2
|
||||||
|
#define LED_STRIP 53 // LED STRIP PIN NUMBER
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A2 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// Incase You Are Using Arduino Nano
|
||||||
|
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
|
||||||
|
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
//----------------------------------------------------------
|
||||||
|
SoftwareSerial BLUETOOTH(10, 11); // RX, TX
|
||||||
|
Button button(2); // BUTTON ON PIN 2
|
||||||
|
#define LED_STRIP 8 // LED STRIP PIN NUMBER
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A3 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// if This Was The ESP32 Core
|
||||||
|
#elif ESP32
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
#include <BluetoothSerial.h>
|
||||||
|
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||||
|
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||||
|
#endif
|
||||||
|
//----------------------------------------------------------
|
||||||
|
|
||||||
|
// BLUETOOTH DEFINITION
|
||||||
|
BluetoothSerial BLUETOOTH;
|
||||||
|
|
||||||
|
// BUTTONS
|
||||||
|
Button button(2); // BUTTON ON PIN 2
|
||||||
|
|
||||||
|
// PIEZO SENSOR PIN
|
||||||
|
#define SENSOR_PIN 39 // IMPACT SENSOR
|
||||||
|
|
||||||
|
// LED STRIP PIN SET
|
||||||
|
#define LED_STRIP 26 // LED STRIP PIN NUMBER
|
||||||
|
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// Battery To 5V Level Booster Setup & Control
|
||||||
|
#define BOOST_PIN 14
|
||||||
|
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
|
||||||
|
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
|
||||||
|
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
|
||||||
|
|
||||||
|
// Battery Level Monitoring
|
||||||
|
#define BATTERY (float)(((analogRead(35) * (3.3 / 4096)) * 2) + 0.28)
|
||||||
|
#define CHARGE mapf(BATTERY, 3.27, 4.31, 0, 100)
|
||||||
|
|
||||||
|
// End Of Arduino Selection ARDUINO_MEGA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Float Mapping Function
|
||||||
|
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
|
||||||
|
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// DEFINITION & DECLERATIONS
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Serial Flags
|
||||||
|
#define isBluetooth BLUETOOTH.available()
|
||||||
|
#define isTERMINAL TERMINAL.available()
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// READING IMPACT POWER FROM ANALOG PINS
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// READING THE IMPACT
|
||||||
|
int readImpact()
|
||||||
|
{
|
||||||
|
int value = abs(constrain(analogRead(SENSOR_PIN), VTH, 1023));
|
||||||
|
value = map(value, VTH, 1023, 0, 1023);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN HARDWARE SETUP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Communications
|
||||||
|
TERMINAL.begin(9600);
|
||||||
|
|
||||||
|
// Oled Display
|
||||||
|
oled_init();
|
||||||
|
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_SETUP;
|
||||||
|
BOOST_OFF;
|
||||||
|
BLUETOOTH.begin("KICKER"); //Bluetooth device name
|
||||||
|
#else
|
||||||
|
BLUETOOTH.begin(9600);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// I/O
|
||||||
|
button.begin(); // Button
|
||||||
|
pixels.begin(); // Neo Pixel
|
||||||
|
LED_CLEAR(); // Turn Off All LED
|
||||||
|
|
||||||
|
// The Random Number Source
|
||||||
|
randomSeed(analogRead(RANDOM_SOURCE));
|
||||||
|
|
||||||
|
// Battery Managment
|
||||||
|
if(BATTERY <= 3.7) {
|
||||||
|
// Display Battery Low
|
||||||
|
dualcomm("Battery Low");
|
||||||
|
// Display Battery Voltage
|
||||||
|
while(BATTERY <= 3.7) { Serial.println(BATTERY); drawProgressBarDemo(CHARGE); oled_show(); delay(5000); }
|
||||||
|
// Clearing The Screen
|
||||||
|
oled_clear();
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// POWER UP MESSGAE
|
||||||
|
dualcomm(POWERUP);
|
||||||
|
|
||||||
|
// TURN BOOSTER ON
|
||||||
|
BOOST_ON;
|
||||||
|
|
||||||
|
// Blue, Red And Green
|
||||||
|
colorWipe(pixels.Color(0, 0, 255), 15); // Blue
|
||||||
|
delay(100);
|
||||||
|
colorWipe(pixels.Color(255, 0, 0), 15); // Red
|
||||||
|
delay(100);
|
||||||
|
colorWipe(pixels.Color(0, 255, 0), 15); // Green
|
||||||
|
|
||||||
|
// Delay 1 Sec
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Red FadeOut
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
|
||||||
|
// Display Rainbow
|
||||||
|
LED_CLEAR();
|
||||||
|
|
||||||
|
// TURN BOOSTER ON
|
||||||
|
BOOST_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Reading From Bluetooth
|
||||||
|
if(BLUETOOTH.available())
|
||||||
|
{
|
||||||
|
// Reading Message From Bluetooth
|
||||||
|
String msg = BLUETOOTH.readString();
|
||||||
|
msg.trim();
|
||||||
|
|
||||||
|
// Display On Sertial
|
||||||
|
terminal(msg);
|
||||||
|
|
||||||
|
// Parsing Objects Message Objects
|
||||||
|
DynamicJsonDocument root(JSON_CAPACITY);
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(root, msg);
|
||||||
|
|
||||||
|
// If The System Understood The Message Clearly
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
// Sending Status Message
|
||||||
|
dualcomm(UNDERSTOOD);
|
||||||
|
|
||||||
|
// Reading Game Name & Settings
|
||||||
|
String game = root["gm"];
|
||||||
|
String settings = root["set"];
|
||||||
|
|
||||||
|
// Clearing JSON Buffer
|
||||||
|
root.clear();
|
||||||
|
|
||||||
|
// Entering To Game Selector
|
||||||
|
game_selector(game, settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Display The Error Message
|
||||||
|
terminal(JSON_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
BLUETOOTH.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END OF PROGRAM
|
||||||
|
//======================================================
|
||||||
29
Firmware Code/KICKER_V2/communication.ino
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//======================================================
|
||||||
|
// TERMINAL WINDOW - NATIVE USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void terminal(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
TERMINAL.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void bluetooth(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
BLUETOOTH.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void dualcomm(String msg)
|
||||||
|
{
|
||||||
|
terminal(msg);
|
||||||
|
bluetooth(msg);
|
||||||
|
}
|
||||||
206
Firmware Code/KICKER_V2/game_counter.ino
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN COUNTER GAME LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* --------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* ct : count
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* WHAT DATA TO BE COLLECTED :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISPLAY AND TIMESTAMP
|
||||||
|
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* No calculation required, Its directly the count
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_counter(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// CONVERTING GAME TEXT TO JSON
|
||||||
|
DynamicJsonDocument play(JSON_CAPACITY); // building JSON Buffer
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(play, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t limit = play["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = play["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
play.clear();
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Display Welcome Message
|
||||||
|
// TERMINAL("");
|
||||||
|
// TERMINAL("==================================================");
|
||||||
|
// TERMINAL(" -->> Counter Game Settings");
|
||||||
|
// TERMINAL("--------------------------------------------------");
|
||||||
|
// TERMINAL("Strike Limit : " + String(limit) + " Strikes");
|
||||||
|
// TERMINAL("Limits Enable : " + String(limitEnable));
|
||||||
|
// TERMINAL("--------------------------------------------------");
|
||||||
|
// TERMINAL("2 Seconds To Start Get Ready & Good Luck !!");
|
||||||
|
// TERMINAL("==================================================");
|
||||||
|
// TERMINAL("");
|
||||||
|
|
||||||
|
// Game Start Lights
|
||||||
|
Counter_Start();
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = BLUETOOTH.readString();
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
// TERMINAL("");
|
||||||
|
// TERMINAL("---------------------------------------------------");
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// TERMINAL("===================================================");
|
||||||
|
// TERMINAL("");
|
||||||
|
Counter_End();
|
||||||
|
// Grean Light In
|
||||||
|
//LED_GREEN_FADEOUT();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
Counter_Reset();
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
// TERMINAL("");
|
||||||
|
// TERMINAL("---------------------------------------------------");
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// TERMINAL("===================================================");
|
||||||
|
// TERMINAL("");
|
||||||
|
// Celebration
|
||||||
|
Counter_Celebration();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Impact
|
||||||
|
if(readImpact() > PWR)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(counter_data_json(counter, timeStamp));
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER DATA JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String counter_data_json(unsigned int ct, unsigned int st)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
DynamicJsonDocument data(JSON_CAPACITY);
|
||||||
|
|
||||||
|
// Convert Int To Float
|
||||||
|
float stamp = st;
|
||||||
|
stamp /= 1000;
|
||||||
|
|
||||||
|
// Assignning Dataset
|
||||||
|
data["ct"] = ct;
|
||||||
|
data["st"] = String(stamp, 3).toFloat();
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(data, output);
|
||||||
|
data.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Counter_Start()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
LED_WHITE_CROSSFADE(2);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Counter_End()
|
||||||
|
{
|
||||||
|
LED_RED_BLINK(2);
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Counter_Celebration()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Counter_Reset()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
LED_BLUE();
|
||||||
|
delay(250);
|
||||||
|
LED_BLUE_FADEOUT();
|
||||||
|
}
|
||||||
237
Firmware Code/KICKER_V2/game_reaction.ino
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
//======================================================
|
||||||
|
// REACTION GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* REACTION GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tr": 10, "mn": 1, "mx": 2}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* tr : trials pre counter
|
||||||
|
* mn : minimum delay, between trials
|
||||||
|
* mx : maximum delay, between trials
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tr" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_reaction(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// CONVERTING GAME TEXT TO JSON
|
||||||
|
DynamicJsonDocument play(JSON_CAPACITY);
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(play, settings);
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint8_t minDelay = play["mn"];
|
||||||
|
uint8_t maxDelay = play["mx"];
|
||||||
|
uint16_t trials = play["lm"];
|
||||||
|
uint16_t temp = trials;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
play.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Display Welcome Message
|
||||||
|
// TERMINAL("");
|
||||||
|
// TERMINAL("==================================================");
|
||||||
|
// TERMINAL(" -->> Reaction Game Settings");
|
||||||
|
// TERMINAL("--------------------------------------------------");
|
||||||
|
// TERMINAL("trials : " + String(trials) + " Strikes");
|
||||||
|
// TERMINAL("try delay : " + String(minDelay) + " to " + String(maxDelay) + " Seconds");
|
||||||
|
// TERMINAL("--------------------------------------------------");
|
||||||
|
// TERMINAL("2 Seconds To Start Get Ready & Good Luck !!");
|
||||||
|
// TERMINAL("==================================================");
|
||||||
|
// TERMINAL("");
|
||||||
|
|
||||||
|
// Ready Signal
|
||||||
|
Reaction_Start();
|
||||||
|
|
||||||
|
// Main Variables
|
||||||
|
uint16_t sdelay = 0;
|
||||||
|
uint16_t power = 0;
|
||||||
|
uint16_t response = 0;
|
||||||
|
unsigned long startTime = 0;
|
||||||
|
unsigned long stopTime = 0;
|
||||||
|
|
||||||
|
// Processing Results
|
||||||
|
for(int i=0; i<trials; i++)
|
||||||
|
{
|
||||||
|
// Reading Kick Data
|
||||||
|
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
|
||||||
|
terminal(" -> Get Ready !!");
|
||||||
|
|
||||||
|
// Set Random Delay Time
|
||||||
|
sdelay = random(minDelay, (maxDelay + 1));
|
||||||
|
sdelay *= 1000;
|
||||||
|
delay(sdelay);
|
||||||
|
|
||||||
|
// Light Up Green
|
||||||
|
rgbLED(0, 150, 0);
|
||||||
|
|
||||||
|
// Start Timer
|
||||||
|
startTime = millis();
|
||||||
|
|
||||||
|
// Sensing Strike Power
|
||||||
|
while(power < PWR)
|
||||||
|
{
|
||||||
|
// Reading The Strike
|
||||||
|
power = readImpact();
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = BLUETOOTH.readString();
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP) {
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
Reaction_End();
|
||||||
|
// LightUp
|
||||||
|
//LED_RED();
|
||||||
|
//delay(2000);
|
||||||
|
// Red FadeOut
|
||||||
|
//LED_RED_FADEOUT();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET) {
|
||||||
|
trials = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop Timer
|
||||||
|
stopTime = millis();
|
||||||
|
|
||||||
|
// Stop Light
|
||||||
|
rgbLED(150, 0, 0);
|
||||||
|
|
||||||
|
// Calculating Response Time
|
||||||
|
response = stopTime - startTime - 1;
|
||||||
|
|
||||||
|
// Create Json Data
|
||||||
|
String msg = reaction_data_json(i+1, power, response, sdelay);
|
||||||
|
|
||||||
|
// Print To TERMINAL
|
||||||
|
dualcomm(msg);
|
||||||
|
|
||||||
|
// Clear All
|
||||||
|
sdelay = 0;
|
||||||
|
power = 0;
|
||||||
|
response = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red Light Delay
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// END GAME
|
||||||
|
// TERMINAL("");
|
||||||
|
// TERMINAL("---------------------------------------------------");
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// TERMINAL("===================================================");
|
||||||
|
// TERMINAL("");
|
||||||
|
|
||||||
|
// Celebration
|
||||||
|
Reaction_Celebration();
|
||||||
|
|
||||||
|
// Blink Red
|
||||||
|
//Reaction_End();
|
||||||
|
|
||||||
|
// Return To Game Selector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION DATA JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String reaction_data_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
DynamicJsonDocument data(JSON_CAPACITY);
|
||||||
|
|
||||||
|
// Convert To Seconds Unit
|
||||||
|
float re = response;
|
||||||
|
re /= 1000;
|
||||||
|
|
||||||
|
// Asignning Values
|
||||||
|
data["ct"] = count; // Strike Number
|
||||||
|
data["pw"] = power; // Strike Power In Analog Read
|
||||||
|
data["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
|
||||||
|
data["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(data, output);
|
||||||
|
data.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Reaction_Start()
|
||||||
|
{
|
||||||
|
LED_WHITE_CROSSFADE(3);
|
||||||
|
LED_RED_FADEIN();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Reaction_End()
|
||||||
|
{
|
||||||
|
LED_RED_BLINK(2);
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Reaction_Celebration()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Reaction_Reset()
|
||||||
|
{
|
||||||
|
LED_BLUE();
|
||||||
|
delay(250);
|
||||||
|
LED_BLUE_FADEOUT();
|
||||||
|
}
|
||||||
37
Firmware Code/KICKER_V2/game_selector.ino
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* game selector is the main function that tell the game groutine
|
||||||
|
* which game to be played and at what parameters
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_selector(String game, String settings)
|
||||||
|
{
|
||||||
|
// Kick Counter Game
|
||||||
|
if(game == "ct") {
|
||||||
|
terminal(GM_COUNTER);
|
||||||
|
game_counter(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ta") {
|
||||||
|
terminal(GM_TATTACK);
|
||||||
|
game_timeAttack(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ra") {
|
||||||
|
terminal(GM_REACTION);
|
||||||
|
game_reaction(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown Game
|
||||||
|
else {
|
||||||
|
dualcomm(UNKNOWN_GAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
261
Firmware Code/KICKER_V2/game_time_attack.ino
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
//======================================================
|
||||||
|
// TIME ATTACK GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tm": 10, "le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* tm : count down timer starting value
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tm" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
|
||||||
|
*
|
||||||
|
* RETURNNING DATA FORMAT :
|
||||||
|
* ------------------------
|
||||||
|
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
|
||||||
|
*
|
||||||
|
* tm : timer count in Sec
|
||||||
|
* ct : strike counter (number of kicks)
|
||||||
|
* dl : delay between strikes
|
||||||
|
* st : time stampe of the strike in milli Seconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_timeAttack(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// CONVERTING GAME TEXT TO JSON
|
||||||
|
DynamicJsonDocument play(JSON_CAPACITY); // building JSON Buffer
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(play, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t time = play["tm"]; // Time Window To Play
|
||||||
|
uint16_t timer = time;
|
||||||
|
uint16_t limit = play["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = play["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
play.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Display Welcome Message
|
||||||
|
// TERMINAL("");
|
||||||
|
// TERMINAL("==================================================");
|
||||||
|
// TERMINAL(" -->> Time Attack Game Settings");
|
||||||
|
// TERMINAL("--------------------------------------------------");
|
||||||
|
// TERMINAL("Timer : " + String(time) + " Seconds");
|
||||||
|
// TERMINAL("Strike Limit : " + String(limit));
|
||||||
|
// TERMINAL("Limit Enabled : " + String(limitEnable));
|
||||||
|
// TERMINAL("--------------------------------------------------");
|
||||||
|
// TERMINAL("2 Seconds To Start Get Ready & Good Luck !!");
|
||||||
|
// TERMINAL("==================================================");
|
||||||
|
// TERMINAL("");
|
||||||
|
|
||||||
|
// Send Initial Display
|
||||||
|
dualcomm(timeAttack_data_json(timer, 0, 0, 0));
|
||||||
|
|
||||||
|
// Start LED Signal
|
||||||
|
TimeAttack_Start();
|
||||||
|
|
||||||
|
// Building Timers 1000mSec -> 1Sec
|
||||||
|
TimeTrigger sec_tick(1000);
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
// store the time of the previous kick
|
||||||
|
unsigned long lastStamp = 0;
|
||||||
|
|
||||||
|
// reseting time ticker
|
||||||
|
sec_tick.Reset();
|
||||||
|
|
||||||
|
// While The Game Is Still On
|
||||||
|
while(timer != 0)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = BLUETOOTH.readString();
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
timer = time;
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
sec_tick.Reset();
|
||||||
|
dualcomm(timeAttack_data_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Kick ---------------------------->>>
|
||||||
|
if(readImpact() > 100)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(timeAttack_data_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Second ---------------------------->>>
|
||||||
|
if(sec_tick.Trigger())
|
||||||
|
{
|
||||||
|
timer--;
|
||||||
|
dualcomm(timeAttack_data_json(timer, counter, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
// TERMINAL("");
|
||||||
|
// TERMINAL("---------------------------------------------------");
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// TERMINAL("===================================================");
|
||||||
|
// TERMINAL("");
|
||||||
|
// LightUp
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send End Game Signal To Smart Phone
|
||||||
|
// TERMINAL("");
|
||||||
|
// TERMINAL("---------------------------------------------------");
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// TERMINAL("===================================================");
|
||||||
|
// TERMINAL("");
|
||||||
|
|
||||||
|
// LightUp
|
||||||
|
LED_RED_FADEIN(); // RED Color
|
||||||
|
delay(2000); // Delay 2000
|
||||||
|
LED_CLEAR(); // CLEAR OFF
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// TIME ATTACK KICK DATA JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String timeAttack_data_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
DynamicJsonDocument data(JSON_CAPACITY);
|
||||||
|
data["tm"] = RunningTime;
|
||||||
|
data["ct"] = KickCount;
|
||||||
|
|
||||||
|
// Calculations
|
||||||
|
if(TimeStamp > 0 )
|
||||||
|
{
|
||||||
|
// Calculate Time Stamp In Seconds
|
||||||
|
float st = TimeStamp;
|
||||||
|
st /= 1000;
|
||||||
|
data["st"] = String(st, 3).toFloat();
|
||||||
|
|
||||||
|
// Calculate Strike Delay In Seconds
|
||||||
|
float dl = TimeStamp - LastStamp;
|
||||||
|
dl /= 1000;
|
||||||
|
data["dl"] = String(dl, 3).toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(data, output);
|
||||||
|
data.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void TimeAttack_Start()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
LED_WHITE_CROSSFADE(3);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void TimeAttack_End()
|
||||||
|
{
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
// Red Light In
|
||||||
|
LED_RED_FADEIN();
|
||||||
|
// Wait For 2 Sec
|
||||||
|
delay(2000);
|
||||||
|
// Red Light Out
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void TimeAttack_Celebration()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void TimeAttack_Reset()
|
||||||
|
{
|
||||||
|
LED_BLUE();
|
||||||
|
delay(250);
|
||||||
|
LED_BLUE_FADEOUT();
|
||||||
|
}
|
||||||
450
Firmware Code/KICKER_V2/neo_pixel.ino
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
#define BETWEEN_FADE 15
|
||||||
|
#define FADE_RATE 15
|
||||||
|
#define BLINK_RATE 250
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// SET STRIP COLOR
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void rgbLED(int red, int green, int blue)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<NUM_PIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, pixels.Color(red,green,blue));
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// CLEAR SIGNAL LED COLOR : NO COLOR
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_CLEAR()
|
||||||
|
{
|
||||||
|
rgbLED(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// RED
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_RED()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
rgbLED(255, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_RED_BLINK(int times)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_RED();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEIN
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_RED_FADEIN()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=0; i<=255; i=i+5)
|
||||||
|
{
|
||||||
|
rgbLED(i, 0, 0);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEOUT
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_RED_FADEOUT()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=255; i>=0; i=i-5)
|
||||||
|
{
|
||||||
|
rgbLED(i, 0, 0);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// CROSS FADE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_RED_CROSSFADE(int times)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_RED_FADEIN();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// GREEN
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_GREEN()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
rgbLED(0, 255, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_GREEN_BLINK(int times)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_GREEN();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEIN
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_GREEN_FADEIN()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=0; i<=255; i=i+5)
|
||||||
|
{
|
||||||
|
rgbLED(0, i, 0);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEOUT
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_GREEN_FADEOUT()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=255; i>=0; i=i-5)
|
||||||
|
{
|
||||||
|
rgbLED(0, i, 0);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// CROSS FADE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_GREEN_CROSSFADE(int times)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_GREEN_FADEIN();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_BLUE()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rgbLED(0, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLUE_BLINK(int times)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_BLUE();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEIN
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLUE_FADEIN()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=0; i<=255; i=i+5)
|
||||||
|
{
|
||||||
|
rgbLED(0, 0, i);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEOUT
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLUE_FADEOUT()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=255; i>=0; i=i-5)
|
||||||
|
{
|
||||||
|
rgbLED(0, 0, i);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// CROSS FADE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLUE_CROSSFADE(int times)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_BLUE_FADEIN();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
LED_BLUE_FADEOUT();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// WHITE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_WHITE()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
rgbLED(255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_WHITE_BLINK(int times)
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_WHITE();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEIN
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_WHITE_FADEIN()
|
||||||
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_ON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=0; i<=255; i=i+5)
|
||||||
|
{
|
||||||
|
rgbLED(i, i, i);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEOUT
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_WHITE_FADEOUT()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=255; i>=0; i=i-5)
|
||||||
|
{
|
||||||
|
rgbLED(i, i, i);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// CROSS FADE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_WHITE_CROSSFADE(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_WHITE_FADEIN();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
LED_WHITE_FADEOUT();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COLOR WHIPE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Fill the dots one after the other with a color
|
||||||
|
void colorWipe(uint32_t c, uint8_t wait)
|
||||||
|
{
|
||||||
|
for(uint16_t i=0; i<NUM_PIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, c);
|
||||||
|
pixels.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Slightly different, this makes the rainbow equally distributed throughout
|
||||||
|
void rainbowCycle(uint8_t wait)
|
||||||
|
{
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
for(j=0; j<256*5; j++)
|
||||||
|
{ // 5 cycles of all colors on wheel
|
||||||
|
for(i=0; i< pixels.numPixels(); i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Input a value 0 to 255 to get a color value.
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
uint32_t Wheel(byte WheelPos)
|
||||||
|
{
|
||||||
|
WheelPos = 255 - WheelPos;
|
||||||
|
if(WheelPos < 85)
|
||||||
|
{
|
||||||
|
return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
|
||||||
|
}
|
||||||
|
if(WheelPos < 170)
|
||||||
|
{
|
||||||
|
WheelPos -= 85;
|
||||||
|
return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
|
||||||
|
}
|
||||||
|
WheelPos -= 170;
|
||||||
|
return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
|
||||||
|
}
|
||||||
84
Firmware Code/KICKER_V2/oled.ino
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||||
|
#include <SSD1306Wire.h> // legacy include: `#include "SSD1306.h"
|
||||||
|
|
||||||
|
// Display Instance
|
||||||
|
SSD1306Wire display(0x3c, 21, 22);
|
||||||
|
|
||||||
|
void oled_init() {
|
||||||
|
display.init();
|
||||||
|
display.flipScreenVertically();
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.clear();
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawTextFlowDemo(String Text) {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.drawStringMaxWidth(0, 0, 128, Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawTextAlignmentDemo() {
|
||||||
|
// Text alignment demo
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
|
||||||
|
// The coordinates define the left starting point of the text
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.drawString(0, 10, "Left aligned (0,10)");
|
||||||
|
|
||||||
|
// The coordinates define the center of the text
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display.drawString(64, 22, "Center aligned (64,22)");
|
||||||
|
|
||||||
|
// The coordinates define the right end of the text
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display.drawString(128, 33, "Right aligned (128,33)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawRectDemo() {
|
||||||
|
// Draw a pixel at given position
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
display.setPixel(i, i);
|
||||||
|
display.setPixel(10 - i, i);
|
||||||
|
}
|
||||||
|
display.drawRect(12, 12, 20, 20);
|
||||||
|
|
||||||
|
// Fill the rectangle
|
||||||
|
display.fillRect(14, 14, 17, 17);
|
||||||
|
|
||||||
|
// Draw a line horizontally
|
||||||
|
display.drawHorizontalLine(0, 40, 20);
|
||||||
|
|
||||||
|
// Draw a line horizontally
|
||||||
|
display.drawVerticalLine(40, 0, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawCircleDemo() {
|
||||||
|
for (int i=1; i < 8; i++) {
|
||||||
|
display.setColor(WHITE);
|
||||||
|
display.drawCircle(32, 32, i*3);
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
display.setColor(BLACK);
|
||||||
|
}
|
||||||
|
display.fillCircle(96, 32, 32 - i* 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawProgressBarDemo(int Value) {
|
||||||
|
int progress = Value;
|
||||||
|
// draw the progress bar
|
||||||
|
display.drawProgressBar(0, 50, 120, 10, progress);
|
||||||
|
|
||||||
|
// draw the percentage as String
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display.drawString(64, 35, String(progress) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
void oled_clear() {
|
||||||
|
display.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void oled_show() {
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
40
Firmware Code/KICKER_V2R2/COMM.ino
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
//======================================================
|
||||||
|
// COMMUNICATION PORTS FUNCTIONS
|
||||||
|
//======================================================
|
||||||
|
// TERMINAL WINDOW - NATIVE USB
|
||||||
|
//------------------------------------------------------
|
||||||
|
void terminal(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Terminal.print(msg);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLUETOOTH WINDOW - NATIVE
|
||||||
|
//------------------------------------------------------
|
||||||
|
void bluetooth(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Bluetooth.print(msg);
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLUETOOTH CONNECTION STATUS
|
||||||
|
//------------------------------------------------------
|
||||||
|
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||||
|
{
|
||||||
|
if(event == ESP_SPP_SRV_OPEN_EVT) {
|
||||||
|
BLUETOOTH_STATUS = true;
|
||||||
|
terminal(BLUETOOTH_CONNECTED);
|
||||||
|
}
|
||||||
|
if(event == ESP_SPP_CLOSE_EVT ) {
|
||||||
|
BLUETOOTH_STATUS = false;
|
||||||
|
terminal(BLUETOOTH_DISCONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// TERMINAL & BLUETOOTH WINDOW - NATIVE
|
||||||
|
//------------------------------------------------------
|
||||||
|
void dualcomm(String msg)
|
||||||
|
{
|
||||||
|
terminal(msg);
|
||||||
|
bluetooth(msg);
|
||||||
|
}
|
||||||
22
Firmware Code/KICKER_V2R2/FUNC.ino
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//======================================================
|
||||||
|
// THIS PAGE IS FOR GENERAL FUNCTIONS AND METHODES
|
||||||
|
//======================================================
|
||||||
|
// Floting Point Mapping
|
||||||
|
//------------------------------------------------------
|
||||||
|
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
|
||||||
|
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// MONITOR THE CENTER BUTTON RELEASE STATE
|
||||||
|
//------------------------------------------------------
|
||||||
|
void DETECT_LONG_PRESS() {
|
||||||
|
// Resetting The Timer For Long Press
|
||||||
|
POWER_PRESS.Reset();
|
||||||
|
|
||||||
|
// Loop If the Person Didnt Release The Button
|
||||||
|
while(!BTN_CENTER.released()) {
|
||||||
|
if(POWER_PRESS.Trigger()) {
|
||||||
|
OLED_POWERING_DOWN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
196
Firmware Code/KICKER_V2R2/GCNT.ino
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN COUNTER GAME LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : game_counter_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : game_counter_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// THIS IS THE STAND ALONE CALL FOR THE GAME
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_counter_standalone()
|
||||||
|
{
|
||||||
|
// Instantiate eeprom objects with parameter/argument names and sizes
|
||||||
|
EEPROMClass game_counter_limit("eeprom0", 0x500);
|
||||||
|
EEPROMClass game_counter_limit_enable("eeprom1", 0x200);
|
||||||
|
EEPROMClass game_counter_result("eeprom2", 0x100);
|
||||||
|
|
||||||
|
if(!game_counter_limit.begin(game_counter_limit.length())) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!game_counter_limit_enable.begin(game_counter_limit_enable.length())) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!game_counter_result.begin(game_counter_result.length())) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables Of The Game
|
||||||
|
uint16_t limit = 0;
|
||||||
|
bool limitEnable = 0;
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_counter(limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// THIS IS THE BLUETOOTH CALL FOR THE GAME
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* --------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* ct : count
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* WHAT JSON TO BE COLLECTED :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
|
||||||
|
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* No calculation required, Its directly the count
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_counter_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_counter(limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER JSON JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_counter(uint16_t limit, bool limitEnable)
|
||||||
|
{
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// Game Start Lights
|
||||||
|
//LED_SIGNAL_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
//LED_SIGNAL_END();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
//LED_SIGNAL_RESET();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebration
|
||||||
|
//LED_SIGNAL_CELEBRATION();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Impact
|
||||||
|
if(PIEZO_MAP >= VTH)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
GAME_COUNTER_DISPLAY(counter);
|
||||||
|
dualcomm(counter_JSON_json(counter, timeStamp));
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER JSON -> To Send Back To Mobile
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String counter_JSON_json(unsigned int ct, unsigned int st)
|
||||||
|
{
|
||||||
|
// Convert Int To Float
|
||||||
|
float stamp = st;
|
||||||
|
stamp /= 1000;
|
||||||
|
|
||||||
|
// Assignning JSONset
|
||||||
|
JSON["ct"] = ct;
|
||||||
|
JSON["st"] = String(stamp, 3).toFloat();
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
273
Firmware Code/KICKER_V2R2/GREA.ino
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
//======================================================
|
||||||
|
// REACTION GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : game_reaction_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : game_reaction_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Game Reaction DataType
|
||||||
|
struct grdt {
|
||||||
|
uint8_t trials = 0; // Number Of Strike Trials
|
||||||
|
uint8_t minDelay = 0; // Minimum Seconds Delay Between Signals
|
||||||
|
uint8_t maxDelay = 0; // Maximum Seconds Delay Between Signals
|
||||||
|
};
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Stand Alone Buttons
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_reaction_standalone()
|
||||||
|
{
|
||||||
|
// Variables
|
||||||
|
uint8_t minDelay = 0;
|
||||||
|
uint8_t maxDelay = 0;
|
||||||
|
uint8_t trials = 0;
|
||||||
|
|
||||||
|
// Display Screen Menu And Button Actions
|
||||||
|
// If The Menu Number 1 -> We Set The Value Of Min Delay
|
||||||
|
// If The Menu Number 2 -> We Set The Value Of Max Delay
|
||||||
|
// If The Menu Number 3 -> We Set The Number Of Trials
|
||||||
|
|
||||||
|
// Call the Game Play
|
||||||
|
play_reaction(minDelay, maxDelay, trials);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Bluetooth Via JSON
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* REACTION GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tr": 10, "mn": 1, "mx": 2}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* tr : trials pre counter
|
||||||
|
* mn : minimum delay, between trials
|
||||||
|
* mx : maximum delay, between trials
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tr" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_reaction_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings);
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint8_t minDelay = JSON["mn"];
|
||||||
|
uint8_t maxDelay = JSON["mx"];
|
||||||
|
uint16_t trials = JSON["lm"];
|
||||||
|
|
||||||
|
// Fix Random Error
|
||||||
|
maxDelay += 1;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
play_reaction(minDelay, maxDelay, trials);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Play The Game
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
|
||||||
|
{
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t temp = trials;
|
||||||
|
|
||||||
|
// Fix Random Error
|
||||||
|
maxDelay += 1;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// DisJSON Welcome Message
|
||||||
|
terminal("");
|
||||||
|
terminal("trials : " + String(trials) + " Strikes");
|
||||||
|
terminal("minDelay : " + String(minDelay) + " Seconds");
|
||||||
|
terminal("maxDelay : " + String(maxDelay) + " Seconds");
|
||||||
|
terminal("2 Seconds To Start Get Ready & Good Luck !!");
|
||||||
|
terminal("");
|
||||||
|
|
||||||
|
// Main Variables
|
||||||
|
uint16_t sdelay = 0;
|
||||||
|
uint16_t power = 0;
|
||||||
|
uint16_t response = 0;
|
||||||
|
unsigned long startTime = 0;
|
||||||
|
unsigned long stopTime = 0;
|
||||||
|
|
||||||
|
// Ready Signal
|
||||||
|
//LED_SIGNAL_REACTION_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// Processing Results
|
||||||
|
for(int i=0; i<trials; i++)
|
||||||
|
{
|
||||||
|
// Reading Kick JSON
|
||||||
|
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
|
||||||
|
terminal(" -> Get Ready !!");
|
||||||
|
|
||||||
|
// Set Random Delay Time
|
||||||
|
sdelay = random(minDelay, maxDelay);
|
||||||
|
sdelay *= 1000;
|
||||||
|
delay(sdelay);
|
||||||
|
|
||||||
|
// Light Up Green
|
||||||
|
//LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
|
||||||
|
// Start Timer
|
||||||
|
startTime = millis();
|
||||||
|
|
||||||
|
// Sensing Strike Power
|
||||||
|
while(power < VTH)
|
||||||
|
{
|
||||||
|
// Reading The Strike
|
||||||
|
power = PIEZO_MAP;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP) {
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
//LED_SIGNAL_END();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET) {
|
||||||
|
//LED_SIGNAL_REACTION_RESET();
|
||||||
|
trials = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop Timer
|
||||||
|
stopTime = millis();
|
||||||
|
|
||||||
|
// Stop Light
|
||||||
|
//LED_SET_COLOR(255, 0, 0, 255);
|
||||||
|
|
||||||
|
// Calculating Response Time
|
||||||
|
response = stopTime - startTime - 1;
|
||||||
|
|
||||||
|
// Create Json JSON
|
||||||
|
String msg = reaction_JSON_json(i+1, power, response, sdelay);
|
||||||
|
|
||||||
|
// Print To Terminal
|
||||||
|
dualcomm(msg);
|
||||||
|
|
||||||
|
// Clear All
|
||||||
|
sdelay = 0;
|
||||||
|
power = 0;
|
||||||
|
response = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red Light Delay
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
|
||||||
|
// Blink Red
|
||||||
|
//LED_SIGNAL_CELEBRATION();
|
||||||
|
|
||||||
|
// Return To Game Selector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION JSON -> To Send Back To Mobile Device
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
|
||||||
|
{
|
||||||
|
// Convert To Seconds Unit
|
||||||
|
float re = response;
|
||||||
|
re /= 1000;
|
||||||
|
|
||||||
|
// Asignning Values
|
||||||
|
JSON["ct"] = count; // Strike Number
|
||||||
|
JSON["pw"] = power; // Strike Power In Analog Read
|
||||||
|
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
|
||||||
|
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_REACTION_START()
|
||||||
|
{
|
||||||
|
// Cross fade the white signal to get ready
|
||||||
|
//LED_CROSS_FADE(255, 255, 255, 3);
|
||||||
|
|
||||||
|
// Set the LED strip color to red
|
||||||
|
//LED_SET_COLOR(255, 0, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_REACTION_RESET()
|
||||||
|
{
|
||||||
|
// Light Bright Blue
|
||||||
|
//LED_BLINK(0, 0, 255, 2);
|
||||||
|
|
||||||
|
// Wait For 1/4 Second
|
||||||
|
//delay(250);
|
||||||
|
|
||||||
|
// Fade Out The Blue
|
||||||
|
//LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
103
Firmware Code/KICKER_V2R2/GSEL.ino
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* game selector is the main function that tell the game groutine
|
||||||
|
* which game to be JSONed and at what parameters
|
||||||
|
*/
|
||||||
|
|
||||||
|
void bluetooth_game_selector(String game, String settings)
|
||||||
|
{
|
||||||
|
// Kick Counter Game
|
||||||
|
if(game == "ct") {
|
||||||
|
terminal(GM_COUNTER);
|
||||||
|
game_counter_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ta") {
|
||||||
|
terminal(GM_TATTACK);
|
||||||
|
time_attack_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ra") {
|
||||||
|
terminal(GM_REACTION);
|
||||||
|
game_reaction_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown Game
|
||||||
|
else {
|
||||||
|
dualcomm(UNKNOWN_GAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//======================================================
|
||||||
|
// GAME SELECTOR CODE
|
||||||
|
//======================================================
|
||||||
|
// SELECTOR ROUTINE
|
||||||
|
//------------------------------------------------------
|
||||||
|
void standalone_game_selector()
|
||||||
|
{
|
||||||
|
// Check Bluetooth
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
// Reading The Message From Bluetooth
|
||||||
|
String message = Bluetooth.readStringUntil('\n');
|
||||||
|
// Cleaning Bluetooth Receive Buffer
|
||||||
|
flushBluetooth;
|
||||||
|
// Cleaning The Message
|
||||||
|
message.trim();
|
||||||
|
// Cleaning JSON Document
|
||||||
|
JSON.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// DISPLAY MENU TITLE FUNCTION
|
||||||
|
//------------------------------------------------------
|
||||||
|
void GAME_TITLE_DISPLAY(uint8_t Number, String Title)
|
||||||
|
{
|
||||||
|
// Starting The First Code
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 5, 1, "MODE " + String(Number + 1));
|
||||||
|
drawTextCenter(128/2, 22, 2, " - " + Title + " - ");
|
||||||
|
drawTextCenter(128/2, 43, 1, "<< SELECT >>");
|
||||||
|
OLED_SHOW();
|
||||||
|
DISPLAY_CHANGED = true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED DISPLAY - GAME COUNTER
|
||||||
|
//------------------------------------------------------
|
||||||
|
void GAME_COUNTER_DISPLAY(uint16_t count)
|
||||||
|
{
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
OLED_SHOW();
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED DISPLAY - GAME TIMEATTACK
|
||||||
|
//------------------------------------------------------
|
||||||
|
void GAME_TIMEATTACK_DISPLAY(uint16_t count)
|
||||||
|
{
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
OLED_SHOW();
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED DISPLAY - GAME REACTION
|
||||||
|
//------------------------------------------------------
|
||||||
|
void GAME_REACTION_DISPLAY(uint16_t count)
|
||||||
|
{
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
OLED_SHOW();
|
||||||
|
}
|
||||||
239
Firmware Code/KICKER_V2R2/GTAT.ino
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
//======================================================
|
||||||
|
// TIME ATTACK GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : time_attack_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : time_attack_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Game Time Attack DataType
|
||||||
|
struct gtdt {
|
||||||
|
uint16_t time = 30; // Max Time Of The Game In Sec
|
||||||
|
uint16_t limit = 0; // Max Kick Count
|
||||||
|
bool limit_ena = false; // Enable End Game If Max Kicks Meet
|
||||||
|
float kicksPerSecond = 0; // Game Time Attack Result
|
||||||
|
};
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Stand Alone Buttons
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void time_attack_standalone()
|
||||||
|
{
|
||||||
|
// Variables
|
||||||
|
uint16_t time = 0;
|
||||||
|
uint16_t timer = 0;
|
||||||
|
uint16_t limit = 0;
|
||||||
|
bool limitEnable = 0;
|
||||||
|
|
||||||
|
// Display Screen Menu And Button Actions
|
||||||
|
// If The Menu Number 1 -> We Set The Value Of Min Delay
|
||||||
|
// If The Menu Number 2 -> We Set The Value Of Max Delay
|
||||||
|
// If The Menu Number 3 -> We Set The Number Of Trials
|
||||||
|
|
||||||
|
// Call the Game Play
|
||||||
|
game_timeAttack(time, timer, limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Bluetooth Via JSON
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tm": 10, "le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* tm : count down timer starting value
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tm" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
|
||||||
|
*
|
||||||
|
* RETURNNING JSON FORMAT :
|
||||||
|
* ------------------------
|
||||||
|
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
|
||||||
|
*
|
||||||
|
* tm : timer count in Sec
|
||||||
|
* ct : strike counter (number of kicks)
|
||||||
|
* dl : delay between strikes
|
||||||
|
* st : time stampe of the strike in milli Seconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
void time_attack_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t time = JSON["tm"]; // Time Window To JSON
|
||||||
|
uint16_t timer = time;
|
||||||
|
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_timeAttack(time, timer, limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Play Time Atack Game
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_timeAttack(uint16_t time, uint16_t timer, uint16_t limit, bool limitEnable)
|
||||||
|
{
|
||||||
|
// Building Timers 1000mSec -> 1Sec
|
||||||
|
TimeTrigger sec_tick(1000);
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// Start LED Signal
|
||||||
|
//LED_SIGNAL_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// Send Initial DisJSON
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
// store the time of the previous kick
|
||||||
|
unsigned long lastStamp = 0;
|
||||||
|
|
||||||
|
// reseting time ticker
|
||||||
|
sec_tick.Reset();
|
||||||
|
|
||||||
|
// While The Game Is Still On
|
||||||
|
while(timer != 0)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
//LED_SIGNAL_END();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
timer = time;
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
sec_tick.Reset();
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
//LED_SIGNAL_RESET();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Kick ---------------------------->>>
|
||||||
|
if(PIEZO_MAP > VTH)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Second ---------------------------->>>
|
||||||
|
if(sec_tick.Trigger())
|
||||||
|
{
|
||||||
|
timer--;
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebrate
|
||||||
|
//LED_SIGNAL_CELEBRATION();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send End Game Signal To Smart Phone
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
//LED_FADEIN(255, 0, 0); // RED Color
|
||||||
|
delay(2000); // Delay 2000
|
||||||
|
//LED_CLEAR(); // CLEAR OFF
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// TIME ATTACK KICK JSON -> To Send Back To Mobile
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
JSON["tm"] = RunningTime;
|
||||||
|
JSON["ct"] = KickCount;
|
||||||
|
|
||||||
|
// Calculations
|
||||||
|
if(TimeStamp > 0)
|
||||||
|
{
|
||||||
|
// Calculate Time Stamp In Seconds
|
||||||
|
float st = TimeStamp;
|
||||||
|
st /= 1000;
|
||||||
|
JSON["st"] = String(st, 3).toFloat();
|
||||||
|
|
||||||
|
// Calculate Strike Delay In Seconds
|
||||||
|
float dl = TimeStamp - LastStamp;
|
||||||
|
dl /= 1000;
|
||||||
|
JSON["dl"] = String(dl, 3).toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
305
Firmware Code/KICKER_V2R2/KICKER_V2R2.ino
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
/* ===============================================
|
||||||
|
* - THIS IS TAKEONE ESP32 BOARD -
|
||||||
|
* ===============================================
|
||||||
|
* MPU9250 Address : 0X69 (ADDRESS)
|
||||||
|
* OLED 128x64 Address : 0X3C (ADDRESS)
|
||||||
|
* -----------------------------------------------
|
||||||
|
* Description : PIN GPIO#
|
||||||
|
* -----------------------------------------------
|
||||||
|
* NEOPIXEL LED STRIP : A0/GPIO 26
|
||||||
|
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
|
||||||
|
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
|
||||||
|
* BUTTONS : TLB (35), BLB (15), CB (33), BRB (27), TRB(12)
|
||||||
|
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
|
||||||
|
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
|
||||||
|
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
|
||||||
|
* LED PIN : 13 (DIGITAL)
|
||||||
|
* BATTERY MONITOR PIN : 35 (ANALOG)
|
||||||
|
* -----------------------------------------------
|
||||||
|
* BUTTONS PINOUTS : PIN GPIO
|
||||||
|
* -----------------------------------------------
|
||||||
|
* TOP LEFT BUTTON : 15 - SWITCH PREVIOUS MENU / CHANGE PARAMETER
|
||||||
|
* TOP RIGHT BUTTON : 12 - SWITCH NEXT MENU / CHANGE PARAMETER
|
||||||
|
* BOTTOM LEFT BUTTON : 32 - POWER INC & BACK & INC PARAMETER
|
||||||
|
* BOTTOM RIGHT BUTTON : 27 - POWER DEC & SAVE & DEC PARAMETER
|
||||||
|
* CENTER BUTTON : 33 - POWER ON & SELECT
|
||||||
|
* -----------------------------------------------
|
||||||
|
* Exclusive Features Of TAKEONE BOARD
|
||||||
|
* -----------------------------------------------
|
||||||
|
* ESP32 TAKEONE Board has some unique hardware features
|
||||||
|
* 1. Battery Voltage Level Monitoring Via Analog Pin 35
|
||||||
|
* 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery
|
||||||
|
* 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom
|
||||||
|
* 4. SPI : SDCARD Reader */
|
||||||
|
//======================================================
|
||||||
|
// LIBRARIES
|
||||||
|
//======================================================
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <EEPROM.h>
|
||||||
|
#include <Button.h>
|
||||||
|
#include <TimeTrigger.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <NeoPixelBus.h>
|
||||||
|
#include <BluetoothSerial.h>
|
||||||
|
//======================================================
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
//======================================================
|
||||||
|
uint8_t MENU_COUNT = 0;
|
||||||
|
bool BLUETOOTH_STATUS = false;
|
||||||
|
bool CHARGE_STATE = false;
|
||||||
|
bool DISPLAY_CHANGED = false;
|
||||||
|
//======================================================
|
||||||
|
// HARDWARE DEFINITIONS
|
||||||
|
//======================================================
|
||||||
|
// Nessesary Definition For Bluetooth Library
|
||||||
|
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||||
|
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||||
|
#endif
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Serial Terminal
|
||||||
|
//------------------------------------------------------
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
|
||||||
|
#define flushTerminal while(isTerminal) { Terminal.read(); }
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Bluetooth Terminal
|
||||||
|
//------------------------------------------------------
|
||||||
|
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
|
||||||
|
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
|
||||||
|
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Buttons
|
||||||
|
//------------------------------------------------------
|
||||||
|
Button BTN_PREVIOUS(15); // TL : 15 - SWITCH PREVIOUS MENU / CHANGE PARAMETER
|
||||||
|
Button BTN_NEXT(12); // TR : 12 - SWITCH NEXT MENU / CHANGE PARAMETER
|
||||||
|
Button BTN_CENTER(33); // CT : 33 - POWER INC & BACK & INC PARAMETER
|
||||||
|
Button BTN_INCREASE(32); // BL : 32 - POWER DEC & SAVE & DEC PARAMETER
|
||||||
|
Button BTN_DECREASE(27); // BR : 27 - POWER ON & SELECT
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Boost 3V3 To 5V
|
||||||
|
//------------------------------------------------------
|
||||||
|
#define BOOST_PIN 14
|
||||||
|
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
|
||||||
|
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
|
||||||
|
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
|
||||||
|
#define BOOST_STU digitalRead(BOOST_PIN)
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Keep Power On
|
||||||
|
//------------------------------------------------------
|
||||||
|
#define POWER_PIN 13
|
||||||
|
#define POWER_SETUP pinMode(POWER_PIN, OUTPUT)
|
||||||
|
#define POWER_OFF digitalWrite(POWER_PIN, LOW)
|
||||||
|
#define POWER_ON digitalWrite(POWER_PIN, HIGH)
|
||||||
|
TimeTrigger POWER_PRESS(4000); // The Interval In mSeconds
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Piezo Transducer
|
||||||
|
//------------------------------------------------------
|
||||||
|
#define VTH 5 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define PIEZO_PIN 34 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE 39 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
#define PIEZO_READ analogRead(PIEZO_PIN)
|
||||||
|
#define PIEZO_MAP map(PIEZO_READ, VTH, 4095, 0, 100)
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Battery Level Monitoring
|
||||||
|
//------------------------------------------------------
|
||||||
|
#define BATTERY_PIN 35
|
||||||
|
#define BATTERY (float)(((analogRead(BATTERY_PIN) * (3.3 / 4096)) * 2) + 0.31)
|
||||||
|
#define CHARGE round(mapf(BATTERY, 3.27, 4.31, 0, 100), 1)
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Power Charging Status
|
||||||
|
//------------------------------------------------------
|
||||||
|
#define STAT_PIN 25
|
||||||
|
#define STAT_SETUP pinMode(STAT_PIN, INPUT)
|
||||||
|
#define STAT_READ digitalRead(STAT_PIN)
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Neo Pixel LED Strip
|
||||||
|
//------------------------------------------------------
|
||||||
|
#define PIXEL_COUNT 21 // make sure to set this to the number of pixels in your strip
|
||||||
|
#define PIXEL_PIN 26 // make sure to set this to the correct pin, ignored for Esp8266
|
||||||
|
// three element pixels, in different order and speeds
|
||||||
|
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> PIXEL_STRIP(PIXEL_COUNT, PIXEL_PIN);
|
||||||
|
//------------------------------------------------------
|
||||||
|
// JSON Object & Memory
|
||||||
|
//------------------------------------------------------
|
||||||
|
#define CAPACITY 200
|
||||||
|
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||||
|
// FIXED OPERATION MODE MESSAGES ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
#define BLUETOOTH_START "{\"status\":\"BLUETOOTH STARTED\"}"
|
||||||
|
#define BLUETOOTH_FAIL "{\"status\":\"BLUETOOTH FAILED\"}"
|
||||||
|
#define BLUETOOTH_CONNECTED "{\"status\":\"BLUETOOTH CONNECTED\"}"
|
||||||
|
#define BLUETOOTH_DISCONNECTED "{\"status\":\"BLUETOOTH DISCONNECTED\"}"
|
||||||
|
#define STAND_ALONE_MODE "{\"status\":\"STAND ALONE MODE\"}"
|
||||||
|
// FIXED MESSAGES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
#define POWERUP "{\"status\":\"POWER UP\"}"
|
||||||
|
#define POWEROFF "{\"status\":\"POWER OFF\"}"
|
||||||
|
#define UNDERSTOOD "{\"status\":\"OK\"}"
|
||||||
|
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
|
||||||
|
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
|
||||||
|
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
|
||||||
|
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
|
||||||
|
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
|
||||||
|
// GAME NAMES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
|
||||||
|
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
|
||||||
|
#define GM_REACTION "{\"gm\":\"REACTION\"}"
|
||||||
|
#define GM_DECISION "{\"gm\":\"DECISION\"}"
|
||||||
|
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
|
||||||
|
// COMMAND LIST ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
#define CM_START "{\"cm\":\"START\"}"
|
||||||
|
#define CM_RESET "{\"cm\":\"RESET\"}"
|
||||||
|
#define CM_STOP "{\"cm\":\"STOP\"}"
|
||||||
|
#define CM_EXIT "{\"cm\":\"EXIT\"}"
|
||||||
|
//======================================================
|
||||||
|
// MAIN SETUP
|
||||||
|
//======================================================
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Power Hold
|
||||||
|
POWER_SETUP;
|
||||||
|
POWER_ON;
|
||||||
|
|
||||||
|
// Turn On Booster
|
||||||
|
BOOST_SETUP;
|
||||||
|
BOOST_OFF;
|
||||||
|
|
||||||
|
// Charging Status Pin
|
||||||
|
STAT_SETUP;
|
||||||
|
|
||||||
|
// I2C Module & OLED
|
||||||
|
Wire.begin();
|
||||||
|
delay(5);
|
||||||
|
OLED_INIT();
|
||||||
|
OLED_CLEAR();
|
||||||
|
OLED_SHOW();
|
||||||
|
|
||||||
|
// Start Buttons Function
|
||||||
|
BTN_PREVIOUS.begin();
|
||||||
|
BTN_NEXT.begin();
|
||||||
|
BTN_CENTER.begin();
|
||||||
|
BTN_INCREASE.begin();
|
||||||
|
BTN_DECREASE.begin();
|
||||||
|
|
||||||
|
// Communication Ports
|
||||||
|
Terminal.begin(9600); Terminal.println();
|
||||||
|
|
||||||
|
// To Detect Connection / Disconnection Event
|
||||||
|
Bluetooth.register_callback(callback);
|
||||||
|
|
||||||
|
// Starting Bluetooth Wireless With Name (KICKER)
|
||||||
|
if(!Bluetooth.begin("KICKER")) {
|
||||||
|
terminal(POWERUP);
|
||||||
|
terminal(BLUETOOTH_FAIL);
|
||||||
|
} else {
|
||||||
|
dualcomm(POWERUP);
|
||||||
|
dualcomm(BLUETOOTH_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Random Number Source
|
||||||
|
randomSeed(analogRead(RANDOM_SOURCE));
|
||||||
|
|
||||||
|
// Display Welcome Screen
|
||||||
|
KICKER_LOGO();
|
||||||
|
delay(2000);
|
||||||
|
}
|
||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// This Is For Bluetooth Mode
|
||||||
|
if(BLUETOOTH_STATUS == true) {
|
||||||
|
OLED_BLUETOOTH_MODE();
|
||||||
|
while(BLUETOOTH_STATUS == true) {
|
||||||
|
ListenToBluetooth(); // Reading Only From Bluetooth
|
||||||
|
}
|
||||||
|
OLED_BLUETOOTH_MODE();
|
||||||
|
delay(1000);
|
||||||
|
terminal(STAND_ALONE_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This Is For Stand Alone Mode
|
||||||
|
else {
|
||||||
|
OLED_STANDALONE_MODE();
|
||||||
|
while(BLUETOOTH_STATUS == false) {
|
||||||
|
ListenToStandAlone();
|
||||||
|
}
|
||||||
|
OLED_BLUETOOTH_MODE();
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// LISTEN TO BLUETOOTH
|
||||||
|
//------------------------------------------------------
|
||||||
|
void ListenToBluetooth()
|
||||||
|
{
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
// Reading Message From Bluetooth
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
|
||||||
|
// Display On Serial Monitor For Debuging
|
||||||
|
terminal(msg);
|
||||||
|
|
||||||
|
// If It Was A Command To Power OFf
|
||||||
|
if(msg == POWEROFF) {
|
||||||
|
OLED_POWERING_DOWN();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, msg);
|
||||||
|
|
||||||
|
// If The System Understood The Message Clearly
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
// Sending Status Message
|
||||||
|
dualcomm(UNDERSTOOD);
|
||||||
|
|
||||||
|
// Reading Game Name & Settings
|
||||||
|
String game = JSON["gm"];
|
||||||
|
String settings = JSON["set"];
|
||||||
|
|
||||||
|
// Clearing JSON Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Entering To Game Selector
|
||||||
|
bluetooth_game_selector(game, settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal(JSON_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//------------------------------------------------------
|
||||||
|
// LISTEN TO STAND ALONE
|
||||||
|
//------------------------------------------------------
|
||||||
|
void ListenToStandAlone()
|
||||||
|
{
|
||||||
|
// SHIFT TO PREVIOUS GAME MENU
|
||||||
|
if(BTN_PREVIOUS.pressed())
|
||||||
|
{
|
||||||
|
DISPLAY_CHANGED = false;
|
||||||
|
MENU_COUNT-=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SHIFT TO NEXT GAME MENU
|
||||||
|
else if(BTN_NEXT.pressed())
|
||||||
|
{
|
||||||
|
MENU_COUNT+=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SELECT CURRENT DISPLAYED MENU
|
||||||
|
else if(BTN_CENTER.pressed())
|
||||||
|
{
|
||||||
|
DETECT_LONG_PRESS(); // IF LONG PRESS POWER OFF
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(MENU_COUNT) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
else :
|
||||||
|
}
|
||||||
|
}
|
||||||
295
Firmware Code/KICKER_V2R2/NPXL.ino
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
////======================================================
|
||||||
|
//// NEO PIXEL LED STRIP
|
||||||
|
////======================================================
|
||||||
|
//// PUBLIC DEFINITIONS
|
||||||
|
////------------------------------------------------------
|
||||||
|
// #define BETWEEN_FADE 15
|
||||||
|
// #define FADE_RATE 15
|
||||||
|
// #define BLINK_RATE 250
|
||||||
|
// #define ColorSaturation 128
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// PURE COLOR
|
||||||
|
////------------------------------------------------------
|
||||||
|
// RgbColor red(colorSaturation, 0, 0);
|
||||||
|
// RgbColor green(0, colorSaturation, 0);
|
||||||
|
// RgbColor blue(0, 0, colorSaturation);
|
||||||
|
// RgbColor white(colorSaturation);
|
||||||
|
// RgbColor black(0);
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// HSL COLOR
|
||||||
|
////------------------------------------------------------
|
||||||
|
// HslColor hslRed(red);
|
||||||
|
// HslColor hslGreen(green);
|
||||||
|
// HslColor hslBlue(blue);
|
||||||
|
// HslColor hslWhite(white);
|
||||||
|
// HslColor hslBlack(black);
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// Clearing The LED Strip
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_CLEAR()
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Clear The Strip Color
|
||||||
|
// PIXEL_STRIP.clear();
|
||||||
|
//
|
||||||
|
// // Show On LED Strip
|
||||||
|
// LED_SHOW();
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// DISPLAY ON STRIP
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_SHOW()
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Pass It To The LED Strip
|
||||||
|
// PIXEL_STRIP.show();
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// Set LED Brightness
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_SET_BRIGHTNESS(uint8_t Value)
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Set The Brightness
|
||||||
|
// PIXEL_STRIP.setBrightness(Value);
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// Set LED Color
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Set Intensity
|
||||||
|
// LED_SET_BRIGHTNESS(Intensity);
|
||||||
|
//
|
||||||
|
// // Loop
|
||||||
|
// for(int i=0; i<NUM_PIXELS; i++) {
|
||||||
|
// PIXEL_STRIP.setPixelColor(i, PIXEL_STRIP.Color(R, G, B));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Show The Colors On LED Strip
|
||||||
|
// LED_SHOW();
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// BLINK
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
|
||||||
|
// {
|
||||||
|
// for(int i=0; i<Times; i++)
|
||||||
|
// {
|
||||||
|
// LED_SET_COLOR(R, G, B, 255);
|
||||||
|
// delay(BLINK_RATE);
|
||||||
|
// LED_CLEAR();
|
||||||
|
// delay(BLINK_RATE);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// COLOR WHIPE
|
||||||
|
////------------------------------------------------------
|
||||||
|
// // Fill the dots one after the other with a color
|
||||||
|
// void LED_COLOR_WIPE(uint32_t c, uint8_t wait)
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Work Loop
|
||||||
|
// for(uint16_t i=0; i<NUM_PIXELS; i++)
|
||||||
|
// {
|
||||||
|
// PIXEL_STRIP.setPixelColor(i, c);
|
||||||
|
// LED_SHOW();
|
||||||
|
// delay(wait);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// END GAME LIGHTING SIGNAL
|
||||||
|
////------------------------------------------------------
|
||||||
|
// // Slightly different, this makes the rainbow equally distributed throughout
|
||||||
|
// void LED_RAINBOW_CYCLE(uint8_t wait)
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Loop Variables
|
||||||
|
// uint16_t i, j;
|
||||||
|
//
|
||||||
|
// // The Loop
|
||||||
|
// for(j=0; j<256*5; j++)
|
||||||
|
// {
|
||||||
|
// // 5 cycles of all colors on WHEEL
|
||||||
|
// for(i=0; i< PIXEL_STRIP.numPixels(); i++)
|
||||||
|
// {
|
||||||
|
// PIXEL_STRIP.setPixelColor(i, LED_COLOR_WHEEL(((i * 256 / PIXEL_STRIP.numPixels()) + j) & 255));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// LED_SHOW();
|
||||||
|
// delay(wait);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// END GAME LIGHTING SIGNAL
|
||||||
|
////------------------------------------------------------
|
||||||
|
// // Input a value 0 to 255 to get a color value.
|
||||||
|
// // The colours are a transition r - g - b - back to r.
|
||||||
|
// uint32_t LED_COLOR_WHEEL(byte WHEELPos)
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Wheel Sequance
|
||||||
|
// WHEELPos = 255 - WHEELPos;
|
||||||
|
//
|
||||||
|
// if(WHEELPos < 85)
|
||||||
|
// {
|
||||||
|
// return PIXEL_STRIP.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
|
||||||
|
// }
|
||||||
|
// if(WHEELPos < 170)
|
||||||
|
// {
|
||||||
|
// WHEELPos -= 85;
|
||||||
|
// return PIXEL_STRIP.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
|
||||||
|
// }
|
||||||
|
// WHEELPos -= 170;
|
||||||
|
// return PIXEL_STRIP.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// Set Color Fade In
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Loop For Fade
|
||||||
|
// for(int i=0; i<=255; i++)
|
||||||
|
// {
|
||||||
|
// PIXEL_STRIP.setBrightness(i);
|
||||||
|
// for(int j=0; j<NUM_PIXELS; j++)
|
||||||
|
// {
|
||||||
|
// PIXEL_STRIP.setPixelColor(j, PIXEL_STRIP.Color(R, G, B));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// LED_SHOW();
|
||||||
|
// delay(4);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// Set Color Fade Out
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// // Loop For Fade Out
|
||||||
|
// for(int i=255; i>=0; i--)
|
||||||
|
// {
|
||||||
|
// PIXEL_STRIP.setBrightness(i);
|
||||||
|
// for(int j=0; j<NUM_PIXELS; j++)
|
||||||
|
// {
|
||||||
|
// PIXEL_STRIP.setPixelColor(j, PIXEL_STRIP.Color(R, G, B));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// LED_SHOW();
|
||||||
|
// delay(4);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// Set LED Color Cross Fade
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
|
||||||
|
// {
|
||||||
|
// // Make Sure Boost Is On
|
||||||
|
// BOOST_ON;
|
||||||
|
//
|
||||||
|
// for(int i=0; i<Times; i++)
|
||||||
|
// {
|
||||||
|
// LED_FADEIN(R, G, B);
|
||||||
|
// LED_FADEOUT(R, G, B);
|
||||||
|
// delay(BETWEEN_FADE);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// REACTION GAME START LED SIGNAL
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_SIGNAL_START()
|
||||||
|
// {
|
||||||
|
// // Cross Fade White Color To Get ready 3 Times
|
||||||
|
// LED_CROSS_FADE(255, 255, 255, 3);
|
||||||
|
//
|
||||||
|
// // Set Strip Color Green
|
||||||
|
// LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_SIGNAL_END()
|
||||||
|
// {
|
||||||
|
// // Blink Red Twice
|
||||||
|
// LED_BLINK(255, 0, 0, 2);
|
||||||
|
//
|
||||||
|
// // Fade The Red Color To Nothing
|
||||||
|
// LED_FADEOUT(255, 0, 0);
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// REACTION GAME START LED CELEBRATION
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_SIGNAL_CELEBRATION()
|
||||||
|
// {
|
||||||
|
// // Display Rainbow Twice
|
||||||
|
// LED_RAINBOW_CYCLE(2);
|
||||||
|
//
|
||||||
|
// // Grean Light OUT
|
||||||
|
// LED_FADEOUT(0, 255, 0);
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// REACTION GAME RESET LED SIGNAL
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_SIGNAL_RESET()
|
||||||
|
// {
|
||||||
|
// // Light Bright Blue
|
||||||
|
// LED_BLINK(0, 0, 255, 2);
|
||||||
|
//
|
||||||
|
// // Wait For 1/4 Second
|
||||||
|
// delay(250);
|
||||||
|
//
|
||||||
|
// // Fade Out The Blue
|
||||||
|
// LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
//
|
||||||
|
// // Set Strip Color Green
|
||||||
|
// LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// DISPLAY BAHRAIN FLAG
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_BAHRAIN_FLAG()
|
||||||
|
// {
|
||||||
|
// BOOST_ON;
|
||||||
|
// LED_SET_BRIGHTNESS(255);
|
||||||
|
// LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 255, 255), 30); // White
|
||||||
|
// delay(250);
|
||||||
|
// LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 0, 0), 30); // Red
|
||||||
|
// delay(250);
|
||||||
|
// LED_FADEOUT(255, 0, 0);
|
||||||
|
// }
|
||||||
|
////------------------------------------------------------
|
||||||
|
//// DISPLAY COLOMBIA FLAG
|
||||||
|
////------------------------------------------------------
|
||||||
|
// void LED_COLOMBIA_FLAG()
|
||||||
|
// {
|
||||||
|
// BOOST_ON;
|
||||||
|
// LED_SET_BRIGHTNESS(255);
|
||||||
|
// LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 255, 0), 30); // Yellow
|
||||||
|
// delay(250);
|
||||||
|
// LED_COLOR_WIPE(PIXEL_STRIP.Color(0, 0, 255), 30); // Blue
|
||||||
|
// delay(250);
|
||||||
|
// LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 0, 0), 30); // Red
|
||||||
|
// delay(250);
|
||||||
|
// LED_FADEOUT(255, 0, 0);
|
||||||
|
// }
|
||||||
272
Firmware Code/KICKER_V2R2/OLED.ino
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
//======================================================
|
||||||
|
// OLED DISPLAY
|
||||||
|
//======================================================
|
||||||
|
// LIBRARY INCLUDE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Include Libraries
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <SSD1306Wire.h>
|
||||||
|
|
||||||
|
// Display Instance
|
||||||
|
SSD1306Wire display(0x3c, 21, 22);
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED INITIALIZATION
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void OLED_INIT() {
|
||||||
|
display.init();
|
||||||
|
display.flipScreenVertically();
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED CLEAR DISPLAY
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void OLED_CLEAR() {
|
||||||
|
display.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED CLEAN DISPLAY
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void OLED_CLEAN() {
|
||||||
|
OLED_CLEAR();
|
||||||
|
OLED_SHOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED SHOW NEW DATA
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void OLED_SHOW() {
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED DISPLAY KICKER WELCOME MESSAGE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void KICKER_LOGO() {
|
||||||
|
// Starting The First Code
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 5, 3, "TAKEONE");
|
||||||
|
drawTextCenter(128/2, 30, 1, " - T E C H N O L O G Y - ");
|
||||||
|
drawTextCenter(128/2, 43, 2, "<< KICKER >>");
|
||||||
|
OLED_SHOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED DISPLAY KICKER POWERING OFF MESSAGE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void OLED_POWERING_DOWN() {
|
||||||
|
dualcomm(POWEROFF);
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 5, 3, "POWER");
|
||||||
|
drawTextCenter(128/2, 30, 1, "- T U R N I N G O F F -");
|
||||||
|
drawTextCenter(128/2, 43, 2, "SEE YOU AGAIN");
|
||||||
|
OLED_SHOW();
|
||||||
|
BOOST_OFF;
|
||||||
|
delay(2000);
|
||||||
|
OLED_CLEAN();
|
||||||
|
delay(250);
|
||||||
|
POWER_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED Display Text
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void drawTextFlowDemo(String Text) {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.drawStringMaxWidth(0, 0, 128, Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED LEFT TEXT Display
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void drawTextLeft() {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.drawString(0, 10, "Left aligned (0,10)");
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED CENTER TEXT Display
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void drawTextCenter(int X, int Y, int Size, String Text) {
|
||||||
|
//display.setFont(ArialMT_Plain_10);
|
||||||
|
|
||||||
|
if(Size == 1) {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
} else if(Size == 2) {
|
||||||
|
display.setFont(ArialMT_Plain_16);
|
||||||
|
} else if(Size == 3) {
|
||||||
|
display.setFont(ArialMT_Plain_24);
|
||||||
|
} else {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
}
|
||||||
|
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display.drawString(X, Y, Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED RIGHT TEXT DISPLAY
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// OLED Display
|
||||||
|
void drawTextRight() {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display.drawString(128, 33, "Right aligned (128,33)");
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED DRAW RECTANGLE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void drawRectDemo() {
|
||||||
|
// Draw a pixel at given position
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
display.setPixel(i, i);
|
||||||
|
display.setPixel(10 - i, i);
|
||||||
|
}
|
||||||
|
display.drawRect(12, 12, 20, 20);
|
||||||
|
|
||||||
|
// Fill the rectangle
|
||||||
|
display.fillRect(14, 14, 17, 17);
|
||||||
|
|
||||||
|
// Draw a line horizontally
|
||||||
|
display.drawHorizontalLine(0, 40, 20);
|
||||||
|
|
||||||
|
// Draw a line horizontally
|
||||||
|
display.drawVerticalLine(40, 0, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED DRAW CIRCLE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void drawCircleDemo() {
|
||||||
|
for (int i=1; i < 8; i++) {
|
||||||
|
display.setColor(WHITE);
|
||||||
|
display.drawCircle(32, 32, i*3);
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
display.setColor(BLACK);
|
||||||
|
}
|
||||||
|
display.fillCircle(96, 32, 32 - i* 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// OLED DRAW PROGRESS BAR
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void drawProgressBarDemo(int Value) {
|
||||||
|
int progress = Value;
|
||||||
|
// draw the progress bar
|
||||||
|
display.drawProgressBar(0, 50, 120, 10, progress);
|
||||||
|
|
||||||
|
// draw the percentage as String
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display.drawString(64, 35, String(progress) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// I2C DECIVES SCANNER
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void scanI2C()
|
||||||
|
{
|
||||||
|
byte error, address;
|
||||||
|
int nDevices;
|
||||||
|
|
||||||
|
Serial.println(" -> Scanning I2C Devices ...");
|
||||||
|
|
||||||
|
nDevices = 0;
|
||||||
|
for(address = 1; address < 127; address++ )
|
||||||
|
{
|
||||||
|
// The i2c_scanner uses the return value of
|
||||||
|
// the Write.endTransmisstion to see if
|
||||||
|
// a device did acknowledge to the address.
|
||||||
|
Wire.beginTransmission(address);
|
||||||
|
error = Wire.endTransmission();
|
||||||
|
|
||||||
|
if (error == 0)
|
||||||
|
{
|
||||||
|
Serial.print(" --> Device Found At Address 0x");
|
||||||
|
if (address<16)
|
||||||
|
Serial.print("0");
|
||||||
|
Serial.print(address,HEX);
|
||||||
|
Serial.println(" !");
|
||||||
|
|
||||||
|
nDevices++;
|
||||||
|
}
|
||||||
|
else if (error==4)
|
||||||
|
{
|
||||||
|
Serial.print(" --> Unknown error at address 0x");
|
||||||
|
if (address<16)
|
||||||
|
Serial.print("0");
|
||||||
|
Serial.println(address,HEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nDevices == 0)
|
||||||
|
Serial.println(" --> No I2C devices found\n");
|
||||||
|
else
|
||||||
|
Serial.println(" --> done");
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// WAITING FOR BLUETOOTH CONNECTION
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void OLED_BLUETOOTH_MODE()
|
||||||
|
{
|
||||||
|
// Starting The First Code
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 5, 3, "KICKER");
|
||||||
|
drawTextCenter(128/2, 30, 1, " - B L U E T O O T H - ");
|
||||||
|
if(BLUETOOTH_STATUS == true) {
|
||||||
|
drawTextCenter(128/2, 43, 2, "< CONNECTED >");
|
||||||
|
} else {
|
||||||
|
drawTextCenter(128/2, 43, 2, "< WAITING >");
|
||||||
|
}
|
||||||
|
OLED_SHOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// WAITING FOR BLUETOOTH CONNECTION
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void OLED_STANDALONE_MODE()
|
||||||
|
{
|
||||||
|
// Starting The First Code
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 5, 3, "KICKER");
|
||||||
|
drawTextCenter(128/2, 30, 1, " - S T A N D A L O N E - ");
|
||||||
|
drawTextCenter(128/2, 43, 2, "< MODE >");
|
||||||
|
OLED_SHOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// GAME SLIDER SELECTOR
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void GAME_PAGE(uint8_t MenuNumber, String Title) {
|
||||||
|
if(DISPLAY_CHANGED == false) {
|
||||||
|
OLED_CLEAR();
|
||||||
|
drawTextCenter(128/2, 5, 3, "< GAME #" + String(MenuNumber) >);
|
||||||
|
drawTextCenter(128/2, 30, 1, " - " + Title + " - ");
|
||||||
|
drawTextCenter(128/2, 43, 2, "<< SELECT >>");
|
||||||
|
OLED_SHOW();
|
||||||
|
DISPLAY_CHANGED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
Firmware Code/TOBOARD/FUNCTIONS.ino
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//====================================================================
|
||||||
|
// GENERAL FUNCTION SECTION
|
||||||
|
//====================================================================
|
||||||
|
// I2C DECIVES SCANNER
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void scanI2C()
|
||||||
|
{
|
||||||
|
byte error, address;
|
||||||
|
int nDevices;
|
||||||
|
|
||||||
|
Serial.println(" -> Scanning I2C Devices ...");
|
||||||
|
|
||||||
|
nDevices = 0;
|
||||||
|
for(address = 1; address < 127; address++ )
|
||||||
|
{
|
||||||
|
// The i2c_scanner uses the return value of
|
||||||
|
// the Write.endTransmisstion to see if
|
||||||
|
// a device did acknowledge to the address.
|
||||||
|
Wire.beginTransmission(address);
|
||||||
|
error = Wire.endTransmission();
|
||||||
|
|
||||||
|
if (error == 0)
|
||||||
|
{
|
||||||
|
Serial.print(" --> Device Found At Address 0x");
|
||||||
|
if (address<16)
|
||||||
|
Serial.print("0");
|
||||||
|
Serial.print(address,HEX);
|
||||||
|
Serial.println(" !");
|
||||||
|
|
||||||
|
nDevices++;
|
||||||
|
}
|
||||||
|
else if (error==4)
|
||||||
|
{
|
||||||
|
Serial.print(" --> Unknown error at address 0x");
|
||||||
|
if (address<16)
|
||||||
|
Serial.print("0");
|
||||||
|
Serial.println(address,HEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nDevices == 0)
|
||||||
|
Serial.println(" --> No I2C devices found\n");
|
||||||
|
else
|
||||||
|
Serial.println(" --> done");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Float Number Mapping Function
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
|
||||||
|
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
41
Firmware Code/TOBOARD/G_COUNTER.ino
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//====================================================================
|
||||||
|
// COUNTER GAME PROGRAM PAGE
|
||||||
|
//====================================================================
|
||||||
|
// GAME COUNTER - MENU
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_counter_menu()
|
||||||
|
{
|
||||||
|
menu_display("COUNTER");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME COUNTER - SETTINGS DISPLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_counter_settings()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME COUNTER - GAME PLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_counter_play()
|
||||||
|
{
|
||||||
|
oled_clear();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
//drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME COUNTER - GAME FINAL RESULT
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_counter_results()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
41
Firmware Code/TOBOARD/G_DECISION.ino
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//====================================================================
|
||||||
|
// DECISION GAME PROGRAM PAGE
|
||||||
|
//====================================================================
|
||||||
|
// GAME DECISION - MENU
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_decision_menu()
|
||||||
|
{
|
||||||
|
menu_display("DECISION");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME DECISION - SETTINGS DISPLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_decision_settings()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME DECISION - GAME PLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_decision_play()
|
||||||
|
{
|
||||||
|
oled_clear();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
//drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME DECISION - GAME FINAL RESULT
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_decision_results()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
42
Firmware Code/TOBOARD/G_FOCUSE.ino
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
//====================================================================
|
||||||
|
// FOUCSE GAME PROGRAM PAGE
|
||||||
|
//====================================================================
|
||||||
|
// GAME FOUCSE - MENU
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_foucse_menu()
|
||||||
|
{
|
||||||
|
menu_display("FOCUSE");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME FOUCSE - SETTINGS DISPLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_foucse_settings()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME FOUCSE - GAME PLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_foucse_play()
|
||||||
|
{
|
||||||
|
oled_clear();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
//drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME FOUCSE - GAME FINAL RESULT
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_foucse_results()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
42
Firmware Code/TOBOARD/G_REACTION.ino
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
//====================================================================
|
||||||
|
// REACTION GAME PROGRAM PAGE
|
||||||
|
//====================================================================
|
||||||
|
// GAME REACTION - MENU
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_reaction_menu()
|
||||||
|
{
|
||||||
|
menu_display("REACTION");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME REACTION - SETTINGS DISPLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_reaction_settings()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME REACTION - GAME PLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_reaction_play()
|
||||||
|
{
|
||||||
|
oled_clear();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
//drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME REACTION - GAME FINAL RESULT
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_reaction_results()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
41
Firmware Code/TOBOARD/G_STAMINA.ino
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//====================================================================
|
||||||
|
// STAMINA GAME PROGRAM PAGE
|
||||||
|
//====================================================================
|
||||||
|
// GAME STAMINA - MENU
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_stamina_menu()
|
||||||
|
{
|
||||||
|
menu_display("STAMINA");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME STAMINA - SETTINGS DISPLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_stamina_settings()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME STAMINA - GAME PLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_stamina_play()
|
||||||
|
{
|
||||||
|
oled_clear();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
//drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME STAMINA - GAME FINAL RESULT
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_stamina_results()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
41
Firmware Code/TOBOARD/G_TIMEATTACK.ino
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//====================================================================
|
||||||
|
// TIMEATTACK GAME PROGRAM PAGE
|
||||||
|
//====================================================================
|
||||||
|
// GAME TIMEATTACK - MENU
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_timeattack_menu()
|
||||||
|
{
|
||||||
|
menu_display("TIMEATTACK");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME TIMEATTACK - SETTINGS DISPLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_timeattack_settings()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME TIMEATTACK - GAME PLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_timeattack_play()
|
||||||
|
{
|
||||||
|
oled_clear();
|
||||||
|
drawTextCenter(128/2, 0, 2, "KICKS");
|
||||||
|
//drawTextCenter(128/2, 20, 3, String(count));
|
||||||
|
drawTextCenter(128/2, 50, 1, "<< EXIT >>");
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// GAME TIMEATTACK - GAME FINAL RESULT
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void game_timeattack_results()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
58
Firmware Code/TOBOARD/MENU.ino
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//====================================================================
|
||||||
|
// COUNTER GAME PROGRAM PAGE
|
||||||
|
//====================================================================
|
||||||
|
// DISPLAY MENU TITLE FUNCTION
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void menu_display(String Title)
|
||||||
|
{
|
||||||
|
// Starting The First Code
|
||||||
|
oled_clear();
|
||||||
|
drawTextCenter(128/2, 5, 1, "MODE " + String(menu_count + 1));
|
||||||
|
drawTextCenter(128/2, 22, 2, " - " + Title + " - ");
|
||||||
|
drawTextCenter(128/2, 43, 1, "<< SELECT >>");
|
||||||
|
oled_show();
|
||||||
|
display_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// SWITCH GAME MENUS
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void switch_menu()
|
||||||
|
{
|
||||||
|
if(menu_count == 0 && display_changed == false) {
|
||||||
|
game_counter_menu();
|
||||||
|
} else if(menu_count == 1 && display_changed == false) {
|
||||||
|
game_timeattack_menu();
|
||||||
|
} else if(menu_count == 2 && display_changed == false) {
|
||||||
|
game_reaction_menu();
|
||||||
|
} else if(menu_count == 3 && display_changed == false) {
|
||||||
|
game_decision_menu();
|
||||||
|
} else if(menu_count == 4 && display_changed == false) {
|
||||||
|
game_stamina_menu();
|
||||||
|
} else if(menu_count == 5 && display_changed == false) {
|
||||||
|
game_foucse_menu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// SELECT A GAME
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void select_game()
|
||||||
|
{
|
||||||
|
if(menu_count == 0 && CB.pressed()) {
|
||||||
|
|
||||||
|
} else if(menu_count == 1 && CB.pressed()) {
|
||||||
|
|
||||||
|
} else if(menu_count == 2 && CB.pressed()) {
|
||||||
|
|
||||||
|
} else if(menu_count == 3 && CB.pressed()) {
|
||||||
|
|
||||||
|
} else if(menu_count == 4 && CB.pressed()) {
|
||||||
|
|
||||||
|
} else if(menu_count == 5 && CB.pressed()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
61
Firmware Code/TOBOARD/NEOPIXEL.ino
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//====================================================================
|
||||||
|
// ADAFRUITE NEO PIXEL
|
||||||
|
//====================================================================
|
||||||
|
// INCLUDE LIBRARY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Neo Pixel Library
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
// When setting up the NeoPixel library, we tell it how many pixels,
|
||||||
|
// and which pin to use to send signals. Note that for older NeoPixel
|
||||||
|
Adafruit_NeoPixel pixels(NUMPIXELS, NEOPIXEL, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// INITIALIZE LED STRIP OBJECT (REQUIRED)
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void neo_init() {
|
||||||
|
BOOST_ON;
|
||||||
|
delay(5);
|
||||||
|
pixels.begin();
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
delay(5);
|
||||||
|
BOOST_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// TURNON LED STRIP - FOR WELCOME
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void neo_welcome() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// TURNON LED STRIP WITH COLOR
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void neo_color(uint8_t R, uint8_t G, uint8_t B) {
|
||||||
|
BOOST_ON;
|
||||||
|
delay(1);
|
||||||
|
pixels.clear();
|
||||||
|
for(int i=0; i<NUMPIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
pixels.setBrightness(50);
|
||||||
|
delay(2);
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// TURNOFF LED STRIP
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void neo_turnoff() {
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
BOOST_OFF;
|
||||||
|
}
|
||||||
175
Firmware Code/TOBOARD/OLED.ino
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
//====================================================================
|
||||||
|
// OLED DISPLAY
|
||||||
|
//====================================================================
|
||||||
|
// LIBRARY INCLUDE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Include Libraries
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <SSD1306Wire.h>
|
||||||
|
|
||||||
|
// Display Instance
|
||||||
|
SSD1306Wire display(0x3c, 21, 22);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED Initialization
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void oled_init() {
|
||||||
|
display.init();
|
||||||
|
display.flipScreenVertically();
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED Display Text
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void drawTextFlowDemo(String Text) {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.drawStringMaxWidth(0, 0, 128, Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED LEFT TEXT Display
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void drawTextLeft() {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display.drawString(0, 10, "Left aligned (0,10)");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED CENTER TEXT Display
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void drawTextCenter(int X, int Y, int Size, String Text) {
|
||||||
|
//display.setFont(ArialMT_Plain_10);
|
||||||
|
|
||||||
|
if(Size == 1) {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
} else if(Size == 2) {
|
||||||
|
display.setFont(ArialMT_Plain_16);
|
||||||
|
} else if(Size == 3) {
|
||||||
|
display.setFont(ArialMT_Plain_24);
|
||||||
|
} else {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
}
|
||||||
|
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display.drawString(X, Y, Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED RIGHT TEXT DISPLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
// OLED Display
|
||||||
|
void drawTextRight() {
|
||||||
|
display.setFont(ArialMT_Plain_10);
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display.drawString(128, 33, "Right aligned (128,33)");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED DRAW RECTANGLE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void drawRectDemo() {
|
||||||
|
// Draw a pixel at given position
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
display.setPixel(i, i);
|
||||||
|
display.setPixel(10 - i, i);
|
||||||
|
}
|
||||||
|
display.drawRect(12, 12, 20, 20);
|
||||||
|
|
||||||
|
// Fill the rectangle
|
||||||
|
display.fillRect(14, 14, 17, 17);
|
||||||
|
|
||||||
|
// Draw a line horizontally
|
||||||
|
display.drawHorizontalLine(0, 40, 20);
|
||||||
|
|
||||||
|
// Draw a line horizontally
|
||||||
|
display.drawVerticalLine(40, 0, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED DRAW CIRCLE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void drawCircleDemo() {
|
||||||
|
for (int i=1; i < 8; i++) {
|
||||||
|
display.setColor(WHITE);
|
||||||
|
display.drawCircle(32, 32, i*3);
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
display.setColor(BLACK);
|
||||||
|
}
|
||||||
|
display.fillCircle(96, 32, 32 - i* 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED DRAW PROGRESS BAR
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void drawProgressBarDemo(int Value) {
|
||||||
|
int progress = Value;
|
||||||
|
// draw the progress bar
|
||||||
|
display.drawProgressBar(0, 50, 120, 10, progress);
|
||||||
|
|
||||||
|
// draw the percentage as String
|
||||||
|
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display.drawString(64, 35, String(progress) + "%");
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED CLEAR DISPLAY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void oled_clear() {
|
||||||
|
display.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED SHOW NEW DATA
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void oled_show() {
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED DISPLAY KICKER WELCOME MESSAGE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void kicker_logo() {
|
||||||
|
// Starting The First Code
|
||||||
|
oled_clear();
|
||||||
|
drawTextCenter(128/2, 5, 3, "TAKEONE");
|
||||||
|
drawTextCenter(128/2, 30, 1, " - T E C H N O L O G Y - ");
|
||||||
|
drawTextCenter(128/2, 43, 2, "<< KICKER >>");
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// OLED DISPLAY BATTERY LEVEL
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void battery_level_display() {
|
||||||
|
// Counting Time
|
||||||
|
timetick = millis();
|
||||||
|
|
||||||
|
// Taking Action Based On Time Count
|
||||||
|
if(timetick - prevtick >= 5000)
|
||||||
|
{
|
||||||
|
prevtick = timetick;
|
||||||
|
String BV = String(BATTERY,2);
|
||||||
|
String BC = String(CHARGE, 0);
|
||||||
|
oled_clear();
|
||||||
|
drawTextFlowDemo("Battery Level : " + BV + " V Charge Level : " + BC + "%");
|
||||||
|
drawProgressBarDemo(BC.toInt());
|
||||||
|
oled_show();
|
||||||
|
}
|
||||||
|
}
|
||||||
240
Firmware Code/TOBOARD/SDCARD.ino
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
//====================================================================
|
||||||
|
// SDCARD READER FUNCTIONS
|
||||||
|
//====================================================================
|
||||||
|
// LIST DIRECTORIES
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
|
||||||
|
Serial.printf("Listing directory: %s\n", dirname);
|
||||||
|
|
||||||
|
File root = fs.open(dirname);
|
||||||
|
if(!root){
|
||||||
|
Serial.println("Failed to open directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!root.isDirectory()){
|
||||||
|
Serial.println("Not a directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = root.openNextFile();
|
||||||
|
while(file){
|
||||||
|
if(file.isDirectory()){
|
||||||
|
Serial.print(" DIR : ");
|
||||||
|
Serial.println(file.name());
|
||||||
|
if(levels){
|
||||||
|
listDir(fs, file.name(), levels -1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Serial.print(" FILE: ");
|
||||||
|
Serial.print(file.name());
|
||||||
|
Serial.print(" SIZE: ");
|
||||||
|
Serial.println(file.size());
|
||||||
|
}
|
||||||
|
file = root.openNextFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// CREATE DIRECTORY
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void createDir(fs::FS &fs, const char * path){
|
||||||
|
Serial.printf("Creating Dir: %s\n", path);
|
||||||
|
if(fs.mkdir(path)){
|
||||||
|
Serial.println("Dir created");
|
||||||
|
} else {
|
||||||
|
Serial.println("mkdir failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// REMOVE DIRECTORIES
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void removeDir(fs::FS &fs, const char * path){
|
||||||
|
Serial.printf("Removing Dir: %s\n", path);
|
||||||
|
if(fs.rmdir(path)){
|
||||||
|
Serial.println("Dir removed");
|
||||||
|
} else {
|
||||||
|
Serial.println("rmdir failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// READ FILE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void readFile(fs::FS &fs, const char * path){
|
||||||
|
Serial.printf("Reading file: %s\n", path);
|
||||||
|
|
||||||
|
File file = fs.open(path);
|
||||||
|
if(!file){
|
||||||
|
Serial.println("Failed to open file for reading");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("Read from file: ");
|
||||||
|
while(file.available()){
|
||||||
|
Serial.write(file.read());
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// WRITE TO A FILE / CREATE A NEW FILE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void writeFile(fs::FS &fs, const char * path, const char * message){
|
||||||
|
Serial.printf("Writing file: %s\n", path);
|
||||||
|
|
||||||
|
File file = fs.open(path, FILE_WRITE);
|
||||||
|
if(!file){
|
||||||
|
Serial.println("Failed to open file for writing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(file.print(message)){
|
||||||
|
Serial.println("File written");
|
||||||
|
} else {
|
||||||
|
Serial.println("Write failed");
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// WRITE TO THE BOTTOM OF A FILE / CONTINUE WRITING
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void appendFile(fs::FS &fs, const char * path, const char * message){
|
||||||
|
Serial.printf("Appending to file: %s\n", path);
|
||||||
|
|
||||||
|
File file = fs.open(path, FILE_APPEND);
|
||||||
|
if(!file){
|
||||||
|
Serial.println("Failed to open file for appending");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(file.print(message)){
|
||||||
|
Serial.println("Message appended");
|
||||||
|
} else {
|
||||||
|
Serial.println("Append failed");
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// RENAME A FILE / CHNAGE THE NAME OF A FILE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void renameFile(fs::FS &fs, const char * path1, const char * path2){
|
||||||
|
Serial.printf("Renaming file %s to %s\n", path1, path2);
|
||||||
|
if (fs.rename(path1, path2)) {
|
||||||
|
Serial.println("File renamed");
|
||||||
|
} else {
|
||||||
|
Serial.println("Rename failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// DELETE A FILE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void deleteFile(fs::FS &fs, const char * path){
|
||||||
|
Serial.printf("Deleting file: %s\n", path);
|
||||||
|
if(fs.remove(path)){
|
||||||
|
Serial.println("File deleted");
|
||||||
|
} else {
|
||||||
|
Serial.println("Delete failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// SDCARD TEST ROUTINE
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void testFileIO(fs::FS &fs, const char * path){
|
||||||
|
File file = fs.open(path);
|
||||||
|
static uint8_t buf[512];
|
||||||
|
size_t len = 0;
|
||||||
|
uint32_t start = millis();
|
||||||
|
uint32_t end = start;
|
||||||
|
if(file){
|
||||||
|
len = file.size();
|
||||||
|
size_t flen = len;
|
||||||
|
start = millis();
|
||||||
|
while(len){
|
||||||
|
size_t toRead = len;
|
||||||
|
if(toRead > 512){
|
||||||
|
toRead = 512;
|
||||||
|
}
|
||||||
|
file.read(buf, toRead);
|
||||||
|
len -= toRead;
|
||||||
|
}
|
||||||
|
end = millis() - start;
|
||||||
|
Serial.printf("%u bytes read for %u ms\n", flen, end);
|
||||||
|
file.close();
|
||||||
|
} else {
|
||||||
|
Serial.println("Failed to open file for reading");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
file = fs.open(path, FILE_WRITE);
|
||||||
|
if(!file){
|
||||||
|
Serial.println("Failed to open file for writing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
start = millis();
|
||||||
|
for(i=0; i<2048; i++){
|
||||||
|
file.write(buf, 512);
|
||||||
|
}
|
||||||
|
end = millis() - start;
|
||||||
|
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// STARTING SDCARD READER
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void sdcard_init(){
|
||||||
|
if(!SD.begin()){
|
||||||
|
Serial.println("Card Mount Failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t cardType = SD.cardType();
|
||||||
|
|
||||||
|
if(cardType == CARD_NONE){
|
||||||
|
Serial.println("No SD card attached");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("SD Card Type: ");
|
||||||
|
if(cardType == CARD_MMC){
|
||||||
|
Serial.println("MMC");
|
||||||
|
} else if(cardType == CARD_SD){
|
||||||
|
Serial.println("SDSC");
|
||||||
|
} else if(cardType == CARD_SDHC){
|
||||||
|
Serial.println("SDHC");
|
||||||
|
} else {
|
||||||
|
Serial.println("UNKNOWN");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
|
||||||
|
Serial.printf("SD Card Size: %lluMB\n", cardSize);
|
||||||
|
|
||||||
|
//listDir(SD, "/", 0);
|
||||||
|
//createDir(SD, "/mydir");
|
||||||
|
//listDir(SD, "/", 0);
|
||||||
|
//removeDir(SD, "/mydir");
|
||||||
|
//listDir(SD, "/", 2);
|
||||||
|
writeFile(SD, "/battery.txt", "Battery Monitoring");
|
||||||
|
//appendFile(SD, "/hello.txt", "World!\n");
|
||||||
|
//readFile(SD, "/hello.txt");
|
||||||
|
//deleteFile(SD, "/foo.txt");
|
||||||
|
//renameFile(SD, "/hello.txt", "/foo.txt");
|
||||||
|
//readFile(SD, "/foo.txt");
|
||||||
|
//testFileIO(SD, "/test.txt");
|
||||||
|
//Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
|
||||||
|
//Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
|
||||||
|
}
|
||||||
379
Firmware Code/TOBOARD/TOBOARD.ino
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
/* ===============================================
|
||||||
|
* - THIS IS TAKEONE BOARD -
|
||||||
|
* ===============================================
|
||||||
|
* MPU9250 Address : 0X69 (ADDRESS)
|
||||||
|
* OLED 128x64 Address : 0X3C (ADDRESS)
|
||||||
|
* -----------------------------------------------
|
||||||
|
* Description : PIN GPIO#
|
||||||
|
* -----------------------------------------------
|
||||||
|
* NEOPIXEL LED STRIP : A0/GPIO 26
|
||||||
|
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
|
||||||
|
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
|
||||||
|
* BUTTONS : TLB (35), BLB (15), CB (33), BRB (27), TRB(12)
|
||||||
|
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
|
||||||
|
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
|
||||||
|
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
|
||||||
|
* LED PIN : 13 (DIGITAL)
|
||||||
|
* BATTERY MONITOR PIN : 35 (ANALOG)
|
||||||
|
* -----------------------------------------------
|
||||||
|
* BUTTONS PINOUTS : PIN GPIO
|
||||||
|
* -----------------------------------------------
|
||||||
|
* TOP LEFT BUTTON : 15 - SWITCH PREVIOUS MENU / CHANGE PARAMETER
|
||||||
|
* TOP RIGHT BUTTON : 12 - SWITCH NEXT MENU / CHANGE PARAMETER
|
||||||
|
* BOTTOM LEFT BUTTON : 32 - POWER INC & BACK & INC PARAMETER
|
||||||
|
* BOTTOM RIGHT BUTTON : 27 - POWER DEC & SAVE & DEC PARAMETER
|
||||||
|
* CENTER BUTTON : 33 - POWER ON & SELECT
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Include Library
|
||||||
|
#include <FS.h>
|
||||||
|
#include <SD.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Button.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <BluetoothSerial.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// Communication Models
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
// Serial Port As Terminal
|
||||||
|
#define terminal Serial
|
||||||
|
|
||||||
|
// Clearing Terminal Remainning
|
||||||
|
#define flush_terminal while(terminal.available()) { terminal.read(); }
|
||||||
|
|
||||||
|
// Bluetooth Object
|
||||||
|
BluetoothSerial bluetooth;
|
||||||
|
|
||||||
|
// Bluetooth Connection Status
|
||||||
|
bool bluetooth_conn = false;
|
||||||
|
|
||||||
|
// Clearing Bluetooth Remainning
|
||||||
|
#define flush_bluetooth while(bluetooth.available()) { bluetooth.read(); }
|
||||||
|
|
||||||
|
// Fixed JSON Strings
|
||||||
|
#define POWERUP "{\"status\":\"POWER UP\"}"
|
||||||
|
#define UNDERSTOOD "{\"status\":\"OK\"}"
|
||||||
|
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
|
||||||
|
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
|
||||||
|
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
|
||||||
|
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
|
||||||
|
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
|
||||||
|
|
||||||
|
// GAME NAMES
|
||||||
|
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
|
||||||
|
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
|
||||||
|
#define GM_REACTION "{\"gm\":\"REACTION\"}"
|
||||||
|
#define GM_DECISION "{\"gm\":\"DECISION\"}"
|
||||||
|
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
|
||||||
|
|
||||||
|
// COMMAND LIST
|
||||||
|
#define CM_START "{\"cm\":\"START\"}"
|
||||||
|
#define CM_RESET "{\"cm\":\"RESET\"}"
|
||||||
|
#define CM_STOP "{\"cm\":\"STOP\"}"
|
||||||
|
#define CM_EXIT "{\"cm\":\"EXIT\"}"
|
||||||
|
|
||||||
|
// JSON CAPACITY
|
||||||
|
#define capacity 250
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
// TAKEONE BOARD HARDWARE DEFINITIONS
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
|
// On Board MPU9250 I2C Address
|
||||||
|
#define MPU_ADD 0x69
|
||||||
|
|
||||||
|
// Connected I2C OLED Address
|
||||||
|
#define OLED_ADD 0x3C
|
||||||
|
|
||||||
|
// Connected I2C LCD Address
|
||||||
|
#define LCD_ADD 0x2C
|
||||||
|
|
||||||
|
// Define Impact Sensor
|
||||||
|
#define PIEZO analogRead(34)
|
||||||
|
#define VOLTS mapf(PIEZO, 0, 4095, 0, 3.3)
|
||||||
|
|
||||||
|
// Panel Push Buttons Pin Assignment Sections
|
||||||
|
Button TLB(32); // Top Left Button
|
||||||
|
Button BLB(15); // Bottom Left Button
|
||||||
|
Button CB(33); // Center Button
|
||||||
|
Button BRB(27); // Bottom Right Button
|
||||||
|
Button TRB(12); // Top Right Button 33
|
||||||
|
|
||||||
|
// Panel Push Buttons Command Assignment
|
||||||
|
#define PrvMenu TLB.pressed()
|
||||||
|
#define NxtMenu TRB.pressed()
|
||||||
|
#define SelMenu CB.pressed()
|
||||||
|
#define IncBtn BLB.pressed()
|
||||||
|
#define DecBtn BRB.pressed()
|
||||||
|
|
||||||
|
// NEO Pixel Strip Section
|
||||||
|
#define NEOPIXEL 26 // Define Pin Number
|
||||||
|
#define NUMPIXELS 22 // Define Number Of LED's
|
||||||
|
|
||||||
|
// Battery Level Monitoring
|
||||||
|
#define BATTERY (float)(((analogRead(35) * (3.3 / 4096)) * 2) + 0.31)
|
||||||
|
#define CHARGE mapf(BATTERY, 3.27, 4.31, 0, 100)
|
||||||
|
|
||||||
|
// Power Latch Holder Pin
|
||||||
|
#define POWER_PIN 14
|
||||||
|
#define POWER_SETUP pinMode(POWER_PIN, OUTPUT)
|
||||||
|
#define POWER_ON digitalWrite(POWER_PIN, HIGH)
|
||||||
|
#define POWER_OFF digitalWrite(POWER_PIN, LOW)
|
||||||
|
|
||||||
|
// Battery To 5V Level Booster Setup & Control
|
||||||
|
#define BOOST_PIN 14
|
||||||
|
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
|
||||||
|
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
|
||||||
|
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
|
||||||
|
|
||||||
|
// On Board LED Setup & Control
|
||||||
|
#define LED_PIN 13
|
||||||
|
#define LED_SETUP pinMode(LED_PIN, OUTPUT)
|
||||||
|
#define LED_ON digitalWrite(LED_PIN, HIGH)
|
||||||
|
#define LED_OFF digitalWrite(LED_PIN, LOW)
|
||||||
|
|
||||||
|
// For Timming
|
||||||
|
unsigned long timetick = 0;
|
||||||
|
unsigned long prevtick = 0;
|
||||||
|
|
||||||
|
/* Display Change Flag Explaination
|
||||||
|
* This flag is used to prevent continous writing to the oled display
|
||||||
|
* once a change has happened we drive the display_changed to false this will tell
|
||||||
|
* the micro controller that a need to write new data is needed, after writing the new data to display
|
||||||
|
* then we drive the display_changed to true that means the nessary changes has been written
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool display_changed = false;
|
||||||
|
uint8_t menu_count = 0;
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// Bluetooth Connection Status Call Back
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
||||||
|
{
|
||||||
|
if(event == ESP_SPP_SRV_OPEN_EVT){
|
||||||
|
//Serial.println("Client Connected");
|
||||||
|
bluetooth_conn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event == ESP_SPP_CLOSE_EVT ){
|
||||||
|
//Serial.println("Client disconnected");
|
||||||
|
bluetooth_conn = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// CHIP MAIN SETUP
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Starting Serial Communications
|
||||||
|
terminal.begin(115200); // Starting Main USB UART Communication Interface
|
||||||
|
terminal.println(); // New Line Seperator 1
|
||||||
|
terminal.println(); // New Line Seperator 2
|
||||||
|
|
||||||
|
// Starting The Bluetooth Module
|
||||||
|
if(!bluetooth.begin("KICKER")) {
|
||||||
|
terminal.println("An error occurred initializing Bluetooth");
|
||||||
|
} else {
|
||||||
|
terminal.println("Bluetooth initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking The Connection Status
|
||||||
|
bluetooth.register_callback(callback);
|
||||||
|
|
||||||
|
// Pin Assignments
|
||||||
|
BOOST_SETUP; // Boost Converter Pin Setup
|
||||||
|
LED_SETUP; // OnBoard LED Pin Setup
|
||||||
|
|
||||||
|
// Turn Off The Pins
|
||||||
|
BOOST_OFF; // Turn Off The Booster
|
||||||
|
LED_OFF; // Turn Off The LED
|
||||||
|
|
||||||
|
// The Five Panel Buttons
|
||||||
|
TLB.begin(); // Setup The Top Left Panel Button
|
||||||
|
BLB.begin(); // Setup The Bottom Left Panel Button
|
||||||
|
BRB.begin(); // Setup The Bottom Right Panel Button
|
||||||
|
TRB.begin(); // Setup The Top Right Panel Button
|
||||||
|
CB.begin(); // Setup The Center Panel Button
|
||||||
|
|
||||||
|
// I2C Section
|
||||||
|
Wire.begin(); // Starting I2C Communication Interface
|
||||||
|
scanI2C(); // Starting I2C Communicatable Devices Detection
|
||||||
|
oled_init(); // Starting OLED Display I2C Communications
|
||||||
|
kicker_logo(); // Display Kicker Main Logo Display
|
||||||
|
|
||||||
|
// Starting SDCARD Interface
|
||||||
|
sdcard_init(); // Starting SDCARD Reader Communication Protocol
|
||||||
|
|
||||||
|
// Neo Pixel Section
|
||||||
|
neo_init(); // Starting Neo Pixel
|
||||||
|
neo_color(0, 0, 0); // Clear All LED's
|
||||||
|
delay(10); // Delay 10 Milli Seconds
|
||||||
|
neo_color(255, 0, 0); // Display RED LED Strip
|
||||||
|
delay(1000); // Delay 1 Second
|
||||||
|
neo_color(0, 255, 0); // Display GREEN LED Strip
|
||||||
|
delay(1000); // Delay 1 Second
|
||||||
|
neo_color(0, 0, 255); // Display BLUE LED Strip
|
||||||
|
delay(1000); // Delay 1 Second
|
||||||
|
neo_turnoff(); // Power Off Neo Pixels & Their Power
|
||||||
|
|
||||||
|
// THE PROGRAM STATE = MENU
|
||||||
|
display_changed = false; // Allow Display Change
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// CHIP MAIN PROGRAM
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Checking The Bluetooth Connection
|
||||||
|
bluetooth.register_callback(callback);
|
||||||
|
|
||||||
|
// Condition The Preiority Is For The Bluetooth
|
||||||
|
if(bluetooth_conn == true)
|
||||||
|
{
|
||||||
|
// Wait For Game JSON String
|
||||||
|
read_game_json();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Condition To Stand Alone Mode - Manual Mode
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Previous Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
if(TLB.pressed()) {
|
||||||
|
if(menu_count == 0) {
|
||||||
|
menu_count = 4;
|
||||||
|
} else {
|
||||||
|
menu_count--;
|
||||||
|
}
|
||||||
|
display_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
if(TRB.pressed()) {
|
||||||
|
if(menu_count == 4) {
|
||||||
|
menu_count = 0;
|
||||||
|
} else {
|
||||||
|
menu_count++;
|
||||||
|
}
|
||||||
|
display_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select A Game ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
if(CB.pressed()) {
|
||||||
|
select_game();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increase Power ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
if(BLB.pressed()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrease Power ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
if(BRB.pressed()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display Target Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
switch_menu();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Read Game JSON String Command From Mobile
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void read_game_json()
|
||||||
|
{
|
||||||
|
// Reading From Bluetooth
|
||||||
|
if(bluetooth.available())
|
||||||
|
{
|
||||||
|
// Reading Message From Bluetooth
|
||||||
|
String msg = bluetooth.readStringUntil('\n');
|
||||||
|
|
||||||
|
// Clearing The Receive Buffer
|
||||||
|
flush_bluetooth;
|
||||||
|
|
||||||
|
// Clean The Message
|
||||||
|
msg.trim();
|
||||||
|
|
||||||
|
// Display On Sertial
|
||||||
|
terminal.println(msg);
|
||||||
|
|
||||||
|
// Parsing Objects Message Objects
|
||||||
|
DynamicJsonDocument root(capacity);
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(root, msg);
|
||||||
|
|
||||||
|
// If The System Understood The Message Clearly
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
// Sending Status Message
|
||||||
|
terminal.println(UNDERSTOOD);
|
||||||
|
bluetooth.println(UNDERSTOOD);
|
||||||
|
|
||||||
|
// Reading Game Name & Settings
|
||||||
|
String game = root["gm"];
|
||||||
|
String settings = root["set"];
|
||||||
|
|
||||||
|
// Clearing JSON Document Buffer
|
||||||
|
root.clear();
|
||||||
|
|
||||||
|
// Entering To Game Selector
|
||||||
|
game_selector(game, settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Display On Serial
|
||||||
|
terminal.println(JSON_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bluetooth Serial RXD Flush
|
||||||
|
flush_bluetooth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Game Selector Function
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_selector(String game, String settings)
|
||||||
|
{
|
||||||
|
// Kick Counter Game
|
||||||
|
if(game == "ct") {
|
||||||
|
terminal.println(GM_COUNTER);
|
||||||
|
//game_counter(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ta") {
|
||||||
|
terminal.println(GM_TATTACK);
|
||||||
|
//game_timeAttack(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ra") {
|
||||||
|
terminal.println(GM_REACTION);
|
||||||
|
//game_reaction(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown Game
|
||||||
|
else {
|
||||||
|
terminal.println(UNKNOWN_GAME);
|
||||||
|
bluetooth.println(UNKNOWN_GAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Firmware Code/kicker_rev_1/communication.ino
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//======================================================
|
||||||
|
// TERMINAL WINDOW - NATIVE USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void terminal(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Terminal.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void bluetooth(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Bluetooth.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void dualcomm(String msg)
|
||||||
|
{
|
||||||
|
terminal(msg);
|
||||||
|
bluetooth(msg);
|
||||||
|
}
|
||||||
192
Firmware Code/kicker_rev_1/game_counter.ino
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN COUNTER GAME LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* --------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* ct : count
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* WHAT DATA TO BE COLLECTED :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISPLAY AND TIMESTAMP
|
||||||
|
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* No calculation required, Its directly the count
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_counter(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// CONVERTING GAME TEXT TO JSON
|
||||||
|
DynamicJsonDocument play(capacity); // building JSON Buffer
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(play, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t limit = play["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = play["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
play.clear();
|
||||||
|
|
||||||
|
// Trying To Delete The Document
|
||||||
|
//play.delete();
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// Game Start Lights
|
||||||
|
Counter_Start();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readString();
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
Counter_Reset();
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebration
|
||||||
|
Counter_Celebration();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Impact
|
||||||
|
if(readImpact() > PWR)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(counter_data_json(counter, timeStamp));
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER DATA JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String counter_data_json(unsigned int ct, unsigned int st)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
DynamicJsonDocument data(capacity);
|
||||||
|
|
||||||
|
// Convert Int To Float
|
||||||
|
float stamp = st;
|
||||||
|
stamp /= 1000;
|
||||||
|
|
||||||
|
// Assignning Dataset
|
||||||
|
data["ct"] = ct;
|
||||||
|
data["st"] = String(stamp, 3).toFloat();
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(data, output);
|
||||||
|
data.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Counter_Start()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
LED_WHITE_CROSSFADE(2);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Counter_End()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
LED_RED();
|
||||||
|
delay(2000);
|
||||||
|
// Red FadeOut
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Counter_Celebration()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Counter_Reset()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
LED_BLUE();
|
||||||
|
delay(250);
|
||||||
|
LED_BLUE_FADEOUT();
|
||||||
|
}
|
||||||
225
Firmware Code/kicker_rev_1/game_reaction.ino
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
//======================================================
|
||||||
|
// REACTION GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* REACTION GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tr": 10, "mn": 1, "mx": 2}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* tr : trials pre counter
|
||||||
|
* mn : minimum delay, between trials
|
||||||
|
* mx : maximum delay, between trials
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tr" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_reaction(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// CONVERTING GAME TEXT TO JSON
|
||||||
|
DynamicJsonDocument play(capacity);
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(play, settings);
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint8_t minDelay = play["mx"];
|
||||||
|
uint8_t maxDelay = play["mn"];
|
||||||
|
uint16_t trials = play["lm"];
|
||||||
|
uint16_t temp = trials;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
play.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Display Welcome Message
|
||||||
|
terminal("");
|
||||||
|
terminal("trials : " + String(trials) + " Strikes");
|
||||||
|
terminal("minDelay : " + String(minDelay) + " Seconds");
|
||||||
|
terminal("maxDelay : " + String(maxDelay) + " Seconds");
|
||||||
|
terminal("2 Seconds To Start Get Ready & Good Luck !!");
|
||||||
|
terminal("");
|
||||||
|
|
||||||
|
// Ready Signal
|
||||||
|
Reaction_Start();
|
||||||
|
|
||||||
|
// Main Variables
|
||||||
|
uint16_t sdelay = 0;
|
||||||
|
uint16_t power = 0;
|
||||||
|
uint16_t response = 0;
|
||||||
|
unsigned long startTime = 0;
|
||||||
|
unsigned long stopTime = 0;
|
||||||
|
|
||||||
|
// Processing Results
|
||||||
|
for(int i=0; i<trials; i++)
|
||||||
|
{
|
||||||
|
// Reading Kick Data
|
||||||
|
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
|
||||||
|
terminal(" -> Get Ready !!");
|
||||||
|
|
||||||
|
// Set Random Delay Time
|
||||||
|
sdelay = random(minDelay, maxDelay);
|
||||||
|
sdelay *= 1000;
|
||||||
|
delay(sdelay);
|
||||||
|
|
||||||
|
// Light Up Green
|
||||||
|
rgbLED(0, 150, 0);
|
||||||
|
|
||||||
|
// Start Timer
|
||||||
|
startTime = millis();
|
||||||
|
|
||||||
|
// Sensing Strike Power
|
||||||
|
while(power < PWR)
|
||||||
|
{
|
||||||
|
// Reading The Strike
|
||||||
|
power = readImpact();
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readString();
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP) {
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
LED_RED();
|
||||||
|
delay(2000);
|
||||||
|
// Red FadeOut
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET) {
|
||||||
|
trials = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop Timer
|
||||||
|
stopTime = millis();
|
||||||
|
|
||||||
|
// Stop Light
|
||||||
|
rgbLED(150, 0, 0);
|
||||||
|
|
||||||
|
// Calculating Response Time
|
||||||
|
response = stopTime - startTime - 1;
|
||||||
|
|
||||||
|
// Create Json Data
|
||||||
|
String msg = reaction_data_json(i+1, power, response, sdelay);
|
||||||
|
|
||||||
|
// Print To Terminal
|
||||||
|
dualcomm(msg);
|
||||||
|
|
||||||
|
// Clear All
|
||||||
|
sdelay = 0;
|
||||||
|
power = 0;
|
||||||
|
response = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red Light Delay
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
|
||||||
|
// Blink Red
|
||||||
|
Reaction_End();
|
||||||
|
|
||||||
|
// Return To Game Selector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION DATA JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String reaction_data_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
DynamicJsonDocument data(capacity);
|
||||||
|
|
||||||
|
// Convert To Seconds Unit
|
||||||
|
float re = response;
|
||||||
|
re /= 1000;
|
||||||
|
|
||||||
|
// Asignning Values
|
||||||
|
data["ct"] = count; // Strike Number
|
||||||
|
data["pw"] = power; // Strike Power In Analog Read
|
||||||
|
data["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
|
||||||
|
data["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(data, output);
|
||||||
|
data.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Reaction_Start()
|
||||||
|
{
|
||||||
|
LED_WHITE_CROSSFADE(3);
|
||||||
|
LED_RED_FADEIN();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Reaction_End()
|
||||||
|
{
|
||||||
|
LED_RED_BLINK(2);
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Reaction_Celebration()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void Reaction_Reset()
|
||||||
|
{
|
||||||
|
LED_BLUE();
|
||||||
|
delay(250);
|
||||||
|
LED_BLUE_FADEOUT();
|
||||||
|
}
|
||||||
37
Firmware Code/kicker_rev_1/game_selector.ino
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* game selector is the main function that tell the game groutine
|
||||||
|
* which game to be played and at what parameters
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_selector(String game, String settings)
|
||||||
|
{
|
||||||
|
// Kick Counter Game
|
||||||
|
if(game == "ct") {
|
||||||
|
terminal(GM_COUNTER);
|
||||||
|
game_counter(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ta") {
|
||||||
|
terminal(GM_TATTACK);
|
||||||
|
game_timeAttack(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ra") {
|
||||||
|
terminal(GM_REACTION);
|
||||||
|
game_reaction(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown Game
|
||||||
|
else {
|
||||||
|
dualcomm(UNKNOWN_GAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
239
Firmware Code/kicker_rev_1/game_time_attack.ino
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
//======================================================
|
||||||
|
// TIME ATTACK GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tm": 10, "le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* tm : count down timer starting value
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tm" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
|
||||||
|
*
|
||||||
|
* RETURNNING DATA FORMAT :
|
||||||
|
* ------------------------
|
||||||
|
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
|
||||||
|
*
|
||||||
|
* tm : timer count in Sec
|
||||||
|
* ct : strike counter (number of kicks)
|
||||||
|
* dl : delay between strikes
|
||||||
|
* st : time stampe of the strike in milli Seconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_timeAttack(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// CONVERTING GAME TEXT TO JSON
|
||||||
|
DynamicJsonDocument play(capacity); // building JSON Buffer
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(play, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t time = play["tm"]; // Time Window To Play
|
||||||
|
uint16_t timer = time;
|
||||||
|
uint16_t limit = play["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = play["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
play.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Send Initial Display
|
||||||
|
dualcomm(timeAttack_data_json(timer, 0, 0, 0));
|
||||||
|
|
||||||
|
// Start LED Signal
|
||||||
|
TimeAttack_Start();
|
||||||
|
|
||||||
|
// Building Timers 1000mSec -> 1Sec
|
||||||
|
TimeTrigger sec_tick(1000);
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
// store the time of the previous kick
|
||||||
|
unsigned long lastStamp = 0;
|
||||||
|
|
||||||
|
// reseting time ticker
|
||||||
|
sec_tick.Reset();
|
||||||
|
|
||||||
|
// While The Game Is Still On
|
||||||
|
while(timer != 0)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readString();
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
timer = time;
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
sec_tick.Reset();
|
||||||
|
dualcomm(timeAttack_data_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Kick ---------------------------->>>
|
||||||
|
if(readImpact() > 100)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(timeAttack_data_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Second ---------------------------->>>
|
||||||
|
if(sec_tick.Trigger())
|
||||||
|
{
|
||||||
|
timer--;
|
||||||
|
dualcomm(timeAttack_data_json(timer, counter, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send End Game Signal To Smart Phone
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
LED_RED_FADEIN(); // RED Color
|
||||||
|
delay(2000); // Delay 2000
|
||||||
|
LED_CLEAR(); // CLEAR OFF
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// TIME ATTACK KICK DATA JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String timeAttack_data_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
DynamicJsonDocument data(capacity);
|
||||||
|
data["tm"] = RunningTime;
|
||||||
|
data["ct"] = KickCount;
|
||||||
|
|
||||||
|
// Calculations
|
||||||
|
if(TimeStamp > 0 )
|
||||||
|
{
|
||||||
|
// Calculate Time Stamp In Seconds
|
||||||
|
float st = TimeStamp;
|
||||||
|
st /= 1000;
|
||||||
|
data["st"] = String(st, 3).toFloat();
|
||||||
|
|
||||||
|
// Calculate Strike Delay In Seconds
|
||||||
|
float dl = TimeStamp - LastStamp;
|
||||||
|
dl /= 1000;
|
||||||
|
data["dl"] = String(dl, 3).toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(data, output);
|
||||||
|
data.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void TimeAttack_Start()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
LED_WHITE_CROSSFADE(2);
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN_FADEIN();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void TimeAttack_End()
|
||||||
|
{
|
||||||
|
// Grean Light In
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
// Red Light In
|
||||||
|
LED_RED_FADEIN();
|
||||||
|
// Wait For 2 Sec
|
||||||
|
delay(2000);
|
||||||
|
// Red Light Out
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void TimeAttack_Celebration()
|
||||||
|
{
|
||||||
|
// LightUp
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void TimeAttack_Reset()
|
||||||
|
{
|
||||||
|
LED_BLUE();
|
||||||
|
delay(250);
|
||||||
|
LED_BLUE_FADEOUT();
|
||||||
|
}
|
||||||
209
Firmware Code/kicker_rev_1/kicker_rev_1.ino
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
//======================================================
|
||||||
|
// LIBRARIES
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
#include <Button.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <TimeTrigger.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
#ifdef __AVR__
|
||||||
|
#include <avr/power.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// MODE SELECTION VARIABLES
|
||||||
|
int mode;
|
||||||
|
bool flagChange = false;
|
||||||
|
|
||||||
|
// FIXED MESSAGES
|
||||||
|
#define POWERUP "{\"status\":\"POWER UP\"}"
|
||||||
|
#define UNDERSTOOD "{\"status\":\"OK\"}"
|
||||||
|
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
|
||||||
|
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
|
||||||
|
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
|
||||||
|
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
|
||||||
|
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
|
||||||
|
|
||||||
|
// GAME NAMES
|
||||||
|
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
|
||||||
|
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
|
||||||
|
#define GM_REACTION "{\"gm\":\"REACTION\"}"
|
||||||
|
#define GM_DECISION "{\"gm\":\"DECISION\"}"
|
||||||
|
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
|
||||||
|
|
||||||
|
// COMMAND LIST
|
||||||
|
#define CM_START "{\"cm\":\"START\"}"
|
||||||
|
#define CM_RESET "{\"cm\":\"RESET\"}"
|
||||||
|
#define CM_STOP "{\"cm\":\"STOP\"}"
|
||||||
|
#define CM_EXIT "{\"cm\":\"EXIT\"}"
|
||||||
|
|
||||||
|
// JSON CAPACITY
|
||||||
|
#define capacity 250
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// HARDWARE SELECTION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define VTH 65 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define PWR 65 // MIN THRESHOLD VOLTAGE FROM ZERO POINT TO BE ACCOUNTED AS KICK
|
||||||
|
#define NUM_PIXELS 24 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
|
||||||
|
// Incase You Are Using Arduino MEGA
|
||||||
|
#ifdef ARDUINO_AVR_MEGA2560
|
||||||
|
|
||||||
|
#define Bluetooth Serial1
|
||||||
|
Button button(52); // BUTTON ON PIN 2
|
||||||
|
#define LED_STRIP 53 // LED STRIP PIN NUMBER
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// Incase You Are Using Arduino Nano
|
||||||
|
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
|
||||||
|
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
//----------------------------------------------------------
|
||||||
|
SoftwareSerial Bluetooth(10, 11); // RX, TX
|
||||||
|
Button button(2); // BUTTON ON PIN 2
|
||||||
|
#define LED_STRIP A1 // LED STRIP PIN NUMBER
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A4 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// if This Was The ESP32 Core
|
||||||
|
#elif ESP32
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
#include <BluetoothSerial.h>
|
||||||
|
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||||
|
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||||
|
#endif
|
||||||
|
//----------------------------------------------------------
|
||||||
|
BluetoothSerial Bluetooth;
|
||||||
|
Button button(2); // BUTTON ON PIN 2
|
||||||
|
#define LED_STRIP 33 // LED STRIP PIN NUMBER
|
||||||
|
#define SENSOR_PIN 39 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// End Of Arduino Selection ARDUINO_MEGA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// DEFINITION & DECLERATIONS
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Serial Flags
|
||||||
|
#define isBluetooth Bluetooth.available()
|
||||||
|
#define isTerminal Terminal.available()
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// READING IMPACT POWER FROM ANALOG PINS
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// READING THE IMPACT
|
||||||
|
int readImpact()
|
||||||
|
{
|
||||||
|
int value = abs(constrain(analogRead(SENSOR_PIN), VTH, 1023));
|
||||||
|
value = map(value, VTH, 1023, 0, 1023);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN HARDWARE SETUP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Communications
|
||||||
|
Terminal.begin(9600);
|
||||||
|
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
Bluetooth.begin("KICKER"); //Bluetooth device name
|
||||||
|
#else
|
||||||
|
Bluetooth.begin(9600);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// I/O
|
||||||
|
button.begin(); // Button
|
||||||
|
pixels.begin(); // Neo Pixel
|
||||||
|
LED_CLEAR(); // Turn Off All LED
|
||||||
|
|
||||||
|
// The Random Number Source
|
||||||
|
randomSeed(analogRead(RANDOM_SOURCE));
|
||||||
|
|
||||||
|
// POWER UP MESSGAE
|
||||||
|
dualcomm(POWERUP);
|
||||||
|
|
||||||
|
// Display Color Wipe
|
||||||
|
colorWipe(pixels.Color(255, 255, 255), 15); // White
|
||||||
|
delay(100);
|
||||||
|
colorWipe(pixels.Color(0, 0, 255), 15); // Blue
|
||||||
|
delay(100);
|
||||||
|
colorWipe(pixels.Color(255, 0, 0), 15); // Red
|
||||||
|
delay(100);
|
||||||
|
colorWipe(pixels.Color(0, 255, 0), 15); // Green
|
||||||
|
|
||||||
|
// Delay 1 Sec
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Red FadeOut
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
|
||||||
|
// Display Rainbow
|
||||||
|
LED_CLEAR();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Reading From Bluetooth
|
||||||
|
if(Bluetooth.available())
|
||||||
|
{
|
||||||
|
// Reading Message From Bluetooth
|
||||||
|
String msg = Bluetooth.readString();
|
||||||
|
msg.trim();
|
||||||
|
|
||||||
|
// Display On Sertial
|
||||||
|
terminal(msg);
|
||||||
|
|
||||||
|
// Parsing Objects Message Objects
|
||||||
|
DynamicJsonDocument root(capacity);
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(root, msg);
|
||||||
|
|
||||||
|
// If The System Understood The Message Clearly
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
// Sending Status Message
|
||||||
|
dualcomm(UNDERSTOOD);
|
||||||
|
|
||||||
|
// Reading Game Name & Settings
|
||||||
|
String game = root["gm"];
|
||||||
|
String settings = root["set"];
|
||||||
|
|
||||||
|
// Clearing JSON Buffer
|
||||||
|
root.clear();
|
||||||
|
|
||||||
|
// Entering To Game Selector
|
||||||
|
game_selector(game, settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal(JSON_ERROR);
|
||||||
|
}
|
||||||
|
Bluetooth.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END OF PROGRAM
|
||||||
|
//======================================================
|
||||||
350
Firmware Code/kicker_rev_1/neo_pixel.ino
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
#define BETWEEN_FADE 15
|
||||||
|
#define FADE_RATE 15
|
||||||
|
#define BLINK_RATE 250
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// SET STRIP COLOR
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void rgbLED(int red, int green, int blue)
|
||||||
|
{
|
||||||
|
for(int i=0; i<NUM_PIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, pixels.Color(red,green,blue));
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// CLEAR SIGNAL LED COLOR : NO COLOR
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_CLEAR()
|
||||||
|
{
|
||||||
|
rgbLED(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// RED
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_RED()
|
||||||
|
{
|
||||||
|
rgbLED(255, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_RED_BLINK(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_RED();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEIN
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_RED_FADEIN()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=0; i<=255; i=i+5)
|
||||||
|
{
|
||||||
|
rgbLED(i, 0, 0);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEOUT
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_RED_FADEOUT()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=255; i>=0; i=i-5)
|
||||||
|
{
|
||||||
|
rgbLED(i, 0, 0);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// CROSS FADE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_RED_CROSSFADE(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_RED_FADEIN();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
LED_RED_FADEOUT();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// GREEN
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_GREEN()
|
||||||
|
{
|
||||||
|
rgbLED(0, 255, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_GREEN_BLINK(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_GREEN();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEIN
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_GREEN_FADEIN()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=0; i<=255; i=i+5)
|
||||||
|
{
|
||||||
|
rgbLED(0, i, 0);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEOUT
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_GREEN_FADEOUT()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=255; i>=0; i=i-5)
|
||||||
|
{
|
||||||
|
rgbLED(0, i, 0);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// CROSS FADE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_GREEN_CROSSFADE(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_GREEN_FADEIN();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
LED_GREEN_FADEOUT();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_BLUE()
|
||||||
|
{
|
||||||
|
rgbLED(0, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLUE_BLINK(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_BLUE();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEIN
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLUE_FADEIN()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=0; i<=255; i=i+5)
|
||||||
|
{
|
||||||
|
rgbLED(0, 0, i);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEOUT
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLUE_FADEOUT()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=255; i>=0; i=i-5)
|
||||||
|
{
|
||||||
|
rgbLED(0, 0, i);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// CROSS FADE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLUE_CROSSFADE(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_BLUE_FADEIN();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
LED_BLUE_FADEOUT();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// WHITE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_WHITE()
|
||||||
|
{
|
||||||
|
rgbLED(255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_WHITE_BLINK(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_WHITE();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEIN
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_WHITE_FADEIN()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=0; i<=255; i=i+5)
|
||||||
|
{
|
||||||
|
rgbLED(i, i, i);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// FADEOUT
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_WHITE_FADEOUT()
|
||||||
|
{
|
||||||
|
// Fade In Red Indicate That You Enter Battle
|
||||||
|
for(int i=255; i>=0; i=i-5)
|
||||||
|
{
|
||||||
|
rgbLED(i, i, i);
|
||||||
|
delay(FADE_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// CROSS FADE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_WHITE_CROSSFADE(int times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<times; i++)
|
||||||
|
{
|
||||||
|
LED_WHITE_FADEIN();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
LED_WHITE_FADEOUT();
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COLOR WHIPE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Fill the dots one after the other with a color
|
||||||
|
void colorWipe(uint32_t c, uint8_t wait)
|
||||||
|
{
|
||||||
|
for(uint16_t i=0; i<NUM_PIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, c);
|
||||||
|
pixels.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Slightly different, this makes the rainbow equally distributed throughout
|
||||||
|
void rainbowCycle(uint8_t wait)
|
||||||
|
{
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
for(j=0; j<256*5; j++)
|
||||||
|
{ // 5 cycles of all colors on wheel
|
||||||
|
for(i=0; i< pixels.numPixels(); i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, Wheel(((i * 256 / pixels.numPixels()) + j) & 255));
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Input a value 0 to 255 to get a color value.
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
uint32_t Wheel(byte WheelPos)
|
||||||
|
{
|
||||||
|
WheelPos = 255 - WheelPos;
|
||||||
|
if(WheelPos < 85)
|
||||||
|
{
|
||||||
|
return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
|
||||||
|
}
|
||||||
|
if(WheelPos < 170)
|
||||||
|
{
|
||||||
|
WheelPos -= 85;
|
||||||
|
return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
|
||||||
|
}
|
||||||
|
WheelPos -= 170;
|
||||||
|
return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
|
||||||
|
}
|
||||||
29
Firmware Code/kicker_rev_2/communication.ino
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//======================================================
|
||||||
|
// TERMINAL WINDOW - NATIVE USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void terminal(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Terminal.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void bluetooth(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Bluetooth.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void dualcomm(String msg)
|
||||||
|
{
|
||||||
|
terminal(msg);
|
||||||
|
bluetooth(msg);
|
||||||
|
}
|
||||||
137
Firmware Code/kicker_rev_2/game_counter.ino
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN COUNTER GAME LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* --------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* ct : count
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* WHAT JSON TO BE COLLECTED :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
|
||||||
|
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* No calculation required, Its directly the count
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_counter(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Trying To Delete The Document
|
||||||
|
//JSON.delete();
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// Game Start Lights
|
||||||
|
LED_SIGNAL_START();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
LED_SIGNAL_RESET();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebration
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Impact
|
||||||
|
if(readImpact() > VTH)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(counter_JSON_json(counter, timeStamp));
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER JSON JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String counter_JSON_json(unsigned int ct, unsigned int st)
|
||||||
|
{
|
||||||
|
// Convert Int To Float
|
||||||
|
float stamp = st;
|
||||||
|
stamp /= 1000;
|
||||||
|
|
||||||
|
// Assignning JSONset
|
||||||
|
JSON["ct"] = ct;
|
||||||
|
JSON["st"] = String(stamp, 3).toFloat();
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
203
Firmware Code/kicker_rev_2/game_reaction.ino
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
//======================================================
|
||||||
|
// REACTION GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* REACTION GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tr": 10, "mn": 1, "mx": 2}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* tr : trials pre counter
|
||||||
|
* mn : minimum delay, between trials
|
||||||
|
* mx : maximum delay, between trials
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tr" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_reaction(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings);
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint8_t minDelay = JSON["mn"];
|
||||||
|
uint8_t maxDelay = JSON["mx"];
|
||||||
|
uint16_t trials = JSON["lm"];
|
||||||
|
uint16_t temp = trials;
|
||||||
|
|
||||||
|
// Fix Random Error
|
||||||
|
maxDelay += 1;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// DisJSON Welcome Message
|
||||||
|
terminal("");
|
||||||
|
terminal("trials : " + String(trials) + " Strikes");
|
||||||
|
terminal("minDelay : " + String(minDelay) + " Seconds");
|
||||||
|
terminal("maxDelay : " + String(maxDelay) + " Seconds");
|
||||||
|
terminal("2 Seconds To Start Get Ready & Good Luck !!");
|
||||||
|
terminal("");
|
||||||
|
|
||||||
|
// Ready Signal
|
||||||
|
LED_SIGNAL_REACTION_START();
|
||||||
|
|
||||||
|
// Main Variables
|
||||||
|
uint16_t sdelay = 0;
|
||||||
|
uint16_t power = 0;
|
||||||
|
uint16_t response = 0;
|
||||||
|
unsigned long startTime = 0;
|
||||||
|
unsigned long stopTime = 0;
|
||||||
|
|
||||||
|
// Processing Results
|
||||||
|
for(int i=0; i<trials; i++)
|
||||||
|
{
|
||||||
|
// Reading Kick JSON
|
||||||
|
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
|
||||||
|
terminal(" -> Get Ready !!");
|
||||||
|
|
||||||
|
// Set Random Delay Time
|
||||||
|
sdelay = random(minDelay, maxDelay);
|
||||||
|
sdelay *= 1000;
|
||||||
|
delay(sdelay);
|
||||||
|
|
||||||
|
// Light Up Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
|
||||||
|
// Start Timer
|
||||||
|
startTime = millis();
|
||||||
|
|
||||||
|
// Sensing Strike Power
|
||||||
|
while(power < VTH)
|
||||||
|
{
|
||||||
|
// Reading The Strike
|
||||||
|
power = readImpact();
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP) {
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET) {
|
||||||
|
LED_SIGNAL_REACTION_RESET();
|
||||||
|
trials = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop Timer
|
||||||
|
stopTime = millis();
|
||||||
|
|
||||||
|
// Stop Light
|
||||||
|
LED_SET_COLOR(255, 0, 0, 255);
|
||||||
|
|
||||||
|
// Calculating Response Time
|
||||||
|
response = stopTime - startTime - 1;
|
||||||
|
|
||||||
|
// Create Json JSON
|
||||||
|
String msg = reaction_JSON_json(i+1, power, response, sdelay);
|
||||||
|
|
||||||
|
// Print To Terminal
|
||||||
|
dualcomm(msg);
|
||||||
|
|
||||||
|
// Clear All
|
||||||
|
sdelay = 0;
|
||||||
|
power = 0;
|
||||||
|
response = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red Light Delay
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
|
||||||
|
// Blink Red
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
|
||||||
|
// Return To Game Selector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION JSON JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
|
||||||
|
{
|
||||||
|
// Convert To Seconds Unit
|
||||||
|
float re = response;
|
||||||
|
re /= 1000;
|
||||||
|
|
||||||
|
// Asignning Values
|
||||||
|
JSON["ct"] = count; // Strike Number
|
||||||
|
JSON["pw"] = power; // Strike Power In Analog Read
|
||||||
|
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
|
||||||
|
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_REACTION_START()
|
||||||
|
{
|
||||||
|
// Cross fade the white signal to get ready
|
||||||
|
LED_CROSS_FADE(255, 255, 255, 3);
|
||||||
|
// Set the LED strip color to red
|
||||||
|
LED_SET_COLOR(255, 0, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_REACTION_RESET()
|
||||||
|
{
|
||||||
|
// Light Bright Blue
|
||||||
|
LED_BLINK(0, 0, 255, 2);
|
||||||
|
// Wait For 1/4 Second
|
||||||
|
delay(250);
|
||||||
|
// Fade Out The Blue
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
37
Firmware Code/kicker_rev_2/game_selector.ino
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* game selector is the main function that tell the game groutine
|
||||||
|
* which game to be JSONed and at what parameters
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_selector(String game, String settings)
|
||||||
|
{
|
||||||
|
// Kick Counter Game
|
||||||
|
if(game == "ct") {
|
||||||
|
terminal(GM_COUNTER);
|
||||||
|
game_counter(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ta") {
|
||||||
|
terminal(GM_TATTACK);
|
||||||
|
game_timeAttack(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ra") {
|
||||||
|
terminal(GM_REACTION);
|
||||||
|
game_reaction(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown Game
|
||||||
|
else {
|
||||||
|
dualcomm(UNKNOWN_GAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
184
Firmware Code/kicker_rev_2/game_time_attack.ino
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
//======================================================
|
||||||
|
// TIME ATTACK GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tm": 10, "le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* tm : count down timer starting value
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tm" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
|
||||||
|
*
|
||||||
|
* RETURNNING JSON FORMAT :
|
||||||
|
* ------------------------
|
||||||
|
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
|
||||||
|
*
|
||||||
|
* tm : timer count in Sec
|
||||||
|
* ct : strike counter (number of kicks)
|
||||||
|
* dl : delay between strikes
|
||||||
|
* st : time stampe of the strike in milli Seconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_timeAttack(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t time = JSON["tm"]; // Time Window To JSON
|
||||||
|
uint16_t timer = time;
|
||||||
|
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Send Initial DisJSON
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, 0, 0, 0));
|
||||||
|
|
||||||
|
// Start LED Signal
|
||||||
|
LED_SIGNAL_START();
|
||||||
|
|
||||||
|
// Building Timers 1000mSec -> 1Sec
|
||||||
|
TimeTrigger sec_tick(1000);
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
// store the time of the previous kick
|
||||||
|
unsigned long lastStamp = 0;
|
||||||
|
|
||||||
|
// reseting time ticker
|
||||||
|
sec_tick.Reset();
|
||||||
|
|
||||||
|
// While The Game Is Still On
|
||||||
|
while(timer != 0)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
timer = time;
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
sec_tick.Reset();
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
LED_SIGNAL_RESET();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Kick ---------------------------->>>
|
||||||
|
if(readImpact() > VTH)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Second ---------------------------->>>
|
||||||
|
if(sec_tick.Trigger())
|
||||||
|
{
|
||||||
|
timer--;
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebrate
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send End Game Signal To Smart Phone
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
LED_FADEIN(255, 0, 0); // RED Color
|
||||||
|
delay(2000); // Delay 2000
|
||||||
|
LED_CLEAR(); // CLEAR OFF
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// TIME ATTACK KICK JSON JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
JSON["tm"] = RunningTime;
|
||||||
|
JSON["ct"] = KickCount;
|
||||||
|
|
||||||
|
// Calculations
|
||||||
|
if(TimeStamp > 0)
|
||||||
|
{
|
||||||
|
// Calculate Time Stamp In Seconds
|
||||||
|
float st = TimeStamp;
|
||||||
|
st /= 1000;
|
||||||
|
JSON["st"] = String(st, 3).toFloat();
|
||||||
|
|
||||||
|
// Calculate Strike Delay In Seconds
|
||||||
|
float dl = TimeStamp - LastStamp;
|
||||||
|
dl /= 1000;
|
||||||
|
JSON["dl"] = String(dl, 3).toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
197
Firmware Code/kicker_rev_2/kicker_rev_2.ino
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
//======================================================
|
||||||
|
// LIBRARIES
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <TimeTrigger.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
#ifdef __AVR__
|
||||||
|
#include <avr/power.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// JSON STRINGS AND DOCUMENT
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// FIXED MESSAGES
|
||||||
|
#define POWERUP "{\"status\":\"POWER UP\"}"
|
||||||
|
#define UNDERSTOOD "{\"status\":\"OK\"}"
|
||||||
|
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
|
||||||
|
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
|
||||||
|
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
|
||||||
|
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
|
||||||
|
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
|
||||||
|
|
||||||
|
// GAME NAMES
|
||||||
|
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
|
||||||
|
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
|
||||||
|
#define GM_REACTION "{\"gm\":\"REACTION\"}"
|
||||||
|
#define GM_DECISION "{\"gm\":\"DECISION\"}"
|
||||||
|
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
|
||||||
|
|
||||||
|
// COMMAND LIST
|
||||||
|
#define CM_START "{\"cm\":\"START\"}"
|
||||||
|
#define CM_RESET "{\"cm\":\"RESET\"}"
|
||||||
|
#define CM_STOP "{\"cm\":\"STOP\"}"
|
||||||
|
#define CM_EXIT "{\"cm\":\"EXIT\"}"
|
||||||
|
|
||||||
|
// JSON CAPACITY
|
||||||
|
#define CAPACITY 100
|
||||||
|
|
||||||
|
// Public JSON Document
|
||||||
|
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// HARDWARE SETUP & SELECTION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Arduino Hardware Serial Port
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
|
||||||
|
// The Integer Value Of The Strike Is Exceeded Accept As A Point
|
||||||
|
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
|
||||||
|
// Number Of LED's In The Neo Pixel Strip
|
||||||
|
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
|
||||||
|
// Incase You Are Using Arduino MEGA
|
||||||
|
#ifdef ARDUINO_AVR_MEGA2560
|
||||||
|
|
||||||
|
#define Bluetooth Serial1 // We will Connect The HC-05 To Hardware Serial1 In Arduino Mega
|
||||||
|
#define LED_STRIP 53 // LED STRIP PIN NUMBER
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// Incase You Are Using Arduino Nano
|
||||||
|
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
|
||||||
|
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
//----------------------------------------------------------
|
||||||
|
SoftwareSerial Bluetooth(10, 11); // Pin 10 RX, Pin 11 TX
|
||||||
|
#define LED_STRIP 2 // LED STRIP PIN NUMBER
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A4 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// if This Was The ESP32 Core
|
||||||
|
#elif ESP32
|
||||||
|
|
||||||
|
//----------------------------------------------------------
|
||||||
|
#include <BluetoothSerial.h>
|
||||||
|
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||||
|
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||||
|
#endif
|
||||||
|
//----------------------------------------------------------
|
||||||
|
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
|
||||||
|
#define LED_STRIP 33 // LED STRIP PIN NUMBER
|
||||||
|
#define SENSOR_PIN 39 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
// End Of Arduino Selection ARDUINO_MEGA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// DEFINITION & DECLERATIONS
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Serial Flags
|
||||||
|
#define isBluetooth Bluetooth.available()
|
||||||
|
#define isTerminal Terminal.available()
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// READING IMPACT POWER FROM ANALOG PINS
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// READING THE IMPACT
|
||||||
|
int readImpact()
|
||||||
|
{
|
||||||
|
int value = analogRead(SENSOR_PIN);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN HARDWARE SETUP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Communications
|
||||||
|
Terminal.begin(9600);
|
||||||
|
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
Bluetooth.begin("KICKER"); //Bluetooth device name
|
||||||
|
#else
|
||||||
|
Bluetooth.begin(9600);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// I/O
|
||||||
|
pixels.begin(); // Neo Pixel
|
||||||
|
LED_CLEAR(); // Turn Off All LED
|
||||||
|
|
||||||
|
// The Random Number Source
|
||||||
|
randomSeed(analogRead(RANDOM_SOURCE));
|
||||||
|
|
||||||
|
// POWER UP MESSGAE
|
||||||
|
dualcomm(POWERUP);
|
||||||
|
|
||||||
|
// DISPLAY COMPANY COUNTRY FLAG
|
||||||
|
LED_BAHRAIN_FLAG(); // Bahrain Flag
|
||||||
|
LED_COLOMBIA_FLAG(); // Colombia Flag
|
||||||
|
|
||||||
|
// DisJSON Rainbow
|
||||||
|
LED_CLEAR();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Reading From Bluetooth
|
||||||
|
if(Bluetooth.available())
|
||||||
|
{
|
||||||
|
// Reading Message From Bluetooth
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
msg.trim();
|
||||||
|
|
||||||
|
// DisJSON On Sertial
|
||||||
|
terminal(msg);
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, msg);
|
||||||
|
|
||||||
|
// If The System Understood The Message Clearly
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
// Sending Status Message
|
||||||
|
dualcomm(UNDERSTOOD);
|
||||||
|
|
||||||
|
// Reading Game Name & Settings
|
||||||
|
String game = JSON["gm"];
|
||||||
|
String settings = JSON["set"];
|
||||||
|
|
||||||
|
// Clearing JSON Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Entering To Game Selector
|
||||||
|
game_selector(game, settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal(JSON_ERROR);
|
||||||
|
}
|
||||||
|
Bluetooth.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END OF PROGRAM
|
||||||
|
//======================================================
|
||||||
244
Firmware Code/kicker_rev_2/neo_pixel.ino
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
#define BETWEEN_FADE 15
|
||||||
|
#define FADE_RATE 15
|
||||||
|
#define BLINK_RATE 250
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<Times; i++)
|
||||||
|
{
|
||||||
|
LED_SET_COLOR(R, G, B, 255);
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// COLOR WHIPE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Fill the dots one after the other with a color
|
||||||
|
void colorWipe(uint32_t c, uint8_t wait)
|
||||||
|
{
|
||||||
|
for(uint16_t i=0; i<NUM_PIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, c);
|
||||||
|
pixels.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Slightly different, this makes the rainbow equally distributed throughout
|
||||||
|
void rainbowCycle(uint8_t wait)
|
||||||
|
{
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
for(j=0; j<256*5; j++)
|
||||||
|
{ // 5 cycles of all colors on WHEEL
|
||||||
|
for(i=0; i< pixels.numPixels(); i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, WHEEL(((i * 256 / pixels.numPixels()) + j) & 255));
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Input a value 0 to 255 to get a color value.
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
uint32_t WHEEL(byte WHEELPos)
|
||||||
|
{
|
||||||
|
WHEELPos = 255 - WHEELPos;
|
||||||
|
if(WHEELPos < 85)
|
||||||
|
{
|
||||||
|
return pixels.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
|
||||||
|
}
|
||||||
|
if(WHEELPos < 170)
|
||||||
|
{
|
||||||
|
WHEELPos -= 85;
|
||||||
|
return pixels.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
|
||||||
|
}
|
||||||
|
WHEELPos -= 170;
|
||||||
|
return pixels.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Brightness
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SET_BRIGHTNESS(uint8_t Value)
|
||||||
|
{
|
||||||
|
pixels.setBrightness(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Color
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
|
||||||
|
{
|
||||||
|
// Set Intensity
|
||||||
|
LED_SET_BRIGHTNESS(Intensity);
|
||||||
|
|
||||||
|
// Loop
|
||||||
|
for(int i=0; i<NUM_PIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set Color Fade In
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
|
||||||
|
{
|
||||||
|
for(int i=0; i<=255; i++)
|
||||||
|
{
|
||||||
|
pixels.setBrightness(i);
|
||||||
|
for(int j=0; j<NUM_PIXELS; j++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(j, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
delay(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set Color Fade Out
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
|
||||||
|
{
|
||||||
|
for(int i=255; i>=0; i--)
|
||||||
|
{
|
||||||
|
pixels.setBrightness(i);
|
||||||
|
for(int j=0; j<NUM_PIXELS; j++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(j, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
delay(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Color Cross Fade
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<Times; i++) {
|
||||||
|
LED_FADEIN(R, G, B);
|
||||||
|
LED_FADEOUT(R, G, B);
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Clearing The LED Strip
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_CLEAR()
|
||||||
|
{
|
||||||
|
// Clear The Strip Color
|
||||||
|
pixels.clear();
|
||||||
|
// Show The Change
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_START()
|
||||||
|
{
|
||||||
|
// Cross Fade White Color To Get ready 3 Times
|
||||||
|
LED_CROSS_FADE(255, 255, 255, 3);
|
||||||
|
// Set Strip Color Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_END()
|
||||||
|
{
|
||||||
|
// Blink Red Twice
|
||||||
|
LED_BLINK(255, 0, 0, 2);
|
||||||
|
// Fade The Red Color To Nothing
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_CELEBRATION()
|
||||||
|
{
|
||||||
|
// Display Rainbow Twice
|
||||||
|
rainbowCycle(2);
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_FADEOUT(0, 255, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_RESET()
|
||||||
|
{
|
||||||
|
// Light Bright Blue
|
||||||
|
LED_BLINK(0, 0, 255, 2);
|
||||||
|
// Wait For 1/4 Second
|
||||||
|
delay(250);
|
||||||
|
// Fade Out The Blue
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
// Set Strip Color Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// DISPLAY BAHRAIN FLAG
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_BAHRAIN_FLAG()
|
||||||
|
{
|
||||||
|
LED_SET_BRIGHTNESS(255);
|
||||||
|
colorWipe(pixels.Color(255, 255, 255), 30); // White
|
||||||
|
delay(250);
|
||||||
|
colorWipe(pixels.Color(255, 0, 0), 30); // Red
|
||||||
|
delay(250);
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// DISPLAY COLOMBIA FLAG
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_COLOMBIA_FLAG()
|
||||||
|
{
|
||||||
|
LED_SET_BRIGHTNESS(255);
|
||||||
|
colorWipe(pixels.Color(255, 255, 0), 30); // Yellow
|
||||||
|
delay(250);
|
||||||
|
colorWipe(pixels.Color(0, 0, 255), 30); // Blue
|
||||||
|
delay(250);
|
||||||
|
colorWipe(pixels.Color(255, 0, 0), 30); // Red
|
||||||
|
delay(250);
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
29
Firmware Code/kicker_rev_3/communication.ino
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//======================================================
|
||||||
|
// TERMINAL WINDOW - NATIVE USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void terminal(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Terminal.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void bluetooth(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Bluetooth.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void dualcomm(String msg)
|
||||||
|
{
|
||||||
|
terminal(msg);
|
||||||
|
bluetooth(msg);
|
||||||
|
}
|
||||||
178
Firmware Code/kicker_rev_3/game_counter.ino
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN COUNTER GAME LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : game_counter_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : game_counter_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// THIS IS THE STAND ALONE CALL FOR THE GAME
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_counter_standalone()
|
||||||
|
{
|
||||||
|
// Variables Of The Game
|
||||||
|
uint16_t limit = 0;
|
||||||
|
bool limitEnable = 0;
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_counter(limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// THIS IS THE BLUETOOTH CALL FOR THE GAME
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* --------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* ct : count
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* WHAT JSON TO BE COLLECTED :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
|
||||||
|
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* No calculation required, Its directly the count
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_counter_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_counter(limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER JSON JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_counter(uint16_t limit, bool limitEnable)
|
||||||
|
{
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// Game Start Lights
|
||||||
|
LED_SIGNAL_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
LED_SIGNAL_RESET();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebration
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Impact
|
||||||
|
if(readImpact() > VTH)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(counter_JSON_json(counter, timeStamp));
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER JSON -> To Send Back To Mobile
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String counter_JSON_json(unsigned int ct, unsigned int st)
|
||||||
|
{
|
||||||
|
// Convert Int To Float
|
||||||
|
float stamp = st;
|
||||||
|
stamp /= 1000;
|
||||||
|
|
||||||
|
// Assignning JSONset
|
||||||
|
JSON["ct"] = ct;
|
||||||
|
JSON["st"] = String(stamp, 3).toFloat();
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
266
Firmware Code/kicker_rev_3/game_reaction.ino
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
//======================================================
|
||||||
|
// REACTION GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : game_reaction_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : game_reaction_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Stand Alone Buttons
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_reaction_standalone()
|
||||||
|
{
|
||||||
|
// Variables
|
||||||
|
uint8_t minDelay = 0;
|
||||||
|
uint8_t maxDelay = 0;
|
||||||
|
uint8_t trials = 0;
|
||||||
|
|
||||||
|
// Display Screen Menu And Button Actions
|
||||||
|
// If The Menu Number 1 -> We Set The Value Of Min Delay
|
||||||
|
// If The Menu Number 2 -> We Set The Value Of Max Delay
|
||||||
|
// If The Menu Number 3 -> We Set The Number Of Trials
|
||||||
|
|
||||||
|
// Call the Game Play
|
||||||
|
play_reaction(minDelay, maxDelay, trials);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Bluetooth Via JSON
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* REACTION GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tr": 10, "mn": 1, "mx": 2}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* tr : trials pre counter
|
||||||
|
* mn : minimum delay, between trials
|
||||||
|
* mx : maximum delay, between trials
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tr" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_reaction_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings);
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint8_t minDelay = JSON["mn"];
|
||||||
|
uint8_t maxDelay = JSON["mx"];
|
||||||
|
uint16_t trials = JSON["lm"];
|
||||||
|
|
||||||
|
// Fix Random Error
|
||||||
|
maxDelay += 1;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
play_reaction(minDelay, maxDelay, trials);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Play The Game
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
|
||||||
|
{
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t temp = trials;
|
||||||
|
|
||||||
|
// Fix Random Error
|
||||||
|
maxDelay += 1;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// DisJSON Welcome Message
|
||||||
|
terminal("");
|
||||||
|
terminal("trials : " + String(trials) + " Strikes");
|
||||||
|
terminal("minDelay : " + String(minDelay) + " Seconds");
|
||||||
|
terminal("maxDelay : " + String(maxDelay) + " Seconds");
|
||||||
|
terminal("2 Seconds To Start Get Ready & Good Luck !!");
|
||||||
|
terminal("");
|
||||||
|
|
||||||
|
// Main Variables
|
||||||
|
uint16_t sdelay = 0;
|
||||||
|
uint16_t power = 0;
|
||||||
|
uint16_t response = 0;
|
||||||
|
unsigned long startTime = 0;
|
||||||
|
unsigned long stopTime = 0;
|
||||||
|
|
||||||
|
// Ready Signal
|
||||||
|
LED_SIGNAL_REACTION_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// Processing Results
|
||||||
|
for(int i=0; i<trials; i++)
|
||||||
|
{
|
||||||
|
// Reading Kick JSON
|
||||||
|
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
|
||||||
|
terminal(" -> Get Ready !!");
|
||||||
|
|
||||||
|
// Set Random Delay Time
|
||||||
|
sdelay = random(minDelay, maxDelay);
|
||||||
|
sdelay *= 1000;
|
||||||
|
delay(sdelay);
|
||||||
|
|
||||||
|
// Light Up Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
|
||||||
|
// Start Timer
|
||||||
|
startTime = millis();
|
||||||
|
|
||||||
|
// Sensing Strike Power
|
||||||
|
while(power < VTH)
|
||||||
|
{
|
||||||
|
// Reading The Strike
|
||||||
|
power = readImpact();
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP) {
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET) {
|
||||||
|
LED_SIGNAL_REACTION_RESET();
|
||||||
|
trials = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop Timer
|
||||||
|
stopTime = millis();
|
||||||
|
|
||||||
|
// Stop Light
|
||||||
|
LED_SET_COLOR(255, 0, 0, 255);
|
||||||
|
|
||||||
|
// Calculating Response Time
|
||||||
|
response = stopTime - startTime - 1;
|
||||||
|
|
||||||
|
// Create Json JSON
|
||||||
|
String msg = reaction_JSON_json(i+1, power, response, sdelay);
|
||||||
|
|
||||||
|
// Print To Terminal
|
||||||
|
dualcomm(msg);
|
||||||
|
|
||||||
|
// Clear All
|
||||||
|
sdelay = 0;
|
||||||
|
power = 0;
|
||||||
|
response = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red Light Delay
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
|
||||||
|
// Blink Red
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
|
||||||
|
// Return To Game Selector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION JSON -> To Send Back To Mobile Device
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
|
||||||
|
{
|
||||||
|
// Convert To Seconds Unit
|
||||||
|
float re = response;
|
||||||
|
re /= 1000;
|
||||||
|
|
||||||
|
// Asignning Values
|
||||||
|
JSON["ct"] = count; // Strike Number
|
||||||
|
JSON["pw"] = power; // Strike Power In Analog Read
|
||||||
|
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
|
||||||
|
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_REACTION_START()
|
||||||
|
{
|
||||||
|
// Cross fade the white signal to get ready
|
||||||
|
LED_CROSS_FADE(255, 255, 255, 3);
|
||||||
|
|
||||||
|
// Set the LED strip color to red
|
||||||
|
LED_SET_COLOR(255, 0, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_REACTION_RESET()
|
||||||
|
{
|
||||||
|
// Light Bright Blue
|
||||||
|
LED_BLINK(0, 0, 255, 2);
|
||||||
|
|
||||||
|
// Wait For 1/4 Second
|
||||||
|
delay(250);
|
||||||
|
|
||||||
|
// Fade Out The Blue
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
37
Firmware Code/kicker_rev_3/game_selector.ino
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* game selector is the main function that tell the game groutine
|
||||||
|
* which game to be JSONed and at what parameters
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_selector(String game, String settings)
|
||||||
|
{
|
||||||
|
// Kick Counter Game
|
||||||
|
if(game == "ct") {
|
||||||
|
terminal(GM_COUNTER);
|
||||||
|
game_counter_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ta") {
|
||||||
|
terminal(GM_TATTACK);
|
||||||
|
game_reaction_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ra") {
|
||||||
|
terminal(GM_REACTION);
|
||||||
|
game_reaction_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown Game
|
||||||
|
else {
|
||||||
|
dualcomm(UNKNOWN_GAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
231
Firmware Code/kicker_rev_3/game_time_attack.ino
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
//======================================================
|
||||||
|
// TIME ATTACK GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : time_attack_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : time_attack_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Stand Alone Buttons
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void time_attack_standalone()
|
||||||
|
{
|
||||||
|
// Variables
|
||||||
|
uint16_t time = 0;
|
||||||
|
uint16_t timer = 0;
|
||||||
|
uint16_t limit = 0;
|
||||||
|
bool limitEnable = 0;
|
||||||
|
|
||||||
|
// Display Screen Menu And Button Actions
|
||||||
|
// If The Menu Number 1 -> We Set The Value Of Min Delay
|
||||||
|
// If The Menu Number 2 -> We Set The Value Of Max Delay
|
||||||
|
// If The Menu Number 3 -> We Set The Number Of Trials
|
||||||
|
|
||||||
|
// Call the Game Play
|
||||||
|
game_timeAttack(time, timer, limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Bluetooth Via JSON
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tm": 10, "le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* tm : count down timer starting value
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tm" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
|
||||||
|
*
|
||||||
|
* RETURNNING JSON FORMAT :
|
||||||
|
* ------------------------
|
||||||
|
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
|
||||||
|
*
|
||||||
|
* tm : timer count in Sec
|
||||||
|
* ct : strike counter (number of kicks)
|
||||||
|
* dl : delay between strikes
|
||||||
|
* st : time stampe of the strike in milli Seconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
void time_attack_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t time = JSON["tm"]; // Time Window To JSON
|
||||||
|
uint16_t timer = time;
|
||||||
|
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_timeAttack(time, timer, limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Play Time Atack Game
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_timeAttack(uint16_t time, uint16_t timer, uint16_t limit, bool limitEnable)
|
||||||
|
{
|
||||||
|
// Building Timers 1000mSec -> 1Sec
|
||||||
|
TimeTrigger sec_tick(1000);
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// Start LED Signal
|
||||||
|
LED_SIGNAL_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// Send Initial DisJSON
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
// store the time of the previous kick
|
||||||
|
unsigned long lastStamp = 0;
|
||||||
|
|
||||||
|
// reseting time ticker
|
||||||
|
sec_tick.Reset();
|
||||||
|
|
||||||
|
// While The Game Is Still On
|
||||||
|
while(timer != 0)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
timer = time;
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
sec_tick.Reset();
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
LED_SIGNAL_RESET();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Kick ---------------------------->>>
|
||||||
|
if(readImpact() > VTH)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Second ---------------------------->>>
|
||||||
|
if(sec_tick.Trigger())
|
||||||
|
{
|
||||||
|
timer--;
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebrate
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send End Game Signal To Smart Phone
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
LED_FADEIN(255, 0, 0); // RED Color
|
||||||
|
delay(2000); // Delay 2000
|
||||||
|
LED_CLEAR(); // CLEAR OFF
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// TIME ATTACK KICK JSON -> To Send Back To Mobile
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
JSON["tm"] = RunningTime;
|
||||||
|
JSON["ct"] = KickCount;
|
||||||
|
|
||||||
|
// Calculations
|
||||||
|
if(TimeStamp > 0)
|
||||||
|
{
|
||||||
|
// Calculate Time Stamp In Seconds
|
||||||
|
float st = TimeStamp;
|
||||||
|
st /= 1000;
|
||||||
|
JSON["st"] = String(st, 3).toFloat();
|
||||||
|
|
||||||
|
// Calculate Strike Delay In Seconds
|
||||||
|
float dl = TimeStamp - LastStamp;
|
||||||
|
dl /= 1000;
|
||||||
|
JSON["dl"] = String(dl, 3).toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
296
Firmware Code/kicker_rev_3/kicker_rev_3.ino
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
//======================================================
|
||||||
|
// LIBRARIES
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Library Include
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <TimeTrigger.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// HARDWARE SETUP & SELECTION
|
||||||
|
//======================================================
|
||||||
|
// Arduino MEGA
|
||||||
|
#ifdef ARDUINO_AVR_MEGA2560
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Library Nessesary
|
||||||
|
#ifdef __AVR__
|
||||||
|
#include <avr/power.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Serial Terminal
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
|
||||||
|
#define flushTerminal while(isTerminal) { Terminal.read(); }
|
||||||
|
|
||||||
|
// Bluetooth Terminal
|
||||||
|
#define Bluetooth Serial1 // We will Connect The HC-05 To Hardware Serial1 In Arduino Mega
|
||||||
|
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
|
||||||
|
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
|
||||||
|
|
||||||
|
// JSON Object & Memory
|
||||||
|
#define CAPACITY 100
|
||||||
|
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||||
|
|
||||||
|
// LED Strip
|
||||||
|
#define LED_STRIP 53 // LED STRIP PIN NUMBER
|
||||||
|
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
// Impact Detection
|
||||||
|
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Arduino Uno / Nano
|
||||||
|
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Library Nessesary
|
||||||
|
#ifdef __AVR__
|
||||||
|
#include <avr/power.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
|
||||||
|
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
|
||||||
|
// Serial Terminal
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
|
||||||
|
#define flushTerminal while(isTerminal) { Terminal.read(); }
|
||||||
|
|
||||||
|
// Bluetooth Terminal
|
||||||
|
SoftwareSerial Bluetooth(10, 11); // Pin 10 RX, Pin 11 TX
|
||||||
|
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
|
||||||
|
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
|
||||||
|
|
||||||
|
// JSON Object & Memory
|
||||||
|
#define CAPACITY 100
|
||||||
|
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||||
|
|
||||||
|
// LED Strip
|
||||||
|
#define LED_STRIP 2 // LED STRIP PIN NUMBER
|
||||||
|
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
// Impact Detection
|
||||||
|
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A4 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// ESP32 TAKEONE BOARD
|
||||||
|
#elif ESP32
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
/* ===============================================
|
||||||
|
* - THIS IS TAKEONE BOARD -
|
||||||
|
* ===============================================
|
||||||
|
* MPU9250 Address : 0X69 (ADDRESS)
|
||||||
|
* OLED 128x64 Address : 0X3C (ADDRESS)
|
||||||
|
* -----------------------------------------------
|
||||||
|
* Description : PIN GPIO#
|
||||||
|
* -----------------------------------------------
|
||||||
|
* NEOPIXEL LED STRIP : A0/GPIO 26
|
||||||
|
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
|
||||||
|
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
|
||||||
|
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
|
||||||
|
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
|
||||||
|
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
|
||||||
|
* LED PIN : 13 (DIGITAL)
|
||||||
|
* BATTERY MONITOR PIN : 35 (ANALOG)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ESP32 HAVE A NATIVE BLUETOOTH MODULE
|
||||||
|
SO WE USE BLUETOOTH SERIAL LIBRARY */
|
||||||
|
#include <BluetoothSerial.h>
|
||||||
|
|
||||||
|
// Nessesary Definition For Bluetooth Library
|
||||||
|
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||||
|
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Serial Terminal
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
|
||||||
|
#define flushTerminal while(isTerminal) { Terminal.read(); }
|
||||||
|
|
||||||
|
// Bluetooth Terminal
|
||||||
|
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
|
||||||
|
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
|
||||||
|
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
|
||||||
|
|
||||||
|
// JSON Object & Memory
|
||||||
|
#define CAPACITY 100
|
||||||
|
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||||
|
|
||||||
|
// LED Strip
|
||||||
|
#define LED_STRIP 33 // LED STRIP PIN NUMBER
|
||||||
|
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
// Impact Detection
|
||||||
|
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define SENSOR_PIN 39 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Exclusive Features Of TAKEONE BOARD
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
/* ESP32 TAKEONE Board has some unique hardware features
|
||||||
|
* 1. Battery Voltage Level Monitoring Via Analog Pin 35
|
||||||
|
* 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery
|
||||||
|
* 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom
|
||||||
|
* 4. SPI : SDCARD Reader */
|
||||||
|
|
||||||
|
// Boost Converter
|
||||||
|
#define BOOST_PIN 14
|
||||||
|
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
|
||||||
|
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
|
||||||
|
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
|
||||||
|
#define BOOST_STU digitalRead(BOOST_PIN)
|
||||||
|
|
||||||
|
// Battery Level Monitoring
|
||||||
|
#define BATTERY_PIN 35
|
||||||
|
#define BATTERY (float)(((analogRead(BATTERY_PIN) * (3.3 / 4096)) * 2) + 0.31)
|
||||||
|
#define CHARGE round(mapf(BATTERY, 3.27, 4.31, 0, 100), 1)
|
||||||
|
|
||||||
|
// Function To Make Sure The Pin Is ON
|
||||||
|
void LED_BOOST_CHK() {
|
||||||
|
if(BOOST_STU == LOW) {
|
||||||
|
BOOST_ON;
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floting Point Mapping
|
||||||
|
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
|
||||||
|
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// PREDEFINED JSON STRINGS MESSAGES
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// FIXED MESSAGES
|
||||||
|
#define POWERUP "{\"status\":\"POWER UP\"}"
|
||||||
|
#define UNDERSTOOD "{\"status\":\"OK\"}"
|
||||||
|
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
|
||||||
|
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
|
||||||
|
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
|
||||||
|
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
|
||||||
|
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
|
||||||
|
|
||||||
|
// GAME NAMES
|
||||||
|
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
|
||||||
|
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
|
||||||
|
#define GM_REACTION "{\"gm\":\"REACTION\"}"
|
||||||
|
#define GM_DECISION "{\"gm\":\"DECISION\"}"
|
||||||
|
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
|
||||||
|
|
||||||
|
// COMMAND LIST
|
||||||
|
#define CM_START "{\"cm\":\"START\"}"
|
||||||
|
#define CM_RESET "{\"cm\":\"RESET\"}"
|
||||||
|
#define CM_STOP "{\"cm\":\"STOP\"}"
|
||||||
|
#define CM_EXIT "{\"cm\":\"EXIT\"}"
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// READING IMPACT POWER FROM ANALOG PINS
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// READING THE IMPACT
|
||||||
|
int readImpact()
|
||||||
|
{
|
||||||
|
int value = analogRead(SENSOR_PIN);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN HARDWARE SETUP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Communications
|
||||||
|
Terminal.begin(9600);
|
||||||
|
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
Bluetooth.begin("KICKER"); // Bluetooth device name
|
||||||
|
BOOST_SETUP; // Boost Pin Setup
|
||||||
|
BOOST_OFF; // Turn It Off
|
||||||
|
#else
|
||||||
|
Bluetooth.begin(9600); // Bluetooth HC-05 / HC-06
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// I/O
|
||||||
|
pixels.begin(); // Neo Pixel
|
||||||
|
LED_CLEAR(); // Turn Off All LED
|
||||||
|
|
||||||
|
// The Random Number Source
|
||||||
|
randomSeed(analogRead(RANDOM_SOURCE));
|
||||||
|
|
||||||
|
// POWER UP MESSGAE
|
||||||
|
dualcomm(POWERUP);
|
||||||
|
|
||||||
|
// DISPLAY COMPANY COUNTRY FLAG
|
||||||
|
LED_BAHRAIN_FLAG(); // Bahrain Flag
|
||||||
|
LED_COLOMBIA_FLAG(); // Colombia Flag
|
||||||
|
|
||||||
|
// DisJSON Rainbow
|
||||||
|
LED_CLEAR();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Reading From Bluetooth
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
// Reading Message From Bluetooth
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
|
||||||
|
// Display On Serial Monitor For Debuging
|
||||||
|
terminal(msg);
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, msg);
|
||||||
|
|
||||||
|
// If The System Understood The Message Clearly
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
// Sending Status Message
|
||||||
|
dualcomm(UNDERSTOOD);
|
||||||
|
|
||||||
|
// Reading Game Name & Settings
|
||||||
|
String game = JSON["gm"];
|
||||||
|
String settings = JSON["set"];
|
||||||
|
|
||||||
|
// Clearing JSON Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Entering To Game Selector
|
||||||
|
game_selector(game, settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal(JSON_ERROR);
|
||||||
|
}
|
||||||
|
Bluetooth.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END OF PROGRAM
|
||||||
|
//======================================================
|
||||||
345
Firmware Code/kicker_rev_3/neo_pixel.ino
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
#define BETWEEN_FADE 15
|
||||||
|
#define FADE_RATE 15
|
||||||
|
#define BLINK_RATE 250
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Clearing The LED Strip
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_CLEAR()
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Clear The Strip Color
|
||||||
|
pixels.clear();
|
||||||
|
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
delay(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Show On LED Strip
|
||||||
|
LED_SHOW();
|
||||||
|
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// DISPLAY ON STRIP
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SHOW()
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Pass It To The LED Strip
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Brightness
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SET_BRIGHTNESS(uint8_t Value)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set The Brightness
|
||||||
|
pixels.setBrightness(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Color
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set Intensity
|
||||||
|
LED_SET_BRIGHTNESS(Intensity);
|
||||||
|
|
||||||
|
// Loop
|
||||||
|
for(int i=0; i<NUM_PIXELS; i++) {
|
||||||
|
pixels.setPixelColor(i, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show The Colors On LED Strip
|
||||||
|
LED_SHOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<Times; i++)
|
||||||
|
{
|
||||||
|
LED_SET_COLOR(R, G, B, 255);
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// COLOR WHIPE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Fill the dots one after the other with a color
|
||||||
|
void LED_COLOR_WIPE(uint32_t c, uint8_t wait)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Work Loop
|
||||||
|
for(uint16_t i=0; i<NUM_PIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, c);
|
||||||
|
LED_SHOW();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Slightly different, this makes the rainbow equally distributed throughout
|
||||||
|
void LED_RAINBOW_CYCLE(uint8_t wait)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loop Variables
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
// The Loop
|
||||||
|
for(j=0; j<256*5; j++)
|
||||||
|
{
|
||||||
|
// 5 cycles of all colors on WHEEL
|
||||||
|
for(i=0; i< pixels.numPixels(); i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, LED_COLOR_WHEEL(((i * 256 / pixels.numPixels()) + j) & 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
LED_SHOW();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Input a value 0 to 255 to get a color value.
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
uint32_t LED_COLOR_WHEEL(byte WHEELPos)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Wheel Sequance
|
||||||
|
WHEELPos = 255 - WHEELPos;
|
||||||
|
|
||||||
|
if(WHEELPos < 85)
|
||||||
|
{
|
||||||
|
return pixels.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
|
||||||
|
}
|
||||||
|
if(WHEELPos < 170)
|
||||||
|
{
|
||||||
|
WHEELPos -= 85;
|
||||||
|
return pixels.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
|
||||||
|
}
|
||||||
|
WHEELPos -= 170;
|
||||||
|
return pixels.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set Color Fade In
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loop For Fade
|
||||||
|
for(int i=0; i<=255; i++)
|
||||||
|
{
|
||||||
|
pixels.setBrightness(i);
|
||||||
|
for(int j=0; j<NUM_PIXELS; j++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(j, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
|
||||||
|
LED_SHOW();
|
||||||
|
delay(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set Color Fade Out
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loop For Fade Out
|
||||||
|
for(int i=255; i>=0; i--)
|
||||||
|
{
|
||||||
|
pixels.setBrightness(i);
|
||||||
|
for(int j=0; j<NUM_PIXELS; j++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(j, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
|
||||||
|
LED_SHOW();
|
||||||
|
delay(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Color Cross Fade
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<Times; i++)
|
||||||
|
{
|
||||||
|
LED_FADEIN(R, G, B);
|
||||||
|
LED_FADEOUT(R, G, B);
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SIGNAL_START()
|
||||||
|
{
|
||||||
|
// Cross Fade White Color To Get ready 3 Times
|
||||||
|
LED_CROSS_FADE(255, 255, 255, 3);
|
||||||
|
|
||||||
|
// Set Strip Color Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SIGNAL_END()
|
||||||
|
{
|
||||||
|
// Blink Red Twice
|
||||||
|
LED_BLINK(255, 0, 0, 2);
|
||||||
|
|
||||||
|
// Fade The Red Color To Nothing
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SIGNAL_CELEBRATION()
|
||||||
|
{
|
||||||
|
// Display Rainbow Twice
|
||||||
|
LED_RAINBOW_CYCLE(2);
|
||||||
|
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_FADEOUT(0, 255, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SIGNAL_RESET()
|
||||||
|
{
|
||||||
|
// Light Bright Blue
|
||||||
|
LED_BLINK(0, 0, 255, 2);
|
||||||
|
|
||||||
|
// Wait For 1/4 Second
|
||||||
|
delay(250);
|
||||||
|
|
||||||
|
// Fade Out The Blue
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
|
||||||
|
// Set Strip Color Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// DISPLAY BAHRAIN FLAG
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BAHRAIN_FLAG()
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LED_SET_BRIGHTNESS(255);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(255, 255, 255), 30); // White
|
||||||
|
delay(250);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(255, 0, 0), 30); // Red
|
||||||
|
delay(250);
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// DISPLAY COLOMBIA FLAG
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_COLOMBIA_FLAG()
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LED_SET_BRIGHTNESS(255);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(255, 255, 0), 30); // Yellow
|
||||||
|
delay(250);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(0, 0, 255), 30); // Blue
|
||||||
|
delay(250);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(255, 0, 0), 30); // Red
|
||||||
|
delay(250);
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
29
Firmware Code/kicker_v2_rev_1/communication.ino
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//======================================================
|
||||||
|
// TERMINAL WINDOW - NATIVE USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void terminal(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Terminal.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void bluetooth(String msg)
|
||||||
|
{
|
||||||
|
msg += "\n";
|
||||||
|
Bluetooth.print(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void dualcomm(String msg)
|
||||||
|
{
|
||||||
|
terminal(msg);
|
||||||
|
bluetooth(msg);
|
||||||
|
}
|
||||||
178
Firmware Code/kicker_v2_rev_1/game_counter.ino
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN COUNTER GAME LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : game_counter_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : game_counter_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// THIS IS THE STAND ALONE CALL FOR THE GAME
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_counter_standalone()
|
||||||
|
{
|
||||||
|
// Variables Of The Game
|
||||||
|
uint16_t limit = 0;
|
||||||
|
bool limitEnable = 0;
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_counter(limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// THIS IS THE BLUETOOTH CALL FOR THE GAME
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* --------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* ct : count
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* WHAT JSON TO BE COLLECTED :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
|
||||||
|
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* No calculation required, Its directly the count
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_counter_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_counter(limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER JSON JSON -> To Send Back To Server
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_counter(uint16_t limit, bool limitEnable)
|
||||||
|
{
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// Game Start Lights
|
||||||
|
LED_SIGNAL_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
LED_SIGNAL_RESET();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebration
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Impact
|
||||||
|
if(readImpact() > VTH)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(counter_JSON_json(counter, timeStamp));
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// COUNTER JSON -> To Send Back To Mobile
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String counter_JSON_json(unsigned int ct, unsigned int st)
|
||||||
|
{
|
||||||
|
// Convert Int To Float
|
||||||
|
float stamp = st;
|
||||||
|
stamp /= 1000;
|
||||||
|
|
||||||
|
// Assignning JSONset
|
||||||
|
JSON["ct"] = ct;
|
||||||
|
JSON["st"] = String(stamp, 3).toFloat();
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
266
Firmware Code/kicker_v2_rev_1/game_reaction.ino
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
//======================================================
|
||||||
|
// REACTION GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : game_reaction_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : game_reaction_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Stand Alone Buttons
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_reaction_standalone()
|
||||||
|
{
|
||||||
|
// Variables
|
||||||
|
uint8_t minDelay = 0;
|
||||||
|
uint8_t maxDelay = 0;
|
||||||
|
uint8_t trials = 0;
|
||||||
|
|
||||||
|
// Display Screen Menu And Button Actions
|
||||||
|
// If The Menu Number 1 -> We Set The Value Of Min Delay
|
||||||
|
// If The Menu Number 2 -> We Set The Value Of Max Delay
|
||||||
|
// If The Menu Number 3 -> We Set The Number Of Trials
|
||||||
|
|
||||||
|
// Call the Game Play
|
||||||
|
play_reaction(minDelay, maxDelay, trials);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Bluetooth Via JSON
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* REACTION GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tr": 10, "mn": 1, "mx": 2}
|
||||||
|
*
|
||||||
|
* MEANNING :
|
||||||
|
* ----------
|
||||||
|
* tr : trials pre counter
|
||||||
|
* mn : minimum delay, between trials
|
||||||
|
* mx : maximum delay, between trials
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tr" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_reaction_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
//------------------------------------------------------
|
||||||
|
// START OF READING THE SETTINGS
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings);
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint8_t minDelay = JSON["mn"];
|
||||||
|
uint8_t maxDelay = JSON["mx"];
|
||||||
|
uint16_t trials = JSON["lm"];
|
||||||
|
|
||||||
|
// Fix Random Error
|
||||||
|
maxDelay += 1;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
play_reaction(minDelay, maxDelay, trials);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Play The Game
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
|
||||||
|
{
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t temp = trials;
|
||||||
|
|
||||||
|
// Fix Random Error
|
||||||
|
maxDelay += 1;
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// DisJSON Welcome Message
|
||||||
|
terminal("");
|
||||||
|
terminal("trials : " + String(trials) + " Strikes");
|
||||||
|
terminal("minDelay : " + String(minDelay) + " Seconds");
|
||||||
|
terminal("maxDelay : " + String(maxDelay) + " Seconds");
|
||||||
|
terminal("2 Seconds To Start Get Ready & Good Luck !!");
|
||||||
|
terminal("");
|
||||||
|
|
||||||
|
// Main Variables
|
||||||
|
uint16_t sdelay = 0;
|
||||||
|
uint16_t power = 0;
|
||||||
|
uint16_t response = 0;
|
||||||
|
unsigned long startTime = 0;
|
||||||
|
unsigned long stopTime = 0;
|
||||||
|
|
||||||
|
// Ready Signal
|
||||||
|
LED_SIGNAL_REACTION_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// Processing Results
|
||||||
|
for(int i=0; i<trials; i++)
|
||||||
|
{
|
||||||
|
// Reading Kick JSON
|
||||||
|
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
|
||||||
|
terminal(" -> Get Ready !!");
|
||||||
|
|
||||||
|
// Set Random Delay Time
|
||||||
|
sdelay = random(minDelay, maxDelay);
|
||||||
|
sdelay *= 1000;
|
||||||
|
delay(sdelay);
|
||||||
|
|
||||||
|
// Light Up Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
|
||||||
|
// Start Timer
|
||||||
|
startTime = millis();
|
||||||
|
|
||||||
|
// Sensing Strike Power
|
||||||
|
while(power < VTH)
|
||||||
|
{
|
||||||
|
// Reading The Strike
|
||||||
|
power = readImpact();
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP) {
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// RESET
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET) {
|
||||||
|
LED_SIGNAL_REACTION_RESET();
|
||||||
|
trials = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop Timer
|
||||||
|
stopTime = millis();
|
||||||
|
|
||||||
|
// Stop Light
|
||||||
|
LED_SET_COLOR(255, 0, 0, 255);
|
||||||
|
|
||||||
|
// Calculating Response Time
|
||||||
|
response = stopTime - startTime - 1;
|
||||||
|
|
||||||
|
// Create Json JSON
|
||||||
|
String msg = reaction_JSON_json(i+1, power, response, sdelay);
|
||||||
|
|
||||||
|
// Print To Terminal
|
||||||
|
dualcomm(msg);
|
||||||
|
|
||||||
|
// Clear All
|
||||||
|
sdelay = 0;
|
||||||
|
power = 0;
|
||||||
|
response = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red Light Delay
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
|
||||||
|
// Blink Red
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
|
||||||
|
// Return To Game Selector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION JSON -> To Send Back To Mobile Device
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
|
||||||
|
{
|
||||||
|
// Convert To Seconds Unit
|
||||||
|
float re = response;
|
||||||
|
re /= 1000;
|
||||||
|
|
||||||
|
// Asignning Values
|
||||||
|
JSON["ct"] = count; // Strike Number
|
||||||
|
JSON["pw"] = power; // Strike Power In Analog Read
|
||||||
|
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
|
||||||
|
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_REACTION_START()
|
||||||
|
{
|
||||||
|
// Cross fade the white signal to get ready
|
||||||
|
LED_CROSS_FADE(255, 255, 255, 3);
|
||||||
|
|
||||||
|
// Set the LED strip color to red
|
||||||
|
LED_SET_COLOR(255, 0, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void LED_SIGNAL_REACTION_RESET()
|
||||||
|
{
|
||||||
|
// Light Bright Blue
|
||||||
|
LED_BLINK(0, 0, 255, 2);
|
||||||
|
|
||||||
|
// Wait For 1/4 Second
|
||||||
|
delay(250);
|
||||||
|
|
||||||
|
// Fade Out The Blue
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
37
Firmware Code/kicker_v2_rev_1/game_selector.ino
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* game selector is the main function that tell the game groutine
|
||||||
|
* which game to be JSONed and at what parameters
|
||||||
|
*/
|
||||||
|
|
||||||
|
void game_selector(String game, String settings)
|
||||||
|
{
|
||||||
|
// Kick Counter Game
|
||||||
|
if(game == "ct") {
|
||||||
|
terminal(GM_COUNTER);
|
||||||
|
game_counter_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ta") {
|
||||||
|
terminal(GM_TATTACK);
|
||||||
|
game_reaction_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time Attack Game
|
||||||
|
else if(game == "ra") {
|
||||||
|
terminal(GM_REACTION);
|
||||||
|
game_reaction_bluetooth(settings);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown Game
|
||||||
|
else {
|
||||||
|
dualcomm(UNKNOWN_GAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
231
Firmware Code/kicker_v2_rev_1/game_time_attack.ino
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
//======================================================
|
||||||
|
// TIME ATTACK GAME MAIN ROUTINE
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* This Game Can Be Called From
|
||||||
|
* Stand Alone Mode / Bluetooth Connection
|
||||||
|
* The primary mode is the standalone but
|
||||||
|
* if the bluetooth is connected it has the priority
|
||||||
|
* so it will take over the control of the device
|
||||||
|
*
|
||||||
|
* If you want to control the game via bluetooth
|
||||||
|
* you need to call : time_attack_bluetooth(JSON String)
|
||||||
|
* If you want to use the stand alone mode
|
||||||
|
* you need to call : time_attack_standalone()
|
||||||
|
*
|
||||||
|
* the game returns a float point number which is
|
||||||
|
* in seconds. so the athlete know how long he takes to react
|
||||||
|
*/
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Stand Alone Buttons
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void time_attack_standalone()
|
||||||
|
{
|
||||||
|
// Variables
|
||||||
|
uint16_t time = 0;
|
||||||
|
uint16_t timer = 0;
|
||||||
|
uint16_t limit = 0;
|
||||||
|
bool limitEnable = 0;
|
||||||
|
|
||||||
|
// Display Screen Menu And Button Actions
|
||||||
|
// If The Menu Number 1 -> We Set The Value Of Min Delay
|
||||||
|
// If The Menu Number 2 -> We Set The Value Of Max Delay
|
||||||
|
// If The Menu Number 3 -> We Set The Number Of Trials
|
||||||
|
|
||||||
|
// Call the Game Play
|
||||||
|
game_timeAttack(time, timer, limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Request From Bluetooth Via JSON
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
|
||||||
|
* ------------------------------------------
|
||||||
|
*
|
||||||
|
* FORMAT :
|
||||||
|
* --------
|
||||||
|
* {"tm": 10, "le": false, "lm": 10}
|
||||||
|
*
|
||||||
|
* tm : count down timer starting value
|
||||||
|
* le : stands for limit enable, if is TRUE the game end if target value is meet
|
||||||
|
* lm : targeted amount of kicks
|
||||||
|
*
|
||||||
|
* THINGS THAT ENDS THE GAME :
|
||||||
|
* ---------------------------
|
||||||
|
* 1. BY COUNT DOWN "tm" REACH TO ZERO
|
||||||
|
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
|
||||||
|
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
|
||||||
|
*
|
||||||
|
* CALCULATING RESULTS :
|
||||||
|
* ---------------------
|
||||||
|
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
|
||||||
|
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
|
||||||
|
*
|
||||||
|
* RETURNNING JSON FORMAT :
|
||||||
|
* ------------------------
|
||||||
|
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
|
||||||
|
*
|
||||||
|
* tm : timer count in Sec
|
||||||
|
* ct : strike counter (number of kicks)
|
||||||
|
* dl : delay between strikes
|
||||||
|
* st : time stampe of the strike in milli Seconds
|
||||||
|
*/
|
||||||
|
|
||||||
|
void time_attack_bluetooth(String settings)
|
||||||
|
{
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
|
||||||
|
|
||||||
|
// JSON ERROR
|
||||||
|
if(error) {
|
||||||
|
dualcomm(JSON_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUBLIC VARIABLES
|
||||||
|
uint16_t time = JSON["tm"]; // Time Window To JSON
|
||||||
|
uint16_t timer = time;
|
||||||
|
uint16_t limit = JSON["lm"]; // Kick Target Limit
|
||||||
|
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
|
||||||
|
|
||||||
|
// Clearing Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Play The Game
|
||||||
|
game_timeAttack(time, timer, limit, limitEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// Play Time Atack Game
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void game_timeAttack(uint16_t time, uint16_t timer, uint16_t limit, bool limitEnable)
|
||||||
|
{
|
||||||
|
// Building Timers 1000mSec -> 1Sec
|
||||||
|
TimeTrigger sec_tick(1000);
|
||||||
|
|
||||||
|
// Kick Counter
|
||||||
|
uint16_t counter = 0;
|
||||||
|
|
||||||
|
// Start LED Signal
|
||||||
|
LED_SIGNAL_START();
|
||||||
|
|
||||||
|
//-------------------------
|
||||||
|
// PREPARE FOR GAME START
|
||||||
|
//-------------------------
|
||||||
|
|
||||||
|
// Send Initial DisJSON
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||||
|
|
||||||
|
// staring Of time stamp
|
||||||
|
unsigned long startStamp = millis();
|
||||||
|
|
||||||
|
// store the time of the previous kick
|
||||||
|
unsigned long lastStamp = 0;
|
||||||
|
|
||||||
|
// reseting time ticker
|
||||||
|
sec_tick.Reset();
|
||||||
|
|
||||||
|
// While The Game Is Still On
|
||||||
|
while(timer != 0)
|
||||||
|
{
|
||||||
|
// Time Stamp
|
||||||
|
unsigned long timeStamp = millis() - startStamp;
|
||||||
|
|
||||||
|
// If Stop Command Came From Smart Phone
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
if(msg == CM_STOP)
|
||||||
|
{
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Grean Light In
|
||||||
|
LED_SIGNAL_END();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(msg == CM_RESET)
|
||||||
|
{
|
||||||
|
timer = time;
|
||||||
|
counter = 0;
|
||||||
|
startStamp = millis();
|
||||||
|
timeStamp = startStamp;
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
sec_tick.Reset();
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
LED_SIGNAL_RESET();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Kick ---------------------------->>>
|
||||||
|
if(readImpact() > VTH)
|
||||||
|
{
|
||||||
|
counter++;
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp));
|
||||||
|
lastStamp = timeStamp;
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every Second ---------------------------->>>
|
||||||
|
if(sec_tick.Trigger())
|
||||||
|
{
|
||||||
|
timer--;
|
||||||
|
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If Limits Are Enabled And Meet
|
||||||
|
if(limitEnable == true && counter == limit)
|
||||||
|
{
|
||||||
|
// END GAME
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// Celebrate
|
||||||
|
LED_SIGNAL_CELEBRATION();
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send End Game Signal To Smart Phone
|
||||||
|
dualcomm(GAME_OVER);
|
||||||
|
// LightUp
|
||||||
|
LED_FADEIN(255, 0, 0); // RED Color
|
||||||
|
delay(2000); // Delay 2000
|
||||||
|
LED_CLEAR(); // CLEAR OFF
|
||||||
|
// Return
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// TIME ATTACK KICK JSON -> To Send Back To Mobile
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
|
||||||
|
{
|
||||||
|
// Building The Buffer
|
||||||
|
JSON["tm"] = RunningTime;
|
||||||
|
JSON["ct"] = KickCount;
|
||||||
|
|
||||||
|
// Calculations
|
||||||
|
if(TimeStamp > 0)
|
||||||
|
{
|
||||||
|
// Calculate Time Stamp In Seconds
|
||||||
|
float st = TimeStamp;
|
||||||
|
st /= 1000;
|
||||||
|
JSON["st"] = String(st, 3).toFloat();
|
||||||
|
|
||||||
|
// Calculate Strike Delay In Seconds
|
||||||
|
float dl = TimeStamp - LastStamp;
|
||||||
|
dl /= 1000;
|
||||||
|
JSON["dl"] = String(dl, 3).toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(JSON, output);
|
||||||
|
JSON.clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
326
Firmware Code/kicker_v2_rev_1/kicker_v2_rev_1.ino
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
//======================================================
|
||||||
|
// LIBRARIES
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// Library Include
|
||||||
|
#include <Button.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <TimeTrigger.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// HARDWARE SETUP & SELECTION
|
||||||
|
//======================================================
|
||||||
|
// Arduino MEGA
|
||||||
|
#ifdef ARDUINO_AVR_MEGA2560
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Library Nessesary
|
||||||
|
#ifdef __AVR__
|
||||||
|
#include <avr/power.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Buttons Definitions
|
||||||
|
Button btn_prv(15); // TOP LEFT BUTTON
|
||||||
|
Button btn_nxt(12); // TOP RIGHT BUTTON
|
||||||
|
Button btn_sel(33); // CENTER BUTTON
|
||||||
|
Button btn_inc(32); // BOTTOM LEFT
|
||||||
|
Button btn_dec(27); // BOTTOM RIGHT
|
||||||
|
|
||||||
|
// Serial Terminal
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
|
||||||
|
#define flushTerminal while(isTerminal) { Terminal.read(); }
|
||||||
|
|
||||||
|
// Bluetooth Terminal
|
||||||
|
#define Bluetooth Serial1 // We will Connect The HC-05 To Hardware Serial1 In Arduino Mega
|
||||||
|
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
|
||||||
|
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
|
||||||
|
|
||||||
|
// JSON Object & Memory
|
||||||
|
#define CAPACITY 100
|
||||||
|
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||||
|
|
||||||
|
// LED Strip
|
||||||
|
#define LED_STRIP 53 // LED STRIP PIN NUMBER
|
||||||
|
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
// Impact Detection
|
||||||
|
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Arduino Uno / Nano
|
||||||
|
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Library Nessesary
|
||||||
|
#ifdef __AVR__
|
||||||
|
#include <avr/power.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Buttons Definitions
|
||||||
|
Button btn_prv(15); // TOP LEFT BUTTON
|
||||||
|
Button btn_nxt(12); // TOP RIGHT BUTTON
|
||||||
|
Button btn_sel(33); // CENTER BUTTON
|
||||||
|
Button btn_inc(32); // BOTTOM LEFT
|
||||||
|
Button btn_dec(27); // BOTTOM RIGHT
|
||||||
|
|
||||||
|
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
|
||||||
|
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
|
||||||
|
// Serial Terminal
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
|
||||||
|
#define flushTerminal while(isTerminal) { Terminal.read(); }
|
||||||
|
|
||||||
|
// Bluetooth Terminal
|
||||||
|
SoftwareSerial Bluetooth(10, 11); // Pin 10 RX, Pin 11 TX
|
||||||
|
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
|
||||||
|
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
|
||||||
|
|
||||||
|
// JSON Object & Memory
|
||||||
|
#define CAPACITY 100
|
||||||
|
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||||
|
|
||||||
|
// LED Strip
|
||||||
|
#define LED_STRIP 2 // LED STRIP PIN NUMBER
|
||||||
|
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
// Impact Detection
|
||||||
|
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define SENSOR_PIN A0 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE A4 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// ESP32 TAKEONE BOARD
|
||||||
|
#elif ESP32
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
/* ===============================================
|
||||||
|
* - THIS IS TAKEONE BOARD -
|
||||||
|
* ===============================================
|
||||||
|
* MPU9250 Address : 0X69 (ADDRESS)
|
||||||
|
* OLED 128x64 Address : 0X3C (ADDRESS)
|
||||||
|
* -----------------------------------------------
|
||||||
|
* Description : PIN GPIO#
|
||||||
|
* -----------------------------------------------
|
||||||
|
* NEOPIXEL LED STRIP : A0/GPIO 26
|
||||||
|
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
|
||||||
|
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
|
||||||
|
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
|
||||||
|
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
|
||||||
|
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
|
||||||
|
* LED PIN : 13 (DIGITAL)
|
||||||
|
* BATTERY MONITOR PIN : 35 (ANALOG)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ESP32 HAVE A NATIVE BLUETOOTH MODULE
|
||||||
|
SO WE USE BLUETOOTH SERIAL LIBRARY */
|
||||||
|
#include <BluetoothSerial.h>
|
||||||
|
|
||||||
|
// Nessesary Definition For Bluetooth Library
|
||||||
|
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||||
|
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Buttons Definitions
|
||||||
|
Button btn_prv(15); // TOP LEFT BUTTON
|
||||||
|
Button btn_nxt(12); // TOP RIGHT BUTTON
|
||||||
|
Button btn_sel(33); // CENTER BUTTON
|
||||||
|
Button btn_inc(32); // BOTTOM LEFT
|
||||||
|
Button btn_dec(27); // BOTTOM RIGHT
|
||||||
|
|
||||||
|
// Serial Terminal
|
||||||
|
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
|
||||||
|
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
|
||||||
|
#define flushTerminal while(isTerminal) { Terminal.read(); }
|
||||||
|
|
||||||
|
// Bluetooth Terminal
|
||||||
|
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
|
||||||
|
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
|
||||||
|
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
|
||||||
|
|
||||||
|
// JSON Object & Memory
|
||||||
|
#define CAPACITY 100
|
||||||
|
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
|
||||||
|
|
||||||
|
// LED Strip
|
||||||
|
#define LED_STRIP 26 // LED STRIP PIN NUMBER
|
||||||
|
#define NUM_PIXELS 22 // NUMBER OF LED'S IN NEO PIXEL STRIP
|
||||||
|
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
|
||||||
|
|
||||||
|
// Impact Detection
|
||||||
|
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
|
||||||
|
#define SENSOR_PIN 39 // IMPACT SENSOR
|
||||||
|
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Exclusive Features Of TAKEONE BOARD
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
/* ESP32 TAKEONE Board has some unique hardware features
|
||||||
|
* 1. Battery Voltage Level Monitoring Via Analog Pin 35
|
||||||
|
* 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery
|
||||||
|
* 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom
|
||||||
|
* 4. SPI : SDCARD Reader */
|
||||||
|
|
||||||
|
// Boost Converter
|
||||||
|
#define BOOST_PIN 14
|
||||||
|
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
|
||||||
|
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
|
||||||
|
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
|
||||||
|
#define BOOST_STU digitalRead(BOOST_PIN)
|
||||||
|
|
||||||
|
// Battery Level Monitoring
|
||||||
|
#define BATTERY_PIN 35
|
||||||
|
#define BATTERY (float)(((analogRead(BATTERY_PIN) * (3.3 / 4096)) * 2) + 0.31)
|
||||||
|
#define CHARGE round(mapf(BATTERY, 3.27, 4.31, 0, 100), 1)
|
||||||
|
|
||||||
|
// Function To Make Sure The Pin Is ON
|
||||||
|
void LED_BOOST_CHK() {
|
||||||
|
if(BOOST_STU == LOW) {
|
||||||
|
BOOST_ON;
|
||||||
|
//delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Floting Point Mapping
|
||||||
|
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
|
||||||
|
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// PREDEFINED JSON STRINGS MESSAGES
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// FIXED MESSAGES
|
||||||
|
#define POWERUP "{\"status\":\"POWER UP\"}"
|
||||||
|
#define UNDERSTOOD "{\"status\":\"OK\"}"
|
||||||
|
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
|
||||||
|
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
|
||||||
|
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
|
||||||
|
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
|
||||||
|
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
|
||||||
|
|
||||||
|
// GAME NAMES
|
||||||
|
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
|
||||||
|
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
|
||||||
|
#define GM_REACTION "{\"gm\":\"REACTION\"}"
|
||||||
|
#define GM_DECISION "{\"gm\":\"DECISION\"}"
|
||||||
|
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
|
||||||
|
|
||||||
|
// COMMAND LIST
|
||||||
|
#define CM_START "{\"cm\":\"START\"}"
|
||||||
|
#define CM_RESET "{\"cm\":\"RESET\"}"
|
||||||
|
#define CM_STOP "{\"cm\":\"STOP\"}"
|
||||||
|
#define CM_EXIT "{\"cm\":\"EXIT\"}"
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// READING IMPACT POWER FROM ANALOG PINS
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
// READING THE IMPACT
|
||||||
|
int readImpact()
|
||||||
|
{
|
||||||
|
int value = analogRead(SENSOR_PIN);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN HARDWARE SETUP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Communications
|
||||||
|
Terminal.begin(9600);
|
||||||
|
Terminal.println();
|
||||||
|
|
||||||
|
// Begin Buttons
|
||||||
|
btn_prv.begin();
|
||||||
|
btn_nxt.begin();
|
||||||
|
btn_sel.begin();
|
||||||
|
btn_inc.begin();
|
||||||
|
btn_dec.begin();
|
||||||
|
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
Bluetooth.begin("KICKER"); // Bluetooth device name
|
||||||
|
BOOST_SETUP; // Boost Pin Setup
|
||||||
|
BOOST_OFF; // Turn It Off
|
||||||
|
#else
|
||||||
|
Bluetooth.begin(9600); // Bluetooth HC-05 / HC-06
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// I/O
|
||||||
|
pixels.begin(); // Neo Pixel
|
||||||
|
LED_CLEAR(); // Turn Off All LED
|
||||||
|
|
||||||
|
// The Random Number Source
|
||||||
|
randomSeed(analogRead(RANDOM_SOURCE));
|
||||||
|
|
||||||
|
// POWER UP MESSGAE
|
||||||
|
dualcomm(POWERUP);
|
||||||
|
|
||||||
|
// DISPLAY COMPANY COUNTRY FLAG
|
||||||
|
LED_BAHRAIN_FLAG(); // Bahrain Flag
|
||||||
|
LED_COLOMBIA_FLAG(); // Colombia Flag
|
||||||
|
|
||||||
|
// DisJSON Rainbow
|
||||||
|
LED_CLEAR();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// MAIN PROGRAM LOOP
|
||||||
|
//======================================================
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// Reading From Bluetooth
|
||||||
|
if(isBluetooth)
|
||||||
|
{
|
||||||
|
// Reading Message From Bluetooth
|
||||||
|
String msg = Bluetooth.readStringUntil('\n');
|
||||||
|
flushBluetooth;
|
||||||
|
msg.trim();
|
||||||
|
|
||||||
|
// Display On Serial Monitor For Debuging
|
||||||
|
terminal(msg);
|
||||||
|
|
||||||
|
// Deserialize the JSON document
|
||||||
|
DeserializationError error = deserializeJson(JSON, msg);
|
||||||
|
|
||||||
|
// If The System Understood The Message Clearly
|
||||||
|
if(!error)
|
||||||
|
{
|
||||||
|
// Sending Status Message
|
||||||
|
dualcomm(UNDERSTOOD);
|
||||||
|
|
||||||
|
// Reading Game Name & Settings
|
||||||
|
String game = JSON["gm"];
|
||||||
|
String settings = JSON["set"];
|
||||||
|
|
||||||
|
// Clearing JSON Buffer
|
||||||
|
JSON.clear();
|
||||||
|
|
||||||
|
// Entering To Game Selector
|
||||||
|
game_selector(game, settings);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
terminal(JSON_ERROR);
|
||||||
|
}
|
||||||
|
Bluetooth.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================
|
||||||
|
// END OF PROGRAM
|
||||||
|
//======================================================
|
||||||
341
Firmware Code/kicker_v2_rev_1/neo_pixel.ino
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
#define BETWEEN_FADE 15
|
||||||
|
#define FADE_RATE 15
|
||||||
|
#define BLINK_RATE 250
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Clearing The LED Strip
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_CLEAR()
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Clear The Strip Color
|
||||||
|
pixels.clear();
|
||||||
|
|
||||||
|
// Show On LED Strip
|
||||||
|
LED_SHOW();
|
||||||
|
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
BOOST_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// DISPLAY ON STRIP
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SHOW()
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
delay(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Pass It To The LED Strip
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Brightness
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SET_BRIGHTNESS(uint8_t Value)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set The Brightness
|
||||||
|
pixels.setBrightness(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Color
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set Intensity
|
||||||
|
LED_SET_BRIGHTNESS(Intensity);
|
||||||
|
|
||||||
|
// Loop
|
||||||
|
for(int i=0; i<NUM_PIXELS; i++) {
|
||||||
|
pixels.setPixelColor(i, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show The Colors On LED Strip
|
||||||
|
LED_SHOW();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// BLINK
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
|
||||||
|
{
|
||||||
|
for(int i=0; i<Times; i++)
|
||||||
|
{
|
||||||
|
LED_SET_COLOR(R, G, B, 255);
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
LED_CLEAR();
|
||||||
|
delay(BLINK_RATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// COLOR WHIPE
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Fill the dots one after the other with a color
|
||||||
|
void LED_COLOR_WIPE(uint32_t c, uint8_t wait)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Work Loop
|
||||||
|
for(uint16_t i=0; i<NUM_PIXELS; i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, c);
|
||||||
|
LED_SHOW();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Slightly different, this makes the rainbow equally distributed throughout
|
||||||
|
void LED_RAINBOW_CYCLE(uint8_t wait)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loop Variables
|
||||||
|
uint16_t i, j;
|
||||||
|
|
||||||
|
// The Loop
|
||||||
|
for(j=0; j<256*5; j++)
|
||||||
|
{
|
||||||
|
// 5 cycles of all colors on WHEEL
|
||||||
|
for(i=0; i< pixels.numPixels(); i++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(i, LED_COLOR_WHEEL(((i * 256 / pixels.numPixels()) + j) & 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
LED_SHOW();
|
||||||
|
delay(wait);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// END GAME LIGHTING SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
// Input a value 0 to 255 to get a color value.
|
||||||
|
// The colours are a transition r - g - b - back to r.
|
||||||
|
uint32_t LED_COLOR_WHEEL(byte WHEELPos)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Wheel Sequance
|
||||||
|
WHEELPos = 255 - WHEELPos;
|
||||||
|
|
||||||
|
if(WHEELPos < 85)
|
||||||
|
{
|
||||||
|
return pixels.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
|
||||||
|
}
|
||||||
|
if(WHEELPos < 170)
|
||||||
|
{
|
||||||
|
WHEELPos -= 85;
|
||||||
|
return pixels.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
|
||||||
|
}
|
||||||
|
WHEELPos -= 170;
|
||||||
|
return pixels.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set Color Fade In
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loop For Fade
|
||||||
|
for(int i=0; i<=255; i++)
|
||||||
|
{
|
||||||
|
pixels.setBrightness(i);
|
||||||
|
for(int j=0; j<NUM_PIXELS; j++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(j, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
|
||||||
|
LED_SHOW();
|
||||||
|
delay(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set Color Fade Out
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loop For Fade Out
|
||||||
|
for(int i=255; i>=0; i--)
|
||||||
|
{
|
||||||
|
pixels.setBrightness(i);
|
||||||
|
for(int j=0; j<NUM_PIXELS; j++)
|
||||||
|
{
|
||||||
|
pixels.setPixelColor(j, pixels.Color(R, G, B));
|
||||||
|
}
|
||||||
|
|
||||||
|
LED_SHOW();
|
||||||
|
delay(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// Set LED Color Cross Fade
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<Times; i++)
|
||||||
|
{
|
||||||
|
LED_FADEIN(R, G, B);
|
||||||
|
LED_FADEOUT(R, G, B);
|
||||||
|
delay(BETWEEN_FADE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// REACTION GAME START LED SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SIGNAL_START()
|
||||||
|
{
|
||||||
|
// Cross Fade White Color To Get ready 3 Times
|
||||||
|
LED_CROSS_FADE(255, 255, 255, 3);
|
||||||
|
|
||||||
|
// Set Strip Color Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// REACTION GAME END SINGNAL LED SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SIGNAL_END()
|
||||||
|
{
|
||||||
|
// Blink Red Twice
|
||||||
|
LED_BLINK(255, 0, 0, 2);
|
||||||
|
|
||||||
|
// Fade The Red Color To Nothing
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// REACTION GAME START LED CELEBRATION
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SIGNAL_CELEBRATION()
|
||||||
|
{
|
||||||
|
// Display Rainbow Twice
|
||||||
|
LED_RAINBOW_CYCLE(2);
|
||||||
|
|
||||||
|
// Grean Light OUT
|
||||||
|
LED_FADEOUT(0, 255, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// REACTION GAME RESET LED SIGNAL
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_SIGNAL_RESET()
|
||||||
|
{
|
||||||
|
// Light Bright Blue
|
||||||
|
LED_BLINK(0, 0, 255, 2);
|
||||||
|
|
||||||
|
// Wait For 1/4 Second
|
||||||
|
delay(250);
|
||||||
|
|
||||||
|
// Fade Out The Blue
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
|
||||||
|
// Set Strip Color Green
|
||||||
|
LED_SET_COLOR(0, 255, 0, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// DISPLAY BAHRAIN FLAG
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_BAHRAIN_FLAG()
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LED_SET_BRIGHTNESS(255);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(255, 255, 255), 30); // White
|
||||||
|
delay(250);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(255, 0, 0), 30); // Red
|
||||||
|
delay(250);
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------
|
||||||
|
// DISPLAY COLOMBIA FLAG
|
||||||
|
//------------------------------------------------------
|
||||||
|
|
||||||
|
void LED_COLOMBIA_FLAG()
|
||||||
|
{
|
||||||
|
// Make Sure Of The Core
|
||||||
|
#ifdef ESP32
|
||||||
|
LED_BOOST_CHK();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LED_SET_BRIGHTNESS(255);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(255, 255, 0), 30); // Yellow
|
||||||
|
delay(250);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(0, 0, 255), 30); // Blue
|
||||||
|
delay(250);
|
||||||
|
LED_COLOR_WIPE(pixels.Color(255, 0, 0), 30); // Red
|
||||||
|
delay(250);
|
||||||
|
LED_FADEOUT(255, 0, 0);
|
||||||
|
}
|
||||||
BIN
Pictures/2019-09-17_15h28_03.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
Pictures/2019-09-17_15h28_57.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
Pictures/2019-09-19_20h37_01.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
Pictures/IMG_20190316_010952.jpg
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
BIN
Pictures/IMG_20190715_013221_228.jpg
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
Pictures/IMG_20190715_014142_468.jpg
Normal file
|
After Width: | Height: | Size: 46 KiB |