Situation
I do not have a real Arduino or ESP, I am using TinkerCAD and in that setup, I have an Arduino Uno R3 connected to an LCD, a temperature sensor, a button, and an ESP8266 to send temperature readings to the ThingSpeak IoT cloud.
Electrical Wiring
The Arduino's hardware serial is connected to the ESP8266 and communicates at 115200 baud. I am using an NMOSFET (2N7000) level shifter to convert the Arduino's 5V TX to the ESP's 3.3V RX.
Arduino ESP8266
GND GND
+3.3V from power supply, not the Arduino 3.3V output (current restrictions)
RX (1) TX
TX (2) RX via NMOS level shifter
Enable to 3.3V supply
Reset to 3.3V supply
Issue
The software initializes the ESP, sets it to Station Mode, Connects to the WiFi. The statuses are updated on the LCD so that I know when those things go amiss. Then the actual processing consists of:
1. Reading the temperature sensor
2. Opening a single TCP connection to the ThingSpeak cloud
3. Sending the GET request to update my ThingSpeak data channel
4. Closing the TCP connection to ThingSpeak
All steps except #3 work correctly. There basically I send the AT+CIPSEND=<length> and I am supposed to receive an ">" from the ESP but it never happens, it doesn't respond to the CIPSEND with anything really. After that, I submit the actual GET request but there I get no response from ESP either.
I also tried using CIPSEND without length and terminating the GET packet with CTRL+Z but no results either.
I also tried not reading the ESP response after CIPSEND=length and simply shooting the GET after a delay but nothing either, my packet never gets to the Internet.
I also tried using Webhook.site to see if my request was getting there (although my ThingSpeak data is correct) but nothing either.
So, what am I missing? I have examined and used a lot of code out there but nothing seems to work. Spent already two full days trying everything to no avail.
The Code
Here is the relevant part of my code. You may notice some code to setup LCD status indicators to give me immediate visual feedback (I don't have a secondary serial terminal).
// ------------------- ESP8266 -----------------
/*
* Sets up the ESP8266, sets it to Station Mode and Connects WiFi AP
* REF: https://room-15.github.io/blog/2015/03/26/esp8266-at-command-reference/
*/
void setupESP8266()
{
lcdWiFiStatus(false);
if(DEBUG){
lcdBootStatus("E?");
}
esp8266Module.flush();
esp8266Module.println(F("AT+RST"));
delay(7000);
if (esp8266Module.find("OK"))
{
if(DEBUG){
PASSED('E');
}
esp8266Module.flush();
changeStationMode(); // put ESP8266 in Station Mode
delay(5000);
esp8266Module.flush();
connectToWiFi(); // connect to WiFi network
}
else
{
if(DEBUG){
FAIL('E');
}
}
}
/*
* Sets ESP8266 to station mode
*/
bool changeStationMode()
{
esp8266Module.println(F("AT+CWMODE=1")); // 1=Station, 2=AP, 3=AP+Station
if (esp8266Module.find("OK"))
{
if(DEBUG){
PASSED('S'); // switched to Station Mode
}
return true;
}
else if(esp8266Module.find("NO CHANGE")){
if(DEBUG){
PASSED('S');
}
return true;
}
else
{
if(DEBUG){
FAIL('S'); // error switching to Station Mode
}
return false;
}
}
/*
* Connects ESP8266 to wifi access point
*/
bool connectToWiFi()
{
bool connected;
if(DEBUG){
lcdBootStatus("W?");
}
String cmd = F("AT+CWJAP=\"");
cmd += network;
cmd += F("\",\"");
cmd += password;
cmd += F("\"");
esp8266Module.println(cmd);
delay(15000);
if (esp8266Module.find("OK"))
{
if(DEBUG){
PASSED('W'); // successful connection to WiFi AP
}
connected = true;
}
else
{
if(DEBUG){
FAIL('W'); // Could not connect to Access Point
}
connected = false;
}
lcdWiFiStatus(connected);
}
/*
* Send data over WiFi to the Internet.
* Display the Transmit (arrow up) icon during sent.
* Blink the Receive icon (arrow down) while waiting for response.
* NOTE: THIS IS NOT WORKING PROPERLY - NO RESPONSES FROM ESP8266
*/
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
lcdSerialStatus(CHR_TX); // LCD indicator for Tx
esp8266Module.print(command); // send the request to the esp8266
long int time = millis();
const int BLINK_RELOAD = 100;
int blink = BLINK_RELOAD;
bool blinkOn = true;
lcdSerialStatus(CHR_RX);
while ( (time + timeout) > millis()) {
while (esp8266Module.available()) {
// output to the serial window
char c = esp8266Module.read(); // read the next character.
response += c;
}
if (--blink == 0)
{
blink = BLINK_RELOAD;
if (blinkOn) {
lcdSerialStatus(CHR_NONE);
} else {
lcdSerialStatus(CHR_RX);
}
blinkOn = !blinkOn;
}
}
lcdSerialStatus(CHR_NONE);
return response;
}
// ------------------- /ESP8266 -----------------
// ------------------- GENERAL -----------------
bool openTcpConnection(String host, int port)
{
String openCmd = "AT+CIPSTART=\"TCP\",\"" + host + "\"," + port;
esp8266Module.println(openCmd);
delay(5000); // Wait a little for the ESP to respond
// response should have been CONNECT
bool error = esp8266Module.find("Error");
return !error;
}
// ------------------- /GENERAL -----------------
// ------------------- THINGSPEAK -----------------
/*
* Open connection to Cloud over WiFi to ThingSpeak API
*/
bool openCloudConnection()
{
String openCmd = "AT+CIPSTART=\"TCP\",\"" + cfgIoT.Host
+ "\"," + cfgIoT.HttpPort;
esp8266Module.println(openCmd);
delay(5000); // Wait a little for the ESP to respond
// response should have been CONNECT
bool error = esp8266Module.find("Error");
return !error;
}
/*
* Close connection to Cloud service over WiFi
* http://www.pridopia.co.uk/pi-doc/ESP8266ATCommandsSet.pdf
*/
void closeCloudConnection()
{ // for multiple connections AT+CIPCLOSE=<id>
esp8266Module.println("AT+CIPCLOSE");
delay(50); // response CLOSED\r\nOK
lcdCloudStatus(false);
}
int thingSpeakApiUpdateGet(int temperature)
{
int retCode = 0;
//openTcpConnection("46.4.105.116", 80);
//sendRequest("GET /a3355acb-5c03-49b8-92a9-8b4610a12a54 HTTP/1.1","webhook.site");
// send request
lcdSerialStatus(CHR_TX);
String req;
req = "GET /update?api_key=" + MY_CHANNEL_WRITE_API_KEY
+ "&field1=" + String(temperature, DEC)
+ " HTTP/1.1\r\nHost: " + "api.thingspeak.com" + "\r\n\r\n";
String cipSend = "AT+CIPSEND=";
//cipSend += 4; // connection ID if CMUX=1 we aren't using that
//cipSend += ", ";
cipSend += String(req.length());
cipSend += "\r\n";
String rsp = sendData(cipSend, 1000, DEBUG); // should receive > but it never does!
lcdPrintAt(0,0,rsp);
rsp = sendData(req, 10000, DEBUG);
lcdPrintAt(0,0,rsp);
lcdSerialStatus(CHR_NONE);
return retCode;
}