Files
TweinStein/ESP8266/ESP8266main.c

454 lines
17 KiB
C
Raw Normal View History

2026-06-12 02:55:04 -07:00
// ESP8266main.c
// testmain for ESP8266 module to act as a WiFi client or server
// Currently restricted to one incoming or outgoing connection at a time
//
// Steven Prickett (steven.prickett@gmail.com)
// Modified version by Dung Nguyen, Wally Guzman
// Modified by Jonathan Valvano, March 28, 2017
// Consolidated by Andreas Gerstlauer, April 6, 2020
// Converted to MSPM0G3507 UART2 by Jonathan Valvano, Jan 18, 2026
/*
THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
// NOTE: see ESP8266 files in datasheets folder
/* Hardware connections
Vcc is a separate regulated 3.3V supply with at least 215mA
/------------------------------\
| chip 1 8 |
| Ant 2 7 |
| enna processor 3 6 |
| 4 5 |
\------------------------------/
Connects MSPM0
UART1 on (PA17/PA18) or UART2 on (PB17/PB18)
Reset on PA25
Ok to not access PB19 because of the internal pullup in ESP8266
ESP8266 MSPM0 Motor board version 7
1 URxD PA17 UART1 out of MSPM0, into ESP8266 115200 baud
2 GPIO0 +3.3V for normal operation (ground to flash)
3 GPIO2 PB19 GPIO, high/float on startup, has internal pullup, can be used for I/O
4 GND Gnd GND (70mA)
5 UTxD PA18 UART out of ESP8266, UART1 into MSPM0 115200 baud
6 Ch_PD chip select, 10k resistor to 3.3V
7 Reset PA25 MSPM0 GPIO output, can issue output low to cause hardware reset
8 Vcc regulated 3.3V supply with at least 70mA
ESP8266 MSPM0 Motor board version 7.1
1 URxD PB17 UART2 out of MSPM0, into ESP8266 115200 baud
2 GPIO0 +3.3V for normal operation (ground to flash)
3 GPIO2 PB19 GPIO, high/float on startup, has internal pullup, can be used for I/O
4 GND Gnd GND (70mA)
5 UTxD PB18 UART out of ESP8266, UART2 into MSPM0 115200 baud
6 Ch_PD chip select, 10k resistor to 3.3V
7 Reset PA25 MSPM0 GPIO output, can issue output low to cause hardware reset
8 Vcc regulated 3.3V supply with at least 70mA
*/
/* Derived from i2c_controller_rw_multibyte_fifo_poll_LP_MSPM0G3507_nortos_ticlang
VCC to +3.3V
I2C SCL: PB2 is the SSD1306 SCL, with 1.5k pullup to 3.3V
I2C SDA: PB3 is the SSD1306 SDA
GND to GND
*/
#include <ti/devices/msp/msp.h>
#include "../inc/LaunchPad.h"
#include "../inc/Clock.h"
#include "../inc/SSD1306.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "../RTOS_Labs_common/esp8266.h"
#include "../inc/UART.h"
// Client or Server ESP8266 Initialization
// 0 means client, != 0 means server at specified port
//#define SERVER 80 // port 80 is for http
// Transparently forwarding debug mode
// #define TRANSPARENT 1
#if (! TRANSPARENT) && (! SERVER)
// client mode
const char Fetch[] = "GET /data/2.5/weather?q=Austin%20Texas&APPID=e8dc75caa5babe657b849dd5e75a19a9 HTTP/1.1\r\nHost:api.openweathermap.org\r\n\r\n";
// 1) go to http://openweathermap.org/appid#use
// 2) Register on the Sign up page
// 3) get an API key (APPID) replace the 1234567890abcdef1234567890abcdef with your APPID
char LOGDATA[] ="GET /php/json/write.php?name=Robot13&bump=19&steering=123&right=456&left=678&systick=44&addthread=75&jitter=75 HTTP/1.0\r\nHOST: embedded.ece.utexas.edu\r\n\r\n";
char Response[512];
char Status[16];
uint16_t StartTime,EndTime,ElaspedTime;
const char OpenWeathermap[] ="api.openweathermap.org";
const char Embedded_ece[] ="embedded.ece.utexas.edu";
int main(void){ // main1
uint32_t bump; char *s;
__disable_irq();
Clock_Init80MHz(0);
LaunchPad_Init(); // set system clock to 80 MHz
UART_Init(); // UART0 only used for debugging
TimerG8_Init(8,250); // 50us 3.2 s
__enable_irq();
UART_OutString("\r\nESP8266 ECE445M Test\r\n");
SSD1306_Init(SSD1306_SWITCHCAPVCC);
SSD1306_SetCursor(0,0);
SSD1306_ClearBuffer();
SSD1306_DrawString(0, 0,"ESP8266 ECE445M Test",SSD1306_WHITE); SSD1306_OutBuffer();
if(!ESP8266_Init(true,false)) { // initialize with rx echo
SSD1306_DrawString(0,16,"No Wifi adapter",SSD1306_WHITE); SSD1306_OutBuffer();
UART_OutString("\r\n---No ESP detected\r\n");
while(1) {}
}
UART_OutString("\r\n-----------System starting...\r\n");
ESP8266_GetVersionNumber();
if(!ESP8266_Connect(true)) { // connect to access point
SSD1306_DrawString(0,16,"No Wifi network",SSD1306_WHITE); SSD1306_OutBuffer();
UART_OutString("\r\n---Failure connecting to access point\r\n");
while(1) {}
}
SSD1306_DrawString(0,16,"Wifi connected",SSD1306_WHITE); SSD1306_OutBuffer();
GPIOB->DOUTSET31_0 = BLUE;
// Lab 6 test
ESP8266_GetStatus();
while(1){
UART_OutString(LOGDATA);
bump = 10*(LOGDATA[42]-'0')+(LOGDATA[43]-'0');
SSD1306_DrawString(0,32,"bump: ",SSD1306_WHITE);
SSD1306_DrawUDec(56,32,bump,SSD1306_WHITE); SSD1306_OutBuffer();
if(ESP8266_MakeTCPConnection((char *)Embedded_ece, 80, 0, false)){
// open socket to web server on port 80
ESP8266_StartReceiveSearch("status=");
StartTime = TIMG8->COUNTERREGS.CTR;
if(ESP8266_Send(LOGDATA)){
// if(ESP8266_Receive(Response, 512)){ // receive response
// UART_OutString(Response);
uint32_t TimeOut=10000000;
do{ s = ESP8266_GetReceiveBuffer(); // get status
TimeOut--;
}while((s==0)&&TimeOut);
EndTime = TIMG8->COUNTERREGS.CTR;
ElaspedTime = StartTime-EndTime;
if(s){
int i=0;
while(((*s)!=' ')&&(i<15)){
Status[i] = *s;
s++; i++;
}
Status[i] = 0;
SSD1306_DrawString(0,44," ",SSD1306_WHITE);
SSD1306_DrawString(0,44,Status,SSD1306_WHITE);
SSD1306_DrawString(0,56,"Time(ms) ",SSD1306_WHITE);
SSD1306_DrawUDec(56,56,ElaspedTime/20,SSD1306_WHITE);
SSD1306_OutBuffer();
}
}
}
while(LaunchPad_InS2()==0){// wait for S2 touch
}
if(LOGDATA[43] == '9'){
LOGDATA[42] = LOGDATA[42]+1;
LOGDATA[43] = '0';
}else{
LOGDATA[43] = LOGDATA[43]+1;
}
GPIOB->DOUTCLR31_0 = GREEN;
GPIOB->DOUTSET31_0 = BLUE;
GPIOB->DOUTTGL31_0 = RED;
}
}
int main2(void){ uint32_t len; char *s; char *e; int32_t data;
__disable_irq();
Clock_Init80MHz(0);
LaunchPad_Init(); // set system clock to 80 MHz
UART_Init(); // UART0 only used for debugging
__enable_irq();
UART_OutString("\r\nESP8266 GetWeather Test\r\n");
SSD1306_Init(SSD1306_SWITCHCAPVCC);
SSD1306_SetCursor(0,0);
SSD1306_ClearBuffer();
SSD1306_DrawString(0, 0,"ESP8266 GetWeather",SSD1306_WHITE); SSD1306_OutBuffer();
if(!ESP8266_Init(true,false)) { // initialize with rx echo
SSD1306_DrawString(0,16,"No Wifi adapter",SSD1306_WHITE); SSD1306_OutBuffer();
UART_OutString("\r\n---No ESP detected\r\n");
while(1) {}
}
UART_OutString("\r\n-----------System starting...\r\n");
ESP8266_GetVersionNumber();
if(!ESP8266_Connect(true)) { // connect to access point
SSD1306_DrawString(0,16,"No Wifi network",SSD1306_WHITE); SSD1306_OutBuffer();
UART_OutString("\r\n---Failure connecting to access point\r\n");
while(1) {}
}
SSD1306_DrawString(0,16,"Wifi connected",SSD1306_WHITE); SSD1306_OutBuffer();
GPIOB->DOUTSET31_0 = BLUE;
ESP8266_GetStatus();
while(1){
ESP8266_GetStatus();
if(ESP8266_MakeTCPConnection((char *)OpenWeathermap, 80, 0, false)){ // open socket to web server on port 80
if(ESP8266_Send(Fetch)){ // send request
SSD1306_DrawString(0,16," ",SSD1306_WHITE); // 20 characters
SSD1306_DrawString(0,32," ",SSD1306_WHITE); // 20 characters
SSD1306_DrawString(0,40," ",SSD1306_WHITE); // 20 characters
SSD1306_OutBuffer();
if(ESP8266_Receive(Response, 512)){ // receive response
if(strncmp(Response, "HTTP", 4) == 0) { // received HTTP response?
SSD1306_DrawString(0,16,"Weather fetched",SSD1306_WHITE); SSD1306_OutBuffer();
GPIOB->DOUTCLR31_0 = BLUE;
GPIOB->DOUTSET31_0 = GREEN;
len = 0;
while(strlen(Response)) { // parse HTTP headers until empty line
if(!ESP8266_Receive(Response, 512)){
len = 0;
break;
}
if(strncmp(Response, "Content-Length: ", 16) == 0) {
len = atol(Response+16); // get HTML body size
}
}
if(len) { // Get HTML body and parse for weather info
ESP8266_Receive(Response, (len < 512)? (len+1) : 512);
s = strstr(Response, "\"temp\":"); // get temperature
if(s){
data = atol(s+7);
SSD1306_DrawString(0,32,"Temp [C]: ",SSD1306_WHITE);
SSD1306_DrawUDec(56,32,data-273,SSD1306_WHITE); SSD1306_OutBuffer();
}
s = strstr(Response, "\"description\":"); // get description
if(s){
e = strchr(s+15, '"'); // find end of substring
if(e){
*e = 0; // temporarily terminate with zero
SSD1306_DrawString(0,40,s+15,SSD1306_WHITE); SSD1306_OutBuffer();
}
}
} else {
SSD1306_DrawString(0,16,"Empty response",SSD1306_WHITE); SSD1306_OutBuffer();
}
} else {
SSD1306_DrawString(0,16,"Invalid response",SSD1306_WHITE); SSD1306_OutBuffer();
}
} else {
SSD1306_DrawString(0,16,"No response",SSD1306_WHITE); SSD1306_OutBuffer();
}
} else {
SSD1306_DrawString(0,16,"Send failed",SSD1306_WHITE); SSD1306_OutBuffer();
}
ESP8266_CloseTCPConnection(); // close connection
} else {
SSD1306_DrawString(0,16,"Connection failed",SSD1306_WHITE); SSD1306_OutBuffer();
}
while(LaunchPad_InS2()==0){// wait for S2 touch
}
GPIOB->DOUTCLR31_0 = GREEN;
GPIOB->DOUTSET31_0 = BLUE;
GPIOB->DOUTTGL31_0 = RED;
}
}
#elif SERVER
/*
======================================================================================================================
========== Simple HTTP SERVER ==========
======================================================================================================================
*/
const char formBody[] =
"<!DOCTYPE html><html><body><center> \
<h1>Enter a message to send to your microcontroller:</h1> \
<form> \
<input type=\"text\" name=\"message\" value=\"Hello ESP8266!\"> \
<br><input type=\"submit\" value=\"Go!\"> \
</form></center></body></html>";
const char statusBody[] =
"<!DOCTYPE html><html><body><center> \
<h1>Message sent successfully!</h1> \
</body></html>";
/*
===================================================================================================
HTTP :: HTTP_ServePage
- constructs and sends a web page via the ESP8266 server
- NOTE: this seems to work for sending pages to Firefox (and maybe other PC-based browsers),
but does not seem to load properly on iPhone based Safari. May need to add some more
data to the header.
===================================================================================================
*/
void itoa(uint32_t n, char message[8]);
int HTTP_ServePage(const char* body){
char header[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\nContent-Length: ";
char contentLength[16];
itoa(strlen(body),contentLength);
// sprintf(contentLength, "%d\r\n\r\n", strlen(body));
strcat(contentLength, "\r\n\r\n");
if(!ESP8266_SendBuffered(header)) return 0;
if(!ESP8266_SendBuffered(contentLength)) return 0;
if(!ESP8266_SendBuffered(body)) return 0;
if(!ESP8266_SendBufferedStatus()) return 0;
return 1;
}
char HTTP_Request[64];
int main(void){
__disable_irq();
Clock_Init80MHz(0);
LaunchPad_Init(); // set system clock to 80 MHz
UART_Init(); // UART0 only used for debugging
__enable_irq();
UART_OutString("\r\nESP8266 Server Test\r\n");
SSD1306_Init(SSD1306_SWITCHCAPVCC);
SSD1306_SetCursor(0,0);
SSD1306_ClearBuffer();
SSD1306_DrawString(0, 0,"ESP8266 Server Test",SSD1306_WHITE); SSD1306_OutBuffer();
if(!ESP8266_Init(true,false)){ // initialize with rx echo
SSD1306_DrawString(0,16,"No Wifi adapter",SSD1306_WHITE); SSD1306_OutBuffer();
UART_OutString("\r\n---No ESP detected\r\n");
while(1) {}
}
UART_OutString("\r\n-----------System starting...\r\n");
ESP8266_GetVersionNumber();
if(!ESP8266_Connect(true)){ // connect to access point
SSD1306_DrawString(0,16,"No Wifi network",SSD1306_WHITE); SSD1306_OutBuffer();
UART_OutString("\r\n---Failure connecting to access point\r\n");
while(1) {}
}
SSD1306_DrawString(0,16,"Wifi connected",SSD1306_WHITE); SSD1306_OutBuffer();
if(!ESP8266_StartServer(SERVER,600)){ // 5min timeout
SSD1306_DrawString(0,16,"Server failure",SSD1306_WHITE); SSD1306_OutBuffer();
UART_OutString("\r\n---Failure starting server\r\n");
while(1) {}
}
SSD1306_DrawString(0,24,"Server started",SSD1306_WHITE); SSD1306_OutBuffer();
GPIOB->DOUTSET31_0 = BLUE;
while(1) {
// Wait for connection
ESP8266_WaitForConnection();
SSD1306_DrawString(0,32,"Server started",SSD1306_WHITE); SSD1306_OutBuffer();
// Receive request
if(!ESP8266_Receive(HTTP_Request, 64)){
SSD1306_DrawString(0,40,"No request",SSD1306_WHITE); SSD1306_OutBuffer();
ESP8266_CloseTCPConnection();
continue;
}
// check for HTTP GET
if(strncmp(HTTP_Request, "GET", 3) == 0) {
char* messagePtr = strstr(HTTP_Request, "?message=");
if(messagePtr) {
// Clear any previous message
SSD1306_DrawString(0,40," ",SSD1306_WHITE); SSD1306_OutBuffer();
// Process form reply
if(HTTP_ServePage(statusBody)) {
SSD1306_DrawString(0,40,"Served status",SSD1306_WHITE); SSD1306_OutBuffer();
GPIOB->DOUTSET31_0 = BLUE;
GPIOB->DOUTCLR31_0 = GREEN;
} else {
SSD1306_DrawString(0,40,"Error serving status",SSD1306_WHITE); SSD1306_OutBuffer();
}
// Terminate message at first separating space
char* messageEnd = strchr(messagePtr, ' ');
if(messageEnd) *messageEnd = 0; // terminate with null character
// Print message on terminal
SSD1306_DrawString(0,48,messagePtr + 9,SSD1306_WHITE); SSD1306_OutBuffer();
UART_OutString("\r\n---Message from the Internet: ");
UART_OutString(messagePtr + 9);
UART_OutString("\n\r");
} else {
// Serve web page
if(HTTP_ServePage(formBody)) {
SSD1306_DrawString(0,40,"Served form",SSD1306_WHITE); SSD1306_OutBuffer();
GPIOB->DOUTCLR31_0 = BLUE;
GPIOB->DOUTSET31_0 = GREEN;
} else {
SSD1306_DrawString(0,40,"Error serving form",SSD1306_WHITE); SSD1306_OutBuffer();
}
}
} else {
// handle data that may be sent via means other than HTTP GET
SSD1306_DrawString(0,40,"Not a GET request",SSD1306_WHITE); SSD1306_OutBuffer();
}
GPIOB->DOUTTGL31_0 = RED;
ESP8266_CloseTCPConnection();
}
}
// works for 0 to 999
void itoa(uint32_t n, char message[8]){
if(n>999)n=999;
if(n>=100){ // 100 to 999
message[0] = (n/100+'0'); /* hundreds digit */
n = n%100; //the rest
message[1] = (n/10+'0'); /* tens digit */
n = n%10; //the rest
message[2] = (n+'0'); /* tenths digit */
message[3] = 0;
}else { // 0 to 99
if(n>=10){ // 10 to 99
message[0] = (n/10+'0'); /* tens digit */
n = n%10; //the rest
message[1] = (n+'0'); /* tenths digit */
message[2] = 0;
}else{ // 0 to 9
message[0] = (n+'0'); /* tenths digit */
message[1] = 0;
}
}
}
#else // TRANSPARENT
// transparent mode for testing
void ESP8266_SendCommand(char *);
void ESP8266_OutChar(char);
int main(void){ char data;
DisableInterrupts();
PLL_Init(Bus80MHz);
LED_Init();
Output_Init(); // UART0 as a terminal
EnableInterrupts();
if(!ESP8266_Init(true,false)) { // initialize with rx echo
printf("\r\n---No ESP detected\r\n");
while(1) {}
}
printf("\r\n-----------System starting...\r\n");
ESP8266_Reset();
// ESP8266_SendCommand("AT+UART=115200,8,1,0,3\r\n");
// data = UART_InChar();
while(1){
// echo data back and forth
data = UART_InCharNonBlock();
if(data){
ESP8266_OutChar(data);
}
}
}
#endif