Created
May 25, 2018 02:18
-
-
Save LieutenantChips/5db5b1428d0cce28390e143635e3c282 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <ESP8266WiFi.h> | |
#include <ESP8266WebServer.h> | |
//The network is required to be connected to the internet | |
//If you want the IP to be sent to the phone. | |
const char* ssid = "NAME OF NETWORK HERE"; | |
const char* password = "PASSWORD OF NETWORK HERE"; | |
//the number of steppermotors connected to arduino | |
//We are currently using only the first one, the second pin values corresponded to | |
//a stepper motor that got changed. | |
#define nrOfSteppers 2 | |
//the pins of the steppers that control the direction | |
const int stepperDirectionPin[nrOfSteppers] = {0,4}; | |
//the pins of the steppers that control the pulse | |
const int stepperPulsePin[nrOfSteppers] = {1,2}; | |
char command; | |
int currentDirection = 0; | |
//These are scaling values, max_height corresponds to the maximum time the | |
//linear actuator can be powered in one direction. (Otherwise it pushes to the limits). | |
int max_rot = 25; | |
int max_height = 2000; | |
//Worm Stepper motor step delay. | |
int wStepDelay = 5; | |
//This integer is used as a flag to know if we are at the limit of our heights. | |
int height = 0; | |
//Server initialization. | |
WiFiServer server(80); | |
//This is there to send the phone the IP address only once. | |
int clientNewConnection = 1; | |
//Big stepper motor delay between steps in milliseconds | |
int stepDelay = 100; | |
int boardSelect = 0; | |
//Initialization of the Pins. | |
//There are multiple values that are corresponding to the same pins | |
//As you can see inA1 == w0 from the bottom declarations. | |
//This is done just for the sake of readability as the pins can get | |
//confusing as we add more and more different servors that function in the Tango. | |
int inA1 = D0; | |
int inA2 = D1; | |
int inB1 = D2; | |
int inB2 = D3; | |
int inC1 = D4; | |
int motors = 1; | |
int w0 = D0; // input 1 of the stepper | |
int w2 = D2; // input 2 of the stepper | |
int w4 = D4; // input 3 of the stepper | |
int w6 = D6; // input 4 of the stepper | |
int w1 = D1; // input 1 of the stepper | |
int w3 = D3; // input 2 of the stepper | |
int w5 = D5; // input 3 of the stepper | |
int w7 = D7; // input 4 of the stepper | |
void setup() { | |
// Sets the data rate (baud) | |
// to 9600 bits per second | |
Serial.begin(9600); | |
delay(10); | |
// This flag is set to make sure that | |
// we send only one message to the phone | |
clientNewConnection = 1; | |
// Setting up the Pin Modes to their correct function. | |
// Not all servos use all the pins, infact only the one of them uses all 8 of them. | |
pinMode(inA1, OUTPUT); | |
pinMode(inA2, OUTPUT); | |
pinMode(inB1, OUTPUT); | |
pinMode(inB2, OUTPUT); | |
pinMode(inC1, OUTPUT); | |
pinMode(D5, OUTPUT); | |
pinMode(D6, OUTPUT); | |
pinMode(D7, OUTPUT); | |
// Not very useful, just making LEDs blink. | |
pinMode(LED_BUILTIN, OUTPUT); | |
digitalWrite(LED_BUILTIN, 0); | |
// Connect to WiFi network | |
Serial.println(); | |
Serial.println(); | |
Serial.print("Connecting to "); | |
Serial.println(ssid); | |
// Connecting to the WiFi with | |
// These credentials { ssid, password } | |
WiFi.mode(WIFI_STA); | |
WiFi.begin(ssid, password); | |
//Wait until connection finishes here, | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(500); | |
Serial.print("."); | |
} | |
Serial.println("WiFi connected"); | |
// Start the server | |
server.begin(); | |
Serial.println("Server started"); | |
// We now have a WebServer at the location | |
// http://<<public_IP>>/ | |
// Print the IP address | |
Serial.println(WiFi.localIP()); | |
} | |
//Worm Gear stepper motor functions. | |
//Each one of these does about 4/360 degrees. | |
//The total of all 4 does 16/360. | |
//In order to chose a direction to go with, | |
//We need to call these 4 functions in a different order. | |
void wStep1() { | |
digitalWrite(w0, LOW); | |
digitalWrite(w2, HIGH); | |
digitalWrite(w4, HIGH); | |
digitalWrite(w6, LOW); | |
digitalWrite(w1, LOW); | |
digitalWrite(w3, HIGH); | |
digitalWrite(w5, HIGH); | |
digitalWrite(w7, LOW); | |
delay(wStepDelay); | |
} | |
void wStep2() { | |
digitalWrite(w0, LOW); | |
digitalWrite(w2, HIGH); | |
digitalWrite(w4, LOW); | |
digitalWrite(w6, HIGH); | |
digitalWrite(w1, LOW); | |
digitalWrite(w3, HIGH); | |
digitalWrite(w5, LOW); | |
digitalWrite(w7, HIGH); | |
delay(wStepDelay); | |
} | |
void wStep3() { | |
digitalWrite(w0, HIGH); | |
digitalWrite(w2, LOW); | |
digitalWrite(w4, LOW); | |
digitalWrite(w6, HIGH); | |
digitalWrite(w1, HIGH); | |
digitalWrite(w3, LOW); | |
digitalWrite(w5, LOW); | |
digitalWrite(w7, HIGH); | |
delay(wStepDelay); | |
} | |
void wStep4() { | |
digitalWrite(w0, HIGH); | |
digitalWrite(w2, LOW); | |
digitalWrite(w4, HIGH); | |
digitalWrite(w6, LOW); | |
digitalWrite(w1, HIGH); | |
digitalWrite(w3, LOW); | |
digitalWrite(w5, HIGH); | |
digitalWrite(w7, LOW); | |
delay(wStepDelay); | |
} | |
//Stops any servo by setting everything to '0'. | |
void stopMotor() { | |
digitalWrite(w0, LOW); | |
digitalWrite(w2, LOW); | |
digitalWrite(w4, LOW); | |
digitalWrite(w6, LOW); | |
digitalWrite(w1, LOW); | |
digitalWrite(w3, LOW); | |
digitalWrite(w5, LOW); | |
digitalWrite(w7, LOW); | |
} | |
//Making the worm gear servo go up. | |
void goUp(int rot){ | |
for (int i=0; i< rot; i++){ | |
wStep1(); | |
wStep2(); | |
wStep3(); | |
wStep4(); | |
} | |
} | |
//Making the worm gear servo go down. | |
void goDown(int rot){ | |
for (int i=0; i< rot; i++){ | |
wStep3(); | |
wStep2(); | |
wStep1(); | |
wStep4(); | |
} | |
} | |
//Stepper function for the big stepper motor. | |
void stepper(int motor, int steps, boolean stepDirection){ | |
//first check the direction, if it's not the current direction change it. | |
currentDirection = digitalRead(stepperDirectionPin[motor]); | |
yield(); | |
if(stepDirection != currentDirection){ | |
digitalWrite(stepperDirectionPin[motor], stepDirection); | |
//this delay makes the motor stop for a while when changing direction. | |
currentDirection = stepDirection; | |
delay(10); | |
} | |
//a for loop to create the pulse | |
for(int s=0; s<steps; s++){ | |
//the LOW, then HIGH creates the pulse the driver is waiting for, no delay needed. | |
digitalWrite(stepperPulsePin[motor],LOW); | |
digitalWrite(stepperPulsePin[motor], HIGH); | |
//this delay creates the pulse, the lower the number the faster the pulse. | |
//play around with it to get your desired speed | |
delayMicroseconds(2000); | |
yield(); | |
} | |
} | |
//Same deal with the steps, this is for the previous worm servo that was not strong enough. | |
void step1() { | |
digitalWrite(inA1, LOW); | |
digitalWrite(inA2, HIGH); | |
digitalWrite(inB1, HIGH); | |
digitalWrite(inB2, LOW); | |
delay(stepDelay); | |
} | |
void step2() { | |
digitalWrite(inA1, LOW); | |
digitalWrite(inA2, HIGH); | |
digitalWrite(inB1, LOW); | |
digitalWrite(inB2, HIGH); | |
delay(stepDelay); | |
} | |
void step3() { | |
digitalWrite(inA1, HIGH); | |
digitalWrite(inA2, LOW); | |
digitalWrite(inB1, LOW); | |
digitalWrite(inB2, HIGH); | |
delay(stepDelay); | |
} | |
void step4() { | |
digitalWrite(inA1, HIGH); | |
digitalWrite(inA2, LOW); | |
digitalWrite(inB1, HIGH); | |
digitalWrite(inB2, LOW); | |
delay(stepDelay); | |
} | |
void wStopMotor() { | |
motors = 0; | |
digitalWrite(inA1, LOW); | |
digitalWrite(inA2, LOW); | |
digitalWrite(inB1, LOW); | |
digitalWrite(inB2, LOW); | |
} | |
void go16Up(int rot){ | |
for (int i=0; i < rot; i++){ | |
step1(); | |
step2(); | |
step3(); | |
step4(); | |
if(motors == 0){ break; } | |
} | |
} | |
void go16Down(int rot){ | |
for (int i=0; i < rot; i++){ | |
step3(); | |
step2(); | |
step1(); | |
step4(); | |
if(motors == 0){ break; } | |
} | |
} | |
void setupLinear(){ | |
//Making sure the linear actuator is at the lowest height. | |
//This is important for the scaling of the Linear actuator as we need to know what | |
//it's current height is. | |
digitalWrite(D0, LOW); | |
digitalWrite(D1, HIGH); | |
delay(2000); | |
digitalWrite(D1, LOW); | |
height = 0; | |
} | |
//This goes half way down with the linear Actuator. | |
void goOneDown(){ | |
if(height > 0){ | |
digitalWrite(D1, HIGH); | |
digitalWrite(D0, LOW); | |
delay(1000); | |
digitalWrite(D1, LOW); | |
height--; | |
} | |
} | |
//This goes half way Up with the linear Actuator. | |
void goOneUp(){ | |
if(height < 2){ | |
digitalWrite(D0, HIGH); | |
digitalWrite(D1, LOW); | |
delay(1000); | |
digitalWrite(D0, LOW); | |
height++; | |
} | |
} | |
//This code used to be here for the linear actuayor. | |
//This used to work with the buttons but then got upgraded to the seekbar. | |
//I left this here in case you wanted to use the buttons. | |
void digitalParser(int val){ | |
Serial.println("Digital parser entered "); | |
if(val == 0){ | |
//low | |
goOneDown(); | |
goOneDown(); | |
}else if(val == 1){ | |
//med | |
if(height == 2){ | |
goOneDown(); | |
}else if(height == 0){ | |
goOneUp(); | |
}//else dont do anything | |
}else{ | |
//high | |
goOneUp(); | |
goOneUp(); | |
} | |
} | |
// Making sure the values given by the Android App | |
// Aren't too large or too low for the linear actuator. | |
void digitalPercentParser(int dir, int rot){ | |
rot = abs(rot); | |
//2000 -- > 2.5 inch --> 25 rot | |
//?? -- > rot | |
//scaling the rot value sent by the phone to a value that | |
//can be interpreted by the linear actuator. | |
int rotDelay = (int)(abs(rot)*2500*4/25); | |
Serial.print("ROT DELAY : "); | |
Serial.println(rotDelay); | |
if(dir == 1){ | |
//Checking that nothing is off the desirable height limit up. | |
height = (height + rotDelay > 2000) ? 2000 : height + rotDelay; | |
digitalWrite(D0, HIGH); | |
digitalWrite(D1, LOW); | |
delay(rotDelay); | |
digitalWrite(D0, LOW); | |
}else{ | |
//Checking that nothing is off the desirable height limit down. | |
height = (height - rotDelay < 0) ? 0 : height - rotDelay; | |
digitalWrite(D1, HIGH); | |
digitalWrite(D0, LOW); | |
delay(rotDelay); | |
digitalWrite(D1, LOW); | |
} | |
} | |
int scaleAnalog(int val){ | |
val = val > 25 ? 25 : val; | |
val = val < 0 ? 0 : val; | |
val = val*1023/25; | |
return val; | |
} | |
//This is possibly the most important function in this file. | |
//The purpose of this function is to parse the webrequest sent by the phone | |
//and gather the correct Data thanks to it. | |
int clientParseReq(String req, WiFiClient client){ | |
delay(15); | |
if (req.indexOf("boardSelect=200/") != -1){ | |
//This is never called other than manually entering the value "IPADDRESS/boardSelect=200/" | |
//Hard Home for the Linear Actuator | |
setupLinear(); | |
}else if(req.indexOf("/boardSelect=1/mtrOff=1") != -1){ | |
// Put the motors Off. | |
stopMotor(); | |
}else if (req.indexOf("/boardSelect=3/rot=01") != -1){ | |
//This sends the big stepper motor that it should move to the lowest height. | |
digitalWrite(D0, HIGH); | |
digitalWrite(D1, LOW); | |
delay(100); | |
digitalWrite(D0, LOW); | |
digitalWrite(D1, LOW); | |
}else if (req.indexOf("/boardSelect=3/rot=11") != -1){ | |
//This sends the big stepper motor that it should move to the highest height. | |
digitalWrite(D0, HIGH); | |
digitalWrite(D1, HIGH); | |
delay(100); | |
digitalWrite(D0, LOW); | |
digitalWrite(D1, LOW); | |
}else if (req.indexOf("/boardSelect=3/rot=10") != -1){ | |
//This sends the big stepper motor that it should move to the middle height. | |
digitalWrite(D0, LOW); | |
digitalWrite(D1, HIGH); | |
delay(100); | |
digitalWrite(D0, LOW); | |
digitalWrite(D1, LOW); | |
}else if (req.indexOf("/boardSelect=3/dir=1/rot=") != -1){ | |
String rotNum = req.substring(req.indexOf("/dir=1/rot=") + strlen("/dir=1/rot="), req.indexOf("/endTurn")); | |
//gets the value of the rotation from | |
//requests sent in the format "IPADDRESS//boardSelect=3/dir=1/rot=100/endTurn" | |
//then the value of rotNum will be "100". whilst going down. | |
goUp(abs(rotNum.toInt())); | |
}else if (req.indexOf("/boardSelect=3/dir=-1/rot=") != -1){ | |
String rotNum = req.substring(req.indexOf("/dir=-1/rot=") + strlen("/dir=-1/rot="), req.indexOf("/endTurn")); | |
//gets the value of the rotation from | |
//requests sent in the format "IPADDRESS//boardSelect=3/dir=-1/rot=100/endTurn" | |
//then the value of rotNum will be "100". whilst going up. | |
goDown(abs(rotNum.toInt())); | |
}else if (req.indexOf("/boardSelect=2/dir=1/rot=") != -1){ | |
String rotNum = req.substring(req.indexOf("/dir=1/rot=") + strlen("/dir=1/rot="), req.indexOf("/endTurn")); | |
//gets the value of the rotation from | |
//requests sent in the format "IPADDRESS//boardSelect=2/dir=-1/rot=100/endTurn" | |
//then the value of rotNum will be "100". whilst going up. | |
//Notice that the only difference between the last request and this one is the boardSelect value = 2. | |
//This alone makes different servos work. | |
digitalPercentParser(1, abs(rotNum.toInt())); | |
//Same deal for the rest. | |
}else if (req.indexOf("/boardSelect=2/dir=-1/rot=") != -1){ | |
String rotNum = req.substring(req.indexOf("/dir=-1/rot=") + strlen("/dir=-1/rot="), req.indexOf("/endTurn")); | |
digitalPercentParser(-1, abs(rotNum.toInt())); | |
}else if (req.indexOf("/boardSelect=1/dir=1/rot=") != -1){ | |
String rotNum = req.substring(req.indexOf("/dir=1/rot=") + strlen("/dir=1/rot="), req.indexOf("/endTurn")); | |
Serial.println("ROTATION NUM : " + rotNum); | |
go16Up(abs(rotNum.toInt()*20)); | |
}else if (req.indexOf("/boardSelect=1/dir=-1/rot=") != -1){ | |
String rotNum = req.substring(req.indexOf("/dir=-1/rot=") + strlen("/dir=-1/rot="), req.indexOf("/endTurn")); | |
Serial.println("ROTATION NUM : " + rotNum); | |
go16Down(abs(rotNum.toInt()*20)); | |
} else { | |
Serial.println("invalid request" + req); | |
//client.stop(); | |
return -1; | |
} | |
return 1; | |
} | |
//resolution of 360/16 22.5 Degrees | |
int convertPinsToInt(int recPin, int pin0, int pin1, int pin2, int pin3){ | |
recPin = digitalRead(recPin); | |
int sum = 0; | |
if(recPin == 1){ | |
int p2 = digitalRead(pin0); | |
int p1 = digitalRead(pin1); | |
int p0 = digitalRead(pin2); | |
sum += (p2 == 1)? 2*2*2 : 0; | |
sum += (p1 == 1)? 2*2 : 0; | |
sum += (p0 == 1)? 1 : 0; | |
} | |
sum *= (digitalRead(pin3) == 1) ? -1 : 1; | |
return sum; | |
} | |
//Lets us talk with pins to the Arduino, we decided to go with an other method later. | |
void convertIntToPins(int val, int pin0, int pin1, int pin2, int pin3, int sendPin){ | |
if(val <= 0){ | |
val *= -1; | |
digitalWrite(pin3, 1); | |
}else{ | |
digitalWrite(pin3, 0); | |
} | |
digitalWrite(pin0, val%2); | |
val = val/2; | |
digitalWrite(pin1, val%2); | |
val = val/2; | |
digitalWrite(pin2, val%2); | |
digitalWrite(sendPin, HIGH); | |
delay(500); | |
digitalWrite(sendPin, LOW); | |
} | |
void loop() { | |
if(clientNewConnection == 1){ | |
//This is where we are sending the request to the webservice called IFTTT, which then lets us send | |
//the IP address to the phone. | |
WiFiClient client; | |
const char * host = "maker.ifttt.com"; | |
const int httpPort = 80; | |
if (!client.connect(host, httpPort)) { Serial.println("Connection failed"); return; } | |
// We now create a URI for the request | |
// These URI are very important and specified by IFTTT themselves. | |
String url = "/trigger"; | |
url += "/ip_request"; | |
url += "/with/key"; | |
url += "/KEY HERE"; //"/c5baLjP2xIrx7HRK5WyBFq"; | |
// This is where the IP address is entered, | |
// the data is then entered in JSON Format. | |
String content = "{\"value1\": \"" + WiFi.localIP().toString() + "\"}"; | |
client.print(String("POST ") + url + " HTTP/1.1\r\n" + | |
"Host: " + host + "\r\n" + | |
"Content-Type: application/json\r\n" + | |
"Content-Length: " + String(content.length()) + "\r\n\n" + | |
content + "\r\n" + | |
"Connection: close\r\n\r\n");\ | |
Serial.println(url); | |
delay(100); | |
clientNewConnection = 0; | |
client.flush(); | |
} | |
WiFiClient client = server.available(); | |
if (!client) { | |
return; | |
} | |
// Wait until the client sends some data | |
while (!client.available()) { | |
delay(1); | |
} | |
Serial.println("new client"); | |
// Read the first line of the request | |
String req = client.readStringUntil('\r'); | |
Serial.println(req); | |
client.flush(); | |
client.println("POST /posts HTTP/1.1/connected" + req); | |
delay(1); | |
client.flush(); | |
//Parse what was sent. | |
clientParseReq(req, client); | |
delay(1); | |
//client.stop(); | |
Serial.println("Client disonnected"); | |
// The client will actually be disconnected | |
// when the function returns and 'client' object is detroyed | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment