Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#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