/*
* Draw Lots Sketch
* by Roland Pelayo
*
* A random number/name generator using ESP8266
*
* Number range and names can be generated using ESP8266 web server. The range of numbers and/or names are stored in EEPROM
*
* Required libraries:
* > ESP8266 Arduino Core
* > MPU6050 for ESP8266
* > Liquid Crystal
* > EEPROM
*/
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <MPU6050.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <stdio.h>
#include <string.h>
//#ifndef APSSID
#define APSSID "drawlots"
#define APPSK "123456"
//#endif
/* Set these to your desired credentials. */
const char *ssid = APSSID;
const char *password = APPSK;
ESP8266WebServer server(80);
MPU6050 mpu;
int SCL_PIN=D6;
int SDA_PIN=D5;
#include <LiquidCrystal.h>
const int rs = D7, en = D8, d4 = D1, d5 = D2, d6 = D3, d7 = D4;
int sw = D0;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
long randNumber,previousNumber;
bool stillShaking = false;
bool serverSetupDone = false;
int activity_counter;
int old_act_counter;
int sensitivity = 4;
byte page = 0; //for checking which screen to display
byte _mode = 0; //for checking whice mode (names or numbers)
const char MAIN_PAGE[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<body>
<style>
div{
text-align: center;
}
body{
font-family: Helvetica, Sans-serif;
}
button{
font-size: 12;
margin: 2px,2px,2px,2px;
}
</style>
<div id="header">
<h1>Draw Lots</h1>
<h2>by Roland Pelayo</h2>
</div>
<div id="form">
<h3>Choose option:</h3>
<div id="buttons">
<form action="/number">
<button type="submit">Random Number</button>
</form>
<form action="/name">
<button type="submit">Random Name</button>
</form>
</div>
</div>
</body>
</html>
)=====";
const char NUMBER_PAGE[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<body>
<style>
div{
text-align: center;
}
body{
font-family: Helvetica, Sans-serif;
}
button{
font-size: 12;
margin: 2px,2px,2px,2px;
}
</style>
<div id="header">
<h1>Random Number Generator</h1>
</div>
<div id="form">
<form action="/save_numbers">
<h4>Enter minimum number</h4>
<input type="text" name="minNumber">
<h4>Enter maximum number</h4>
<input type="text" name="maxNumber">
<p></p>
<input type="submit" value="Save"></input>
</form>
</div>
</body>
</html>
)=====";
const char NAMES_PAGE[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<body>
<style>
div{
text-align: center;
}
body{
font-family: Helvetica, Sans-serif;
}
button{
font-size: 12;
margin: 2px,2px,2px,2px;
}
</style>
<div id="header">
<h1>Random Names Generator</h1>
</div>
<div id="form">
<form action="/save_names">
<h4>Enter Names separated by comma</h4>
<input type="text" name="names">
<input type="submit" value="Submit"></input>
</form>
</div>
</body>
</html>
)=====";
void handleRoot() {
String st = MAIN_PAGE;
server.send(200, "text/html", st);
}
void handleNumber(){
String st = NUMBER_PAGE;
server.send(200,"text/html", st);
}
void handleNames(){
String st = NAMES_PAGE;
server.send(200,"text/html", st);
}
void handleSaveNumbers(){
String minNum = server.arg("minNumber");
int minNumber = minNum.toInt();
String maxNum = server.arg("maxNumber");
int maxNumber = maxNum.toInt();
EEPROM.write(0,minNumber);
EEPROM.write(1,maxNumber);
EEPROM.write(2,1);
EEPROM.commit();
String s = "<a href='/'>Home</a>";
server.send(200,"text/html",s);
}
void handleSaveNames(){
String names = server.arg("names");
Serial.println(names);
int counter;
counter = countCommas(names)+1;
Serial.print("Names: ");
Serial.println(counter);
EEPROM.write(2,0);
EEPROM.write(3,counter); //store number of names
EEPROM.commit();
String _names [20];
for(int i = 0;i<counter;i++){
_names[i] = getValue(names,',',i);
writeString((i+1)*10,_names[i]);
}
String s2[20];
for(int j=0;j<counter;j++){
s2[j] = read_String((j+1)*10);
Serial.println(s2[j]);
}
String s = "<a href='/'>Home</a>";
server.send(200,"text/html",s);
}
//Function to write string to EEPROM
void writeString(char add, String data){
int _size = data.length();
int i;
for(i = 0;i<_size;i++){
EEPROM.write(add+i,data[i]);
}
EEPROM.write(add+_size,'\0');
EEPROM.commit();
}
//Function to read string from EEPROM
String read_String(char add){
int i;
char data[100];
int len=0;
unsigned char k;
k=EEPROM.read(add);
while(k!= '\0' && len<500){
k=EEPROM.read(add+len);
data[len]=k;
len++;
}
data[len]='\0';
return String(data);
}
//Function to count commas, and consequently, the number of names
int countCommas(String s){
byte counter = 0;
int stringLength;
byte index,newIndex;
stringLength = s.length();
// Serial.print("The string is: ");
// Serial.println(s);
// Serial.print("The string length is: ");
// Serial.println(stringLength);
index = s.indexOf(',');
// Serial.print("Index of first comma is: ");
// Serial.println(index);
while(index < stringLength){
newIndex = s.indexOf(',',index+1);
if(newIndex > stringLength){
break;
}
if(newIndex != -1){
// Serial.println("Next comma found! ");
counter++;
// Serial.print("Index of next comma is: ");
// Serial.println(newIndex);
// Serial.print("Commas found: ");
// Serial.println(counter);
}else{
break;
}
index = newIndex;
}
//Serial.print("The number of commas is: ");
//Serial.println(counter+1);
return counter+1;
}
//Function to split string with separator (comma, in this case)
String getValue(String data, char separator, int index){
int found = 0;
int strIndex[] = {0,-1};
int maxIndex = data.length()-1;
for(int i=0;i<=maxIndex && found <=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0]=strIndex[1]+1;
strIndex[1]=(i==maxIndex)?i+1:i;
}
if(i==maxIndex && found == index){
strIndex[0]= strIndex[1]+1;
strIndex[1]= maxIndex;
return data.substring(strIndex[0],strIndex[1]);
}
}
return found>index ? data.substring(strIndex[0],strIndex[1]) : "";
}
void setup()
{
lcd.begin(16,2);
delay(1);
Serial.begin(9600);
randomSeed(analogRead(0));
pinMode(sw,INPUT);
lcd.setCursor(0,0);
lcd.print("Initializing");
EEPROM.begin(512);
initMPU();
}
void initMPU(){
while(!mpu.beginSoftwareI2C(SCL_PIN,SDA_PIN,MPU6050_SCALE_2000DPS, MPU6050_RANGE_16G))
{
lcd.print("IMU Error!");
delay(500);
}
delay(1000);
lcd.clear();
mpu.setAccelPowerOnDelay(MPU6050_DELAY_3MS);
mpu.setIntFreeFallEnabled(false);
mpu.setIntZeroMotionEnabled(false);
mpu.setIntMotionEnabled(false);
mpu.setDHPFMode(MPU6050_DHPF_5HZ);
mpu.setMotionDetectionThreshold(2);
mpu.setMotionDetectionDuration(5);
mpu.setZeroMotionDetectionThreshold(4);
mpu.setZeroMotionDetectionDuration(2);
}
void serverMode(){
lcd.setCursor(0,0);
lcd.print("Server mode ");
delay(1000);
lcd.setCursor(0,0);
lcd.print("Configuring AP ");
/* You can remove the password parameter if you want the AP to be open. */
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP();
lcd.setCursor(0,0);
lcd.print("IP: ");
lcd.print(myIP);
server.on("/", handleRoot);
server.on("/number",handleNumber);
server.on("/name",handleNames);
server.on("/save_numbers",handleSaveNumbers);
server.on("/save_names",handleSaveNames);
server.begin();
lcd.setCursor(0,1);
lcd.print("Server started ");
serverSetupDone = true;
}
void loop()
{
if(digitalRead(sw) == 1){
delay(500);
if(serverSetupDone == false){
serverMode();
}else{
server.handleClient();
}
}else{
delay(500);
gameMode();
}
}
void gameMode(){
WiFi.forceSleepBegin();
Serial.print("Page: ");
Serial.println(page);
int stage = checkMotion();
if(stage == 1 && page == 0){
startCheckMode();
}else if(stage == 1 && page == 1){
startRandomizer();
}else if(stage == 0 && page == 0){
//lcd.clear();
lcd.setCursor(0,0);
lcd.print("Shake device to ");
lcd.setCursor(0,1);
lcd.print("start ");
}else if(stage == 0 && page == 1){
lcd.setCursor(0,0);
lcd.print("Shake device to ");
lcd.setCursor(0,1);
lcd.print("draw ");
}else{;}
delay(500);
}
int checkMotion(){
Activites act = mpu.readActivites();
if(act.isActivity == 1){
activity_counter++;
Serial.print("Activity: ");
Serial.println(activity_counter);
if(activity_counter > 1000){
activity_counter = 0;
}
if(activity_counter - old_act_counter == sensitivity){
old_act_counter = activity_counter;
return 1;
}else{
return 0;
}
}else{
return 0;
}
}
/*
int checkMotion(){
//Vector rawAccel = mpu.readRawAccel();
int count = 0;
bool doneShaking = false;
Activites act = mpu.readActivites();
if(act.isActivity == 1 && act.isInactivity == 0){
delay(500);
Activites act = mpu.readActivites();
if(act.isActivity == 1 && act.isInactivity == 0){
stillShaking = true;
lcd.clear();
count++;
if(count < 3){
lcd.setCursor(0,0);
lcd.print("Shake & shake!");
lcd.setCursor(count,1);
lcd.print('.');
return 2;
}else if(count == 3){
count = 0;
return 3;
}
}else{
return 0;
}
}else{
return 0;
}
/*
delay(1000);
while(stillShaking == true){
Activites act = mpu.readActivites();
delay(500);
if(act.isActivity && !act.isInactivity){
stillShaking = true;
count++;
lcd.setCursor(0,0);
lcd.print("Shake & shake!");
lcd.setCursor(count,1);
lcd.print('.');
if(count==3){
doneShaking = true;
stillShaking = false;
count == 0;
break;
}
}
delay(200);
}
if(doneShaking == true){
return 1;
}
}*/
void startCheckMode(){
_mode = EEPROM.read(2);
if(_mode == 0){
lcd.setCursor(0,0);
lcd.print("Drawing Names ");
lcd.setCursor(0,1);
lcd.print(" ");
}else if(_mode == 1){
lcd.setCursor(0,0);
lcd.print("Drawing Numbers ");
lcd.setCursor(0,1);
lcd.print(" ");
}else{;}
page = 1;
}
bool startRandomizer(){
if(_mode == 1){
Serial.println("Draw random numbers");
byte data1,data2;
data1 = EEPROM.read(0);
data2 = EEPROM.read(1);
int minNum = (int)data1;
int maxNum = (int)data2;
randNumber = random(minNum,maxNum);
while(randNumber == previousNumber){
randNumber = random(minNum,maxNum);
}
lcd.setCursor(0,0);
lcd.print("Lucky number is: ");
lcd.setCursor(0,1);
lcd.print(randNumber);
previousNumber = randNumber;
if(randNumber > 9){
lcd.print(" ");
}else{
lcd.print(" ");
}
}
else if(_mode == 0){
Serial.println("Draw random names");
byte count;
count = EEPROM.read(3);
String names[20];
for(int i=0;i<(int)count;i++){
names[i] = read_String((i+1)*10);
}
randNumber = random(1,(int)count);
while(randNumber == previousNumber){
randNumber = random(1,(int)count);
}
lcd.setCursor(0,0);
lcd.print("Lucky Person is: ");
lcd.setCursor(0,1);
lcd.print(names[randNumber]);
previousNumber = randNumber;
}
delay(5000);
page = 0;
}
Comments