Skip to content

Instantly share code, notes, and snippets.

@xesscorp
Last active December 7, 2021 17:06
Show Gist options
  • Save xesscorp/3f791cdec611db3eb400 to your computer and use it in GitHub Desktop.
Save xesscorp/3f791cdec611db3eb400 to your computer and use it in GitHub Desktop.
This program issues commands to an ESP8266 Wifi module in order to receive an HTML page from a website.
///////////////////////////////////////////////////////////////////////////////////////
// This program uses the ESP8266 Wifi module to access a webpage. It's an adaptation of
// the program discussed at http://hackaday.io/project/3072/instructions
// and shown here http://dunarbin.com/esp8266/retroBrowser.ino .
//
// This program was ported to the ZPUino 2.0, a softcore processor that runs on an FPGA
// and emulates an Arduino.
//
// This program works with version 00160901 of the ESP8266 firmware.
///////////////////////////////////////////////////////////////////////////////////////
#define SSID "XESS"
#define PASS "6a27a85603d39b7" // ESP8266 works with WPA2-PSK (AES) passwords.
//#define DEST_HOST "retro.hackaday.com"
//#define DEST_PAGE "/"
//#define DEST_IP "192.254.235.21"
#define DEST_HOST "www.xess.com"
#define DEST_PAGE "/static/media/pages/xess_esp8266.html"
#define DEST_IP "192.241.200.6"
#define DEST_PORT 80
#define TIMEOUT 10000 // mS
#define CONTINUE false
#define HALT true
#define DO_ECHO true
#define NO_ECHO false
#define CONNECTION_TRIES 5
#define ECHO_COMMANDS // Un-comment to echo AT+ commands to serial monitor.
// Print error message and loop stop.
void errorHalt(String msg)
{
Serial.println(msg);
Serial.println("HALT");
while(true);
}
// Wait until a char is received from the ESP8266. Then return it.
char getChar()
{
while(Serial1.available() == false)
;
return Serial1.read();
}
// Buffer used to compare strings against the output from the ESP8266.
#define CB_SIZE 20
char comp_buffer[CB_SIZE] = {0,}; // Fill buffer with string terminator.
// Get char from ESP8266 and also shift it into the comparison buffer.
char getCharAndBuffer()
{
char b = getChar();
char *cb_src, *cb_dst;
cb_src = comp_buffer+1;
cb_dst = comp_buffer;
for(int i=1; i<CB_SIZE-1; i++)
*cb_dst++ = *cb_src++;
*cb_dst = b;
return b;
}
// Compare the string against the newest contents of the buffer.
boolean cb_match(String &s)
{
return strcmp(s, comp_buffer + CB_SIZE - 1 - s.length()) == 0; // Return true on match.
}
// Read characters from ESP8266 module and echo to serial until keyword occurs or timeout.
boolean echoFind(String keyword, boolean do_echo)
{
// Fail if the target string has not been sent by deadline.
unsigned long deadline = millis() + TIMEOUT;
while(millis() < deadline)
{
char ch = getCharAndBuffer();
if(do_echo)
Serial.write(ch);
if(cb_match(keyword))
return true;
}
return false; // Timed out
}
// Echo module output until 3 newlines encountered.
// (Used when we're indifferent to "OK" vs. "no change" responses.)
void echoSkip()
{
echoFind("\n", DO_ECHO); // Search for nl at end of command echo
echoFind("\n", DO_ECHO); // Search for 2nd nl at end of response.
echoFind("\n", DO_ECHO); // Search for 3rd nl at end of blank line.
}
// Send a command to the module and wait for acknowledgement string
// (or flush module output if no ack specified).
// Echoes all data received to the serial monitor.
boolean echoCommand(String cmd, String ack, boolean halt_on_fail)
{
// Send the command to the ESP8266.
Serial1.print(cmd);
Serial1.write('\r'); // Append return to commands.
#ifdef ECHO_COMMANDS
Serial.println("\n\n\r--------------------------------------");
Serial.println("COMMAND: " + cmd + "\n");
#endif
// If no ack response specified, skip all available module output.
if (strlen(ack) == 0)
echoSkip();
else
{
// Otherwise wait for ack.
if (!echoFind(ack, DO_ECHO)) // timed out waiting for ack string
{
if (halt_on_fail)
errorHalt(cmd + " failed");// Critical failure halt.
else
return false; // Let the caller handle it.
}
}
return true; // ack blank or ack found
}
// Data packets have the format "+IPD,0,1024:lwkjfwsnv....". This routine gets
// the second number preceding the ":" that indicates the number of characters
// in the packet.
int getPacketLength()
{
while(getChar() != ',')
;
char len[10];
for(int i=0; i<10; i++)
{
char c = getChar();
if(c == ':')
{
len[i] = 0; // Terminate string.
break;
}
len[i] = c;
}
return atoi(len);
}
// Echo a received Wifi packet to the PC.
void echoPacket()
{
if(echoFind("+IPD,", NO_ECHO))
{
for(int l = getPacketLength(); l>0; l--)
Serial.write(getChar());
}
}
// Connect to the specified wireless network.
boolean connectWiFi(String ssid, String pwd)
{
String cmd = "AT+CWJAP=\"" + ssid + "\",\"" + pwd + "\"";
if (echoCommand(cmd, "OK", CONTINUE)) // Join Access Point
{
Serial.println("\nConnected to WiFi.");
return true;
}
else
{
Serial.println("\nConnection to WiFi failed.");
return false;
}
}
// Establish a TCP link to a given IP address and port.
boolean establishTcpLink(String ip, int port)
{
String cmd = "AT+CIPSTART=0,\"TCP\",\"" + ip + "\"," + port;
return echoCommand(cmd, "OK", HALT);
}
// Request a page from an HTTP server.
boolean requestPage(String host, String page, int port)
{
// Create raw HTTP request for web page.
String http_req = "GET " + page + " HTTP/1.1\r\nHost: " + host + ":" + port + "\r\n\r\n";
// Ready the module to receive raw data.
String cmd = "AT+CIPSEND=0,";
cmd = cmd + http_req.length(); // Tell the ESP8266 how long the coming HTTP request is.
if (!echoCommand(cmd, ">", CONTINUE))
{
echoCommand("AT+CIPCLOSE", "", CONTINUE);
errorHalt("Connection timeout");
}
// Send the raw HTTP request.
return echoCommand(http_req, "OK", CONTINUE);
}
HardwareSerial esp8266(2); // Find the ZPUino serial port connected to the ESP8266.
void setup()
{
Serial.begin(115200); // Initialize serial port to the PC.
Serial1 = esp8266; // Rename the ESP8266 serial port to something more standard.
// Initialize the serial port to the ESP8266, but also assign the RX & TX lines
// to specific pins of the ZPUino FPGA. Obviously, this part is not needed when
// using a standard Arduino.
Serial1.begin(115200, TX(3), RX(17));
// Wait for a keypress from the PC before running the demo.
while(!Serial.available())
;
Serial.read();
Serial.println("\n\n\n\r----------- ESP8266 Demo -----------\n\n");
echoCommand("AT+RST", "ready", HALT); // Reset the module.
echoCommand("AT+GMR", "OK", CONTINUE); // Show module's firmware ID.
echoCommand("AT+CWMODE=1", "", CONTINUE); // Set module into station mode.
echoCommand("AT+CIPMUX=1", "OK", CONTINUE); // Allow multiple connections. Necessary for TCP link.
delay(2000); // Let things settle down for a bit...
echoCommand("AT+CWLAP", "OK", HALT); // Scan for available access points.
// Connect to the Wifi.
for(int i=1; i<=CONNECTION_TRIES; i++)
{
if(connectWiFi(SSID, PASS))
break;
if(i == CONNECTION_TRIES)
errorHalt("Connection failed");
}
delay(4000); // Let the link stabilize.
echoCommand("AT+CIFSR", "", HALT); // Show the IP address assigned by the access point.
}
void loop()
{
establishTcpLink(DEST_IP, DEST_PORT);
delay(2000); // Once again, let the link stabilize.
// Show the connection status.
echoCommand("AT+CIPSTATUS", "OK", HALT);
// Request a page from an HTTP server.
requestPage(DEST_HOST, DEST_PAGE, DEST_PORT);
// Loop forever echoing data received over the Wifi from the HTTP server.
while(true)
echoPacket();
errorHalt("ONCE ONLY");
}
@robofred
Copy link

Hello There,

I'm not a programmer but I found your code and its been REALLY helpful, however:

I'm trying to update LEDs on my Arduino via the ESP8266 using a file on my website. The file will have an integer for each LED which will be either 0 (off) or 1 (on)... X 12 LEDs so it'll be a string like "010101110011".

I am able to see the contents of the file, but how can I pick out these 12 characters (integers?) from all the verbiage that comes through serial?

Any help would be MUCH appreciated. Thank you.

/Fred

@ambrogit
Copy link

Good day ,
I was reading those pages with a lot interest.
I have in mind to connect the ESP to my PIC MCU using the UART interface in order to send text data on a web page visible from any where . I am not able to find out such a sample program on the web.
Could you please give me some directions please ?
Thanks in advance.
regards,
Ambro

@Breidenbach
Copy link

I pasted the shown sketch into the Arduino IDE, but it would not compile. The Strings seem to be the problem. Any suggestions? Is there a special library to download?

@gabrielstellini
Copy link

@Breidenbach know its late, but how did you solve it?

@sfkhooper
Copy link

@Breidenbach @gabrielstellini I'm having the very same problem. Did either of you get this working?

@sfkhooper
Copy link

where is Serial1 defined? Arduino IDE gives me 'Serial1' was not declared in this scope

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment