Comments (49)
Hi,
you can connect serial monitor to the ESP, the ESP SDK writes sometimes a piece of information there.
from wifispi.
Hi! I have finally been able to hook my ESP up to a serial to see what is happening.
This is the debug messages that is responded to me:
SPI SLAVE ver. 0.1.1
Fatal exception 3(LoadStoreErrorCause):
epc1=0x402060ce, epc2=0x00000000, epc3=0x00000000, excvaddr=0x40238512, depc=0x00000000
Exception (3):
epc1=0x402060ce epc2=0x00000000 epc3=0x00000000 excvaddr=0x40238512 depc=0x00000000
ctx: cont
sp: 3fff0070 end: 3fff02c0 offset: 01a0
>>>stack>>>
3fff0210: 312e3020 000a312e feefeffe 3ffef290
3fff0220: 0000002f 3ffeef48 3ffeef58 3ffef290
3fff0230: 3fffdad0 00000000 3ffef264 4020576d
3fff0240: 40238512 00000000 00000029 402031b2
3fff0250: 0001c200 0000001c 3ffef264 40205891
3fff0260: 3fffdad0 00000000 3ffeef24 402026f1
3fff0270: 402010fc 3ffeef28 00000004 4020365d
3fff0280: 00000000 00000000 00000000 00000000
3fff0290: 00000000 00000000 00000000 00000000
3fff02a0: 3fffdad0 00000000 3ffef288 40205c70
3fff02b0: feefeffe feefeffe 3ffef2a0 40100710
<<<stack<<<
ets Jan 8 2013,rst cause:1, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v4ceabea9
~ld
How can I figure out what is causing this? :-)
Thank you,
Morten Lund
from wifispi.
Hi,
use exception decoder (https://github.com/me-no-dev/EspExceptionDecoder). At least it will tell you where exactly the exception occured.
Post the result here, please.
J.
from wifispi.
This is the result from the decode :-)
Decoding 9 results
0x4020576d: Print::write(char const*) at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/Print.cpp line 107
0x40238512: sleep_reset_analog_rtcreg_8266 at ?? line ?
0x402031b2: WiFiSpiEspCommandProcessor::cmdGetStateTcp() at /var/folders/2n/sr5cmbvj7w90sb_dw0trzg100000gn/T/arduino_build_559429/sketch/WiFiSPICmdServer.cpp line 110
0x40205891: Print::print(char const*) at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/Print.cpp line 107
: (inlined by) Print::println(char const*) at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/Print.cpp line 172
0x402026f1: WiFiSpiEspCommandProcessor::processCommand(unsigned char*) at /var/folders/2n/sr5cmbvj7w90sb_dw0trzg100000gn/T/arduino_build_559429/sketch/WiFiSPICmd.cpp line 173
0x402010fc: hspi_slave_begin at /var/folders/2n/sr5cmbvj7w90sb_dw0trzg100000gn/T/arduino_build_559429/sketch/hspi_slave.c line 99
0x4020365d: loop at /Users/mortenlund/Dropbox/Development/ESP8266/ESPSpi/WiFiSpiESP-master/WiFiSPIESP/WiFiSPIESP.ino line 122
0x40205c70: loop_wrapper at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/core_esp8266_main.cpp line 57
0x40100710: cont_norm at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/cont.S line 109
This seems to be cause by this code:
WiFiSpiClient client = TCPserver.available();
if ( client )
{
}
from wifispi.
When reducing my sketch (SPI Master) to the bare minimum the debug sometimes yields this:
Decoding 10 results
0x40224bc8: ppRecycleRxPkt at ?? line ?
0x402243d1: pp_enable_noise_timer at ?? line ?
0x402244b4: pp_noise_test at ?? line ?
0x40224f17: pp_tx_idle_timeout at ?? line ?
0x4022bcb5: ets_timer_handler_isr at ?? line ?
0x4022bcfa: ets_timer_handler_isr at ?? line ?
0x40205bdf: loop_task at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/core_esp8266_main.cpp line 57
from wifispi.
I am using the latest version 2.4.0 of ESP8266 Arduino using Board manager in Arduino if that is relevant.
from wifispi.
I must say I am confused. I hoped the trace would help us.
from wifispi.
I need to reproduce the error. I assume you loaded the sketch to the ESP8266 exactly as it was.
Next, you have an app in STM32, right? It would be great if you sent me the bare minimum app (sketch) that caused the crash and all relevant info. I have here STM32F103C8 boards and one F407 so if we are lucky I'll reproduce the issue here.
from wifispi.
Yes, this is the sketch i am using to test with. I had originally made everything ready in my complete application, but due to this errors I tried your example-sketch and just made some minor changes to it to test my functionality.
I am using a generic STM32, STM32F103C8, and the ESP is an ESP-201.
I am using unmodified WifiSPI sketch and unmodified ESP8266-Arduino 2.4.0.
The ESP is also powered with its own voltage regulator, not from the STM32 so it should have stable power.
Morten
/*
Web client
This sketch connects to a website (http://www.google.com)
using a WiFi ESP8266 module.
This example is written for a network using WPA encryption.
Circuit:
1. On ESP8266 must be running (flashed) WiFiSPIESP application.
2. Connect the Arduino to the following pins on the esp8266:
ESP8266 |
GPIO NodeMCU Name | Uno
===================================
15 D8 SS | D10
13 D7 MOSI | D11
12 D6 MISO | D12
14 D5 SCK | D13
Note: If the ESP is booting at the moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected)
the ESP8266 WILL FAIL to boot!
original sketch for WiFi library created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
modified for WiFiSpi library 14 Mar 2017
by Jiri Bilek
*/
#include <WiFiSpi.h>
char ssid[] = "MogH"; // your network SSID (name)
char pass[] = "10042057"; // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
char server[] = "www.google.com"; // name address for Google (using DNS)
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiSpiServer TCPserver(80);
void setup() {
pinMode(PB12, OUTPUT);
digitalWrite(PB12, HIGH);
//Initialize serial and wait for port to open:
Serial1.begin(115200);
while (!Serial1) {
; // wait for serial port to connect. Needed for native USB port only
}
// Initialize the WifiSpi library
WiFiSpi.init();
digitalWrite(PB12, LOW);
delay(250);
digitalWrite(PB12, HIGH);
delay(5000);
// check for the presence of the shield:
if (WiFiSpi.status() == WL_NO_SHIELD) {
Serial1.println("WiFi shield not present");
// don't continue:
while (true);
}
String fv = WiFiSpi.firmwareVersion();
if (fv != "0.1.1") {
Serial1.println(fv);
Serial1.println("Please upgrade the firmware");
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial1.print("Attempting to connect to SSID: ");
Serial1.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFiSpi.begin(ssid, pass);
Serial1.println(status);
Serial1.print("Done with begin");
// wait 10 seconds for connection:
delay(10000);
}
Serial1.println("Connected to wifi");
printWifiStatus();
Serial1.println("\nStarting connection to server...");
TCPserver.begin();
if ( TCPserver.status() )
{
Serial1.println("\nStarted server");
}
}
void loop() {
// if there are incoming bytes available
// from the server, read them and print them:
WiFiSpiClient client = TCPserver.available();
if ( client )
{
/*Serial1.println("Found client");
if ( client.connected() )
{
while ( client.available() ) {
char c = client.read();
Serial1.write(c);
}
}
const char* responseCode = "200";
const char* body = "Test";
char Header[100];
snprintf(Header, sizeof Header, PSTR("HTTP/1.1 %s OK\r\nContent-Type: text/plain\r\nConnection: close\r\nContent-Length: %i\r\n\r\n"), responseCode, (int)strlen(body));
char buffer[1024];
strncat(buffer, Header, strlen(Header));
strncat(buffer, body, strlen(body));
client.print(buffer);
client.stop();*/
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial1.print("SSID: ");
Serial1.println(WiFiSpi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFiSpi.localIP();
Serial1.print("IP Address: ");
Serial1.println(ip);
// print the received signal strength:
long rssi = WiFiSpi.RSSI();
Serial1.print("signal strength (RSSI):");
Serial1.print(rssi);
Serial1.println(" dBm");
}
from wifispi.
It is also wired so that the STM32 controls the CH_PD pin to reset the board. PB12 on my board.
from wifispi.
Thanks, I will try it soon on my "blue pill". I can test the ESP library only on ESP-12F but it should make no difference.
Jiri
Meanwhile, you could test the ESP side on freshly downloaded stuff from ESP8266-Arduino github project. I had an issue recently, although not related to our problems, and using the newest library solved it.
from wifispi.
Thank you, I will try that! Thought about it but my board manager said it was up to date! But I did not think about the git repo of course :-)
from wifispi.
My testing stops with the exception, too. I am using the newest ESP library now.
Probably, we are in bad project now as this should be an issue of the ESP library.
from wifispi.
Should I try a older version of the Arduino ESP lib? Its good to see that you have issues too as I was really looking forward to use your library as the ESP AT commands version is no good.
from wifispi.
Hi Morten,
it seems to me there is a bug in my ESP library that shows up when it receives invalid packet. I suspect SPI interface in STM32 to behave differently than in Atmel328P. Immediately after initializing SPI on STM32 I am getting tremendous load on SPI interface on ESP. The data received are obviously meaningless and the library crashes. I am working on it since noon (GMT+1 :) ).
from wifispi.
The problem was in another repo.
JiriBilek/WiFiSpiESP@19f3338
from wifispi.
Hi! That sounds promising! I hope you figure this out! Really looking forward to use your library! Tell me if there is anything i can do to help!
Morten
from wifispi.
For STM32F1 I had to slow down the SPI. The default frequency was too fast and I got communication errors. The speed 1000000 is ok.
The additional parameter for SPI speed setting added: fd38121
from wifispi.
@m0rt3nlund
I tested your sketch and it is running almost perfectly. When you create a http server, you start to poll the ESP8266 quite heavily and with the default speed of STM32's SPI some communication errors appeared. The communication protocol can handle it but I'd recommend to slow down the SPI speed. I added a parameter to init() function for setting max speed.
In your code I'd rather first reset the ESP and then setup the communication (although your code runs fine). And finally, in commented out server part of your code you should copy the first string to the buffer instead of concatenating it.
char buffer[1024];
**strncpy**(buffer, Header, strlen(Header));
strncat(buffer, body, strlen(body));
Also note that reading the data from the ESP byte-by-byte is rather slow as there is a couple of roundtrips on SPI bus needed. I am going to tune the protocol in future but there are serious limitations on the ESP side.
J.
from wifispi.
And thanks for testing on STM32 and finding a bug.
from wifispi.
i wrote spi code that runs at 30 and 60mhz spi bus between two cortexes, jiribilek, perhaps youll like the implementation i did, it uses circular buffer sending for slave responses to master, fire & forget, and callbacks at both master/slave for 2 way communication similar to uart behaviour
from wifispi.
@tonton81 , I think it is not a matter of discarding data but rather distorting. The protocol I use on top of SPI is master-slave (I know what you think about it :) ).
I have to find out, why the message sometimes comes corrupt. I have a funny chinese logic analyzer so I hope I'll see the problem. Nevertheless my wiring on breadboard is hideous, I am surprised that it can transfer 1MHz signal.
from wifispi.
Very nice work! Will test this first thing tomorrow! Thank you for your great effort!
from wifispi.
I used your sketch for testing and found another problem with the strings. The server part of the sketch should be
strcpy(buffer, Header);
strcat(buffer, body);
or you have to add +1 to strlen in order to copy the trailing '\0'. It's funny, yesterday it somehow worked :)
from wifispi.
Hi! I have finally been able to test this again! :)
But I keep getting an exception like this one:
0x402010fc: hspi_slave_begin at /var/folders/2n/sr5cmbvj7w90sb_dw0trzg100000gn/T/arduino_build_631951/sketch/hspi_slave.c line 99
0x40203501: loop at /Users/mortenlund/Dropbox/Development/ESP8266/ESPSpi/WifiSpiESP_0.1.2/WiFiSPIESP/WiFiSPIESP.ino line 135
0x40205a25: esp_schedule at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/core_esp8266_main.cpp line 57
0x40205a50: loop_wrapper at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/core_esp8266_main.cpp line 57
0x40100710: cont_norm at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/cont.S line 109
from wifispi.
I am using this as my init now: WiFiSpi.init(PA4,1000000);
from wifispi.
Also, this:
Exception (0):
epc1=0x402245a1 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: sys
sp: 3ffffdf0 end: 3fffffb0 offset: 01a0
>>>stack>>>
3fffff90: 402244a6 3fffdab0 00000000 402059bf
3fffffa0: 3ffe9608 40000f49 3fffdab0 40000f49
<<<stack<<<
ets Jan 8 2013,rst cause:1, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v4ceabea9
~ld
0x402244a6: ppPeocessRxPktHdr at ?? line ?
0x402059bf: loop_task at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/core_esp8266_main.cpp line 57
from wifispi.
Also, this:
3fff0178: 3ffef160 40100710 feefeffe 3ffef160
from wifispi.
This is with the development branch of WifiSpi.
from wifispi.
Hm.. This may have been a wiring/noise problem.. I have now forced the reset-pin HIGH and IO01 HIGH and the board is much more stable..
Wiring is now as following:
CHIP_EN - PB12 on STM
RESET - 3.3V on ESP board
IO01 - 3.3V on ESP board
IO02 - 3.3V on ESP board
Now I can request the webpage again and again with correct response..
However the response is very slow.
I have about 2.3 seconds "Time before First Byte" delay.
Is this due to the nature of reading byte-by-byte from the ESP as you described earlier?
Morten
from wifispi.
After running for a while I got this exception:
SPI SLAVE ver. 0.1.2
Exception (9):
epc1=0x40210521 epc2=0x00000000 epc3=0x00000000 excvaddr=0x32e0c112 depc=0x00000000
ctx: cont
sp: 3ffeff00 end: 3fff0180 offset: 01a0
>>>stack>>>
3fff00a0: ffffffff 3fffc6fc 00000001 3ffef148
3fff00b0: 00000000 3fffdad0 3ffef150 00000030
3fff00c0: 00000000 3fffdad0 3fff151c 40204db6
3fff00d0: 00000000 0000002e 3fff1c6c 3ffef150
3fff00e0: 0000002f 3ffeee08 3ffeee18 40204832
3fff00f0: 0000002f 3ffeee08 3ffeee18 40202c60
3fff0100: 3ffe8bb0 00000000 00001388 40202be2
3fff0110: 00000000 00000000 3ffeed00 3ffef150
3fff0120: 3fffdad0 00000000 3ffeede4 40202655
3fff0130: 402010fc 3ffeede8 00000004 402034f9
3fff0140: 012fe0df 00ee0001 00000000 00000000
3fff0150: 00000000 00000000 00000000 00000000
3fff0160: 3fffdad0 00000000 3ffef148 40205a50
3fff0170: feefeffe feefeffe 3ffef160 40100710
<<<stack<<<
ets Jan 8 2013,rst cause:1, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v4ceabea9
~ld
0x40204db6: WiFiServer::available(unsigned char*) at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/libraries/ESP8266WiFi/src/WiFiServer.cpp line 97
0x40204832: ClientContext::_write_some() at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/libraries/ESP8266WiFi/src/include/ClientContext.h line 421
0x40202c60: WiFiSpiEspCommandProcessor::cmdGetClientStateTcp() at /var/folders/2n/sr5cmbvj7w90sb_dw0trzg100000gn/T/arduino_build_483666/sketch/WiFiSPICmdClient.cpp line 96
0x40202be2: WiFiSpiEspCommandProcessor::cmdStopClientTcp() at /var/folders/2n/sr5cmbvj7w90sb_dw0trzg100000gn/T/arduino_build_483666/sketch/WiFiSPICmdClient.cpp line 307
0x40202655: WiFiSpiEspCommandProcessor::processCommand(unsigned char*) at /var/folders/2n/sr5cmbvj7w90sb_dw0trzg100000gn/T/arduino_build_483666/sketch/WiFiSPICmd.cpp line 123
0x402010fc: hspi_slave_begin at /var/folders/2n/sr5cmbvj7w90sb_dw0trzg100000gn/T/arduino_build_483666/sketch/hspi_slave.c line 99
0x402034f9: loop at /Users/mortenlund/Dropbox/Development/ESP8266/ESPSpi/WifiSpiESP_0.1.2/WiFiSPIESP/WiFiSPIESP.ino line 134
0x40205a50: loop_wrapper at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/core_esp8266_main.cpp line 57
0x40100710: cont_norm at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/cont.S line 109
from wifispi.
Hi, thanks for testing.
Firstly, make sure you have stable power on ESP, it can draw a lot of current. I think the 3v3 from STM board is not enough. I am always powering the breadboard with external power. Don't forget to connect the ground then. Sorry if it is obvious to you.
Secondly, when giving a stack trace, please give it full. The reason of the exception is quite important to me.
I load your testing sketch and see what happens.
from wifispi.
I have the ESP powered by its own voltage regulator connected to USB power (Same USB as the STM) but can try to power it totally seperatly.
I have edited the exceptions above with the full stack trace.
from wifispi.
SPI SLAVE ver. 0.1.2
Invalid message header - message rejected.
Invalid message header - message rejected.
Exception (9):
epc1=0x4022ba52 epc2=0x00000000 epc3=0x00000000 excvaddr=0x61020365 depc=0x00000000
ctx: sys
sp: 3ffffdd0 end: 3fffffb0 offset: 01a0
>>>stack>>>
3fffff70: 3ffeb710 3fffdcc0 3ffe9600 3ffe9600
3fffff80: 4022bada 3fffdab0 00000000 3fffdcb0
3fffff90: 3ffee7d0 3fffdad0 3ffef150 402059bf
3fffffa0: 40000f49 40000f49 3fffdab0 40000f49
<<<stack<<<
ets Jan 8 2013,rst cause:1, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v4ceabea9
~ld
0x4022bada: ets_timer_handler_isr at ?? line ?
0x402059bf: loop_task at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/core_esp8266_main.cpp line 57
from wifispi.
Thanks,
and please decode the exceptions. I can see the exception code now (Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address) but my Arduino IDE apparently doesn't have the same configuration as yours, so I am getting unusable stack dump.
from wifispi.
I have decoded the stack traces now, hope they help! :)
from wifispi.
This seems to be the most recurring one:
SPI SLAVE ver. 0.1.2
Exception (0):
epc1=0x402245c0 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: sys
sp: 3ffffdf0 end: 3fffffb0 offset: 01a0
>>>stack>>>
3fffff90: 00000000 3fffdad0 3ffef150 402059bf
3fffffa0: 3ffe9610 40000f49 3fffdab0 40000f49
<<<stack<<<
ets Jan 8 2013,rst cause:1, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v4ceabea9
~ld
Decoding 3 results
0x402059bf: loop_task at /Users/mortenlund/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.0/cores/esp8266/core_esp8266_main.cpp line 57
from wifispi.
Meanwhile, I have good news for you. I hope to be seeing light at the end of the tunnel, at least.
I played with delays in esp_proxy.h file and now I can send 100 requests at full SPI speed, got 100 responses and no trap on ESP8266 and no rejected messages. Also the response times are stable.
Will test further.
I slightly modified your sketch:
#include <WiFiSpi.h>
char ssid[] = "*"; // your network SSID (name)
char pass[] = "*"; // your network password (use for WPA)
int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
char server[] = "www.google.com"; // name address for Google (using DNS)
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiSpiServer TCPserver(80);
void setup() {
pinMode(PB12, OUTPUT);
digitalWrite(PB12, HIGH);
//Initialize serial and wait for port to open:
Serial.begin(115200);
while (!Serial.available()) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Reset ESP8266");
// Initialize the WifiSpi library
// WiFiSpi.init(SS, 1000000);
digitalWrite(PB12, LOW);
delay(100);
digitalWrite(PB12, HIGH);
delay(200);
// WiFiSpi.init(SS, 1000000);
WiFiSpi.init();
// check for the presence of the shield:
if (WiFiSpi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
WiFiSpi.status();
// don't continue:
while (true);
}
String fv = WiFiSpi.firmwareVersion();
if (fv != "0.1.3") {
Serial.println(fv);
Serial.println("Please upgrade the firmware");
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFiSpi.begin(ssid, pass);
Serial.println(status);
Serial.print("Done with begin");
// wait 1 second for connection:
delay(1000);
}
Serial.println("Connected to wifi");
printWifiStatus();
Serial.println("\nStarting connection to server...");
TCPserver.begin();
if ( TCPserver.status() )
{
Serial.println("\nStarted server");
}
}
void loop() {
static uint16_t counter = 0;
// if there are incoming bytes available
// from the server, read them and print them:
WiFiSpiClient client = TCPserver.available();
if ( client )
{
Serial.println("Found client");
if ( client.connected() )
{
while (! client.available() ) {}
/* while ( client.available() ) {
char c = client.read();
Serial.write(c);
}*/
char input[400];
uint16_t inputLen;
while ((inputLen = client.available()) > 0) {
if (inputLen > sizeof(input) - 1)
inputLen = sizeof(input) - 1;
client.read(reinterpret_cast<uint8_t*>(input), inputLen);
input[inputLen] = 0;
Serial.print(input);
}
}
const uint16_t responseCode = 200;
char buffer[1024];
char header[100];
char body[100];
snprintf(body, sizeof body, PSTR("Test %d\r\n"), ++counter);
snprintf(header, sizeof header, PSTR("HTTP/1.1 %d OK\r\nContent-Type: text/plain\r\nConnection: close\r\nContent-Length: %i\r\n\r\n"), responseCode, (int)strlen(body));
strcpy(buffer, header);
strcat(buffer, body);
client.print(buffer);
client.stop();
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFiSpi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFiSpi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFiSpi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
from wifispi.
Looking forward to test! :) Great work!
from wifispi.
I assume the code above should be used with your next uncomitted version 0.1.3? :)
from wifispi.
Yes, check out the development branch for both projects.
My recent changes are in espspi_proxy.h only. You can try it:
... Edit 10.3.18, 21:49 GMT+1: source file deleted, see next post for a updated one ...
This runs fine. But it needs more testing.
I am testing on STM32F103C8.
from wifispi.
Posting espspi_proxy.h that passed my stress test (2000 http requests).
/*
espspi_proxy.h - Library for Arduino SPI connection with ESP8266
Copyright (c) 2017 Jiri Bilek. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-------------
WiFi SPI Safe Master for connecting with ESP8266
On ESP8266 must be flashed WiFiSPIESP application
Connect the SPI Master device to the following pins on the esp8266:
ESP8266 |
GPIO NodeMCU Name | Uno
===================================
15 D8 SS | D10**
13 D7 MOSI | D11
12 D6 MISO | D12
14 D5 SCK | D13
**) User changeable
Based on Hristo Gochkov's SPISlave library.
*/
#ifndef _ESPSPI_PROXY_H_INCLUDED
#define _ESPSPI_PROXY_H_INCLUDED
#include <SPI.h>
#include "debug.h"
// The command codes are fixed by ESP8266 hardware
#define CMD_WRITESTATUS 0x01
#define CMD_WRITEDATA 0x02
#define CMD_READDATA 0x03
#define CMD_READSTATUS 0x04
// Message indicators
#define MESSAGE_FINISHED 0xDF
#define MESSAGE_CONTINUES 0xDC
// SPI Status
enum {
SPISLAVE_RX_BUSY,
SPISLAVE_RX_READY
};
enum {
SPISLAVE_TX_NODATA,
SPISLAVE_TX_READY,
SPISLAVE_TX_PREPARING_DATA
};
// How long we will wait for slave to be ready
#define SLAVE_RX_READY_TIMEOUT 3000UL
#define SLAVE_TX_READY_TIMEOUT 3000UL
// How long will be SS held high when starting transmission
#define SS_PULSE_DELAY_MICROSECONDS 50
class EspSpiProxy
{
private:
SPIClass *spi_obj;
uint8_t _ss_pin;
uint8_t buffer[32];
uint8_t buflen;
uint8_t bufpos;
void _pulseSS(boolean start)
{
if (_ss_pin >= 0)
{
/* digitalWrite(_ss_pin, HIGH);
delayMicroseconds(SS_PULSE_DELAY_MICROSECONDS);
digitalWrite(_ss_pin, LOW);
delayMicroseconds(SS_PULSE_DELAY_MICROSECONDS); // Added as an attempt to get rid of false messages
*/
if (start) { // tested ok: 5, 15 / 5
digitalWrite(_ss_pin, HIGH);
delayMicroseconds(1);
digitalWrite(_ss_pin, LOW);
delayMicroseconds(15); // 10us is low (some errors), 20 us is safe (no errors)
}
else {
digitalWrite(_ss_pin, HIGH);
delayMicroseconds(1);
digitalWrite(_ss_pin, LOW);
}
}
}
public:
EspSpiProxy()
{
_ss_pin = -1;
buflen = 0;
}
void begin(uint8_t pin, SPIClass *in_spi)
{
spi_obj = in_spi;
_ss_pin = pin;
pinMode(_ss_pin, OUTPUT);
digitalWrite(_ss_pin, LOW);
}
uint32_t readStatus()
{
_pulseSS(true);
spi_obj->transfer(CMD_READSTATUS);
uint32_t status = (spi_obj->transfer(0) | ((uint32_t)(spi_obj->transfer(0)) << 8) | ((uint32_t)(spi_obj->transfer(0)) << 16) | ((uint32_t)(spi_obj->transfer(0)) << 24));
_pulseSS(false);
return status;
}
void writeStatus(uint32_t status)
{
_pulseSS(true);
spi_obj->transfer(CMD_WRITESTATUS);
spi_obj->transfer(status & 0xFF);
spi_obj->transfer((status >> 8) & 0xFF);
spi_obj->transfer((status >> 16) & 0xFF);
spi_obj->transfer((status >> 24) & 0xFF);
_pulseSS(false);
}
void readData(uint8_t* buf)
{
_pulseSS(true);
spi_obj->transfer(CMD_READDATA);
spi_obj->transfer(0x00);
for(uint8_t i=0; i<32; i++) {
buf[i] = spi_obj->transfer(0); // the value is not important
}
_pulseSS(false);
}
void writeData(uint8_t * data, size_t len)
{
uint8_t i=0;
_pulseSS(true);
spi_obj->transfer(CMD_WRITEDATA);
spi_obj->transfer(0x00);
while(len-- && i < 32) {
spi_obj->transfer(data[i++]);
}
while(i++ < 32) {
spi_obj->transfer(0);
}
_pulseSS(false);
}
void flush(uint8_t indicator)
{
// Is buffer empty?
if (buflen == 0)
return;
// Message state indicator
buffer[0] = indicator;
// Wait for slave ready
if (waitForSlaveRxReady() == SPISLAVE_RX_READY) // TODO: move the waiting loop to writeByte
{
// Send the buffer
writeData(buffer, buflen+1);
}
buflen = 0;
}
void writeByte(uint8_t b)
{
bufpos = 0; // discard input data in the buffer
if (buflen >= 31)
flush(MESSAGE_CONTINUES);
buffer[++buflen] = b;
}
uint8_t readByte()
{
buflen = 0; // discard output data in the buffer
if (bufpos >= 32) // the buffer segment was read
{
if (buffer[0] != MESSAGE_CONTINUES)
return 0;
bufpos = 0; // read next chunk
// Wait for the slave
waitForSlaveTxReady();
}
if (bufpos == 0) // buffer empty
{
uint32_t endTime = millis() + 1000;
do {
readData(buffer);
} while (buffer[0] != MESSAGE_FINISHED && buffer[0] != MESSAGE_CONTINUES && millis() < endTime);
if (buffer[0] != MESSAGE_FINISHED && buffer[0] != MESSAGE_CONTINUES)
return 0;
bufpos = 1;
}
return buffer[bufpos++];
}
/*
Waits for slave receiver ready status.
Return: status (SPISLAVE_RX_BUSY, SPISPLAVE_RX_READY or SPISLAVE_RX_PREPARING_DATA)
*/
int8_t waitForSlaveRxReady()
{
uint32_t endTime = (millis() & 0x0fffffff) + SLAVE_RX_READY_TIMEOUT;
uint32_t status = SPISLAVE_RX_BUSY;
do
{
status = readStatus();
if (((status >> 28) == SPISLAVE_RX_READY))
return (status >> 28); // status
yield();
} while ((millis() & 0x0fffffff) < endTime);
WARN("Slave rx is not ready");
WARN2("Returning: ", status >> 28);
return (status >> 28); // timeout
}
/*
Waits for slave transmitter ready status.
Return: status (SPISLAVE_TX_NODATA, SPISPLAVE_TX_READY
*/
int8_t waitForSlaveTxReady()
{
uint32_t endTime = (millis() & 0x0fffffff) + SLAVE_RX_READY_TIMEOUT;
uint32_t status = SPISLAVE_TX_NODATA;
do
{
status = readStatus();
if ((((status >> 24) & 0x0f) == SPISLAVE_TX_READY))
return ((status >> 24) & 0x0f); // status
yield();
} while ((millis() & 0x0fffffff) < endTime);
WARN("Slave tx is not ready");
WARN2("Returning: ", (status >> 24) & 0x0f);
return ((status >> 24) & 0x0f); // timeout
}
};
extern EspSpiProxy espSpiProxy;
#endif
from wifispi.
I have tested this now and it is much more stable.
I am seeing something strange though..
I am using this sketch now to time each step of the communication with the client since it takes from 100ms to 10seconds to get a response.
The strange thing is that it uses avg ~180ms from the client connects to the data is sent, but can use up to 10 seconds stopping the connection to the client (client.stop)
Other times I see it can take 2-3ms, trying to figure out a pattern! :)
0 Found client
2 Wait for data
3 Data is now avaliable
GET / HTTP/1.1
Host: 192.168.1.37
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: nb-NO,nb;q=0.9,no;q=0.8,nn;q=0.7,en-US;q=0.6,en;q=0.5
49 Done reading data
49 Return data
180 Done sending data
5672 Stopped client
Sketch:
/*
Web client
This sketch connects to a website (http://www.google.com)
using a WiFi ESP8266 module.
This example is written for a network using WPA encryption.
Circuit:
1. On ESP8266 must be running (flashed) WiFiSPIESP application.
2. Connect the Arduino to the following pins on the esp8266:
ESP8266 |
GPIO NodeMCU Name | Uno
===================================
15 D8 SS | D10
13 D7 MOSI | D11
12 D6 MISO | D12
14 D5 SCK | D13
Note: If the ESP is booting at the moment when the SPI Master (i.e. Arduino) has the Select line HIGH (deselected)
the ESP8266 WILL FAIL to boot!
original sketch for WiFi library created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
modified for WiFiSpi library 14 Mar 2017
by Jiri Bilek
*/
#include <WiFiSpi.h>
#include <aWOT.h>
char ssid[] = "MogH"; // your network SSID (name)
char pass[] = "10042057"; // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
char server[] = "www.google.com"; // name address for Google (using DNS)
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
WiFiSpiServer TCPserver(80);
void setup() {
pinMode(PA4, OUTPUT);
digitalWrite(PA4, LOW);
pinMode(PB12, OUTPUT);
digitalWrite(PB12, HIGH);
//Initialize serial and wait for port to open:
Serial1.begin(115200);
Serial1.println("Reset ESP8266");
// Initialize the WifiSpi library
// WiFiSpi.init(SS, 1000000);
digitalWrite(PB12, LOW);
delay(100);
digitalWrite(PB12, HIGH);
delay(200);
// WiFiSpi.init(SS, 1000000);
WiFiSpi.init(PA4, 1000000);
// check for the presence of the shield:
if (WiFiSpi.status() == WL_NO_SHIELD) {
Serial1.println("WiFi shield not present");
WiFiSpi.status();
// don't continue:
while (true);
}
String fv = WiFiSpi.firmwareVersion();
if (fv != "0.1.2") {
Serial1.println(fv);
Serial1.println("Please upgrade the firmware");
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
Serial1.print("Attempting to connect to SSID: ");
Serial1.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFiSpi.begin(ssid, pass);
Serial1.println(status);
Serial1.print("Done with begin");
// wait 1 second for connection:
delay(1000);
}
Serial1.println("Connected to wifi");
printWifiStatus();
Serial1.println("\nStarting connection to server...");
TCPserver.begin();
if ( TCPserver.status() )
{
Serial1.println("\nStarted server");
}
}
void loop() {
static uint16_t counter = 0;
// if there are incoming bytes available
// from the server, read them and print them:
WiFiSpiClient client = TCPserver.available();
if ( client )
{
long startT = millis();
Serial1.print(millis()-startT);
Serial1.println(" Found client");
if ( client.connected() )
{
Serial1.print(millis()-startT);
Serial1.println(" Wait for data");
while (! client.available() ) {
if ( millis()-startT > 2000 )
{
Serial1.print(millis()-startT);
Serial1.println(" Timeout wating for data");
client.stop();
return;
}
}
Serial1.print(millis()-startT);
Serial1.println(" Data is now avaliable");
/* while ( client.available() ) {
char c = client.read();
Serial1.write(c);
}*/
char input[400];
uint16_t inputLen;
while ((inputLen = client.available()) > 0) {
if (inputLen > sizeof(input) - 1)
inputLen = sizeof(input) - 1;
client.read(reinterpret_cast<uint8_t*>(input), inputLen);
input[inputLen] = 0;
Serial1.print(input);
}
}
Serial1.print(millis()-startT);
Serial1.println(" Done reading data");
const uint16_t responseCode = 200;
char buffer[1024];
char header[100];
char body[100];
snprintf(body, sizeof body, PSTR("Test %d\r\n"), ++counter);
snprintf(header, sizeof header, PSTR("HTTP/1.1 %d OK\r\nContent-Type: text/plain\r\nConnection: close\r\nContent-Length: %i\r\n\r\n"), responseCode, (int)strlen(body));
strcpy(buffer, header);
strcat(buffer, body);
Serial1.print(millis()-startT);
Serial1.println(" Return data");
client.print(buffer);
Serial1.print(millis()-startT);
Serial1.println(" Done sending data");
client.stop();
Serial1.print(millis()-startT);
Serial1.println(" Stopped client");
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial1.print("SSID: ");
Serial1.println(WiFiSpi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFiSpi.localIP();
Serial1.print("IP Address: ");
Serial1.println(ip);
// print the received signal strength:
long rssi = WiFiSpi.RSSI();
Serial1.print("signal strength (RSSI):");
Serial1.print(rssi);
Serial1.println(" dBm");
}
from wifispi.
I also had to add a couple of lines at the start to keep the SS pin low during the beginning as my ESP was not behaving without it.. :-)
from wifispi.
I removed it during testing, in the post it is back.
Edit: sorry, bad understanding. GPIO15 should have resistor to GND and uninitialized port should be in high impedance state. But it's good practice to set the pin explicitly to low state.
from wifispi.
I removed the "client.stop()" line from the code and now I have response-time < 200ms.
I thought I needed the stop command to release the sockets to free up the connection pool which I thought was limited to 4-5 connections?
Without the line it works very well! :)
from wifispi.
Been working great so far! :) Only issue is the delays between client request and getting a response, but this may be due to ESP-Arduino library maby? :) And maybe due to the "One-byte-at-a-time" transfer approach? :)
from wifispi.
Refer #9 (comment)
from wifispi.
Implemented new more robust protocol (48ea9f3). If you are interested, please try the new version. If the problems still persist, please open a new issue.
from wifispi.
Related Issues (20)
- Using library with Arduino Zero clone. HOT 2
- Example wifiManager HOT 1
- Problem with 3 second delay when calling WiFiSpiServer::avaliable() HOT 28
- Allow more than one connection in WiFiSPIServer HOT 3
- WiFi module not present HOT 23
- Protocol version mismatch. Please upgrade the firmware HOT 2
- Possible to run this on Arduino Due? HOT 10
- Add .remoteIP() function to WiFiSpiClient HOT 1
- How to manage maximum socket connections? HOT 16
- Compiler warning when "delete"ing a client instance HOT 31
- ESP8266: change AxTLS to BearSSL HOT 1
- Deprecated boolean type HOT 1
- Problems using ArduinoMDNS with WiFiSpi HOT 13
- Possible to set MAC address of ESP? HOT 1
- Reason for limitation of 4 sockets? HOT 1
- Protocol version mismatch. Please upgrade the firmware HOT 8
- Connect fail using BearSSL branch HOT 26
- Version mismatch HOT 2
- WiFiSpi.config(...) problems with number of parameters HOT 6
- Unstable HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wifispi.