Soft wdt reset on ESP8266 when using Speed Sensor - mqtt

I'm on my personal project to create a esp8266 module that can read several sensor from a vehicle and it can sends data over mqtt. so I have written the code where I try to reading the speed sensor its getting wdt reset and the esp8266 resetting again
so heres my code
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
lcd.init();
lcd.backlight();
pinMode(speedSensor,INPUT_PULLUP);
// attempt to connect to WiFi network:
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
lcd.setCursor(0,0);
lcd.print("Connecting to");
lcd.setCursor(0,1);
lcd.print("the network");
Serial.print(".");
delay(5000);
}
lcd.clear();
Serial.println("You're connected to the network");
Serial.println();
lcd.setCursor(0,0);
lcd.print("Connected to");
lcd.setCursor(0,1);
lcd.print("the network");
delay(2000);
lcd.clear();
// attempt to connect to the MQTT broker:
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You're connected to the MQTT broker!");
Serial.println();
// subscribe to the topic and set callback function
mqttClient.onMessage(SwitchMotor);
mqttClient.subscribe(topicSwitchMotor);
lcd.setCursor(0,0);
lcd.print("Connected to");
lcd.setCursor(0,1);
lcd.print("the MQTT broker");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Fuel :");
lcd.setCursor(0,1);
lcd.print(" RPM :");
SPI.begin();
rfid.PCD_Init();
Serial.println("I am waiting for card...");
pinMode(pinRelay, OUTPUT);
digitalWrite(pinRelay, HIGH);
}
void loop() {
mqttClient.poll(); // check for incoming messages
FuelSensor(); // Fuel Sensor
SpeedMotor(); // Speed Sensor
StartMotor(); // Start Motor with RFID
}
void SpeedMotor(){
start_time=millis();
end_time=start_time+1000;
while(millis()<end_time){
yield();
if(digitalRead(speedSensor)){
steps=steps+1;
while(digitalRead(speedSensor));
}
}
// calculate the speed
temp=steps-steps_old;
steps_old=steps;
rps=(temp/20);
rpm=(rps*60);
lcd.setCursor(9,1);
lcd.print(rpm);
lcd.print(" ");
// publish the message
mqttClient.beginMessage(topicSpeedRpm);
mqttClient.print(rpm);
mqttClient.endMessage();
mqttClient.beginMessage(topicSpeedRps);
mqttClient.print(rps);
mqttClient.endMessage();
}
and this is the output from serial monitor
Attempting to connect to WPA SSID: cieciecie
...You're connected to the network
Attempting to connect to the MQTT broker: xx.xxx.xxx.xx
You're connected to the MQTT broker!
I am waiting for card...
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
Soft WDT reset
>>>stack>>>
ctx: cont
sp: 3ffffde0 end: 3fffffc0 offset: 01a0
3fffff80: 3fffdad0 3ffee7bc 3ffee7c0 40201143
3fffff90: 3fffdad0 00000000 3ffeeaa8 402016e9
3fffffa0: 3fffdad0 00000000 3ffeeaa8 40205d5c
3fffffb0: feefeffe feefeffe 3ffe8600 40100e61
<<<stack<<<
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
⸮⸮Attempting to connect to WPA SSID: cieciecie
...You're connected to the network
Attempting to connect to the MQTT broker: xx.xxx.xxx.xx
You're connected to the MQTT broker!
I am waiting for card...
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
Soft WDT reset
it'll soft wdt reset all over again and again
I'd already try Stack ESP execption decoder and it given this results
ESP Exception decoder results
at the results its mentioning line 152 at speedMotor() function
void SpeedMotor(){
start_time=millis();
end_time=start_time+1000;
while(millis()<end_time){
yield(); // already use yield(); on while() loop
if(digitalRead(speedSensor)){ // line 152
steps=steps+1;
while(digitalRead(speedSensor));
}
}
// calculate the speed
temp=steps-steps_old;
steps_old=steps;
rps=(temp/20);
rpm=(rps*60);
lcd.setCursor(9,1);
lcd.print(rpm);
lcd.print(" ");
// publish the message
mqttClient.beginMessage(topicSpeedRpm);
mqttClient.print(rpm);
mqttClient.endMessage();
mqttClient.beginMessage(topicSpeedRps);
mqttClient.print(rps);
mqttClient.endMessage();
}
and i already try too from arduino forum https://forum.arduino.cc/t/solved-esp8266-millis-crash/636543
it says try using yield(); in the while() loop but its still given the soft wdt rest
i would like to have clear answer how to use the yield(); function properly so theres no more soft wdt resetting again

As per the comments the issue was in this section of code:
while(millis()<end_time){
yield(); // already use yield(); on while() loop
if(digitalRead(speedSensor)){ // line 152
steps=steps+1;
while(digitalRead(speedSensor));
}
}
The problem is that if digitalRead(speedSensor) returns true then a loop runs until digitalRead(speedSensor) returns false; this may run long enough to trigger the watchdog.
while(digitalRead(speedSensor));
One way of fixing this is to yield within the loop i.e.:
while(digitalRead(speedSensor)) {
yield();
}

Related

lwIP mqtt connection error on stm32f4 discovery

I am trying to use lwIP for a client, which sends data to mosquitto broker on stm32f407 discovery.
Mqtt application is implemented at lwIP. I just use them like that at main after initializing.
mqtt_client_t static_client;
Afterwards, with USART interrupt, I call
example_do_connect(&static_client); example_publish(&static_client,0);
Which calls those functions:
{
struct mqtt_connect_client_info_t ci;
err_t err;
/* Setup an empty client info structure */
memset(&ci, 0, sizeof(ci));
/* Minimal amount of information required is client identifier, so set it here */
ci.client_id = "lwip_test";
ci.client_user = NULL;
ci.client_pass = NULL;
/* Initiate client and connect to server, if this fails immediately an error code is returned
otherwise mqtt_connection_cb will be called with connection result after attempting
to establish a connection with the server.
For now MQTT version 3.1.1 is always used */
err = mqtt_client_connect(client, &serverIp, MQTT_PORT, mqtt_connection_cb, 0, &ci);
/* For now just print the result code if something goes wrong*/
if(err != ERR_OK) {
}
}
and
void example_publish(mqtt_client_t *client, void *arg)
{
const char *pub_payload= "stm32_test";
err_t err;
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
u8_t retain = 0; /* No don't retain such crappy payload... */
err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
if(err != ERR_OK) {
// printf("Publish err: %d\n", err);
err = ERR_OK;
}
}
/* Called when publish is complete either with sucess or failure */
static void mqtt_pub_request_cb(void *arg, err_t result)
{
if(result != ERR_OK) {
// printf("Publish result: %d\n", result);
}
}
I am able to ping board, my IP adress has been assigned in main by using IP_ADDR4(&serverIp, 192,168,2,97);
I've used all needed functions like MX_LWIP_Init(), MX_LWIP_Process() and actually i am even able to implement a TCP client, which is working nice. So internet connection is well, but I guess, there is a point that i missed in mqttclient. Callbacks is also have done by Erik Anderssen's guide.
When i try to subscribe to board's IP by using mosquitto, Error: no connection could be made because the target actively refused it. If you notice some point that i have missed or have an idea, please let me know.
Any help will appreciated, thanks in advance.
I had a similar problem that the server refused the connection when QoS (quality of service) was set to 2, but the server needed it to be 0. Try changing the parameter qos in the line in the connection callback to either 0 or 1:
err = mqtt_subscribe(mqtt.client, "topic", qos, MqttApp_SubscribeRequestCallback, arg);
Same applies to the parameter qos in the publish function:
change u8_t qos = 2; to u8_t qos = 0; (or 1 - whatever your server requires)
Hope it helps. Cheers.

How is the ESP32 (DOIT DevKit) finding another host in the same LAN via mDNS?

I have a Raspberry Pi connected to my Wifi LAN that responds to mDNS as mqtt-broker.local.
I can find it on my laptop with this command:
$ avahi-resolve-host-name -4 mqtt-broker.local
mqtt-broker.local 192.168.XXX.YYY
I have an ESP32 DOIT DevKit device that can send messages to the Raspberry Pi via Wifi if I use the IP address 192.168.XXX.YYY, however I would like my ESP32 to resolve the host using mDNS.
I am not able to get the mDNS working, the code at the bottom prints:
Finding the mDNS details...
No services found...
Done finding the mDNS details...
What's wrong with this code?
What should I put as service in MDNS.queryService("mqtt-broker", "tcp")? I have tried even with service mqtt with no luck, however this shouldn't matter, the mDNS stuff should work regardless what's exposed from the Raspberry Pi (HTTP server, MQTT, FTP whatever...)
Checking here https://github.com/espressif/arduino-esp32/blob/master/libraries/ESPmDNS/src/ESPmDNS.h#L98 there is not that much information about this "service" and "proto", and I am not that much familiar with low-level C/C++, what are these things?
This is the code I am using:
// import the headers
#include <ESPmDNS.h>
void findMyPi() {
Serial.println("Finding the mDNS details...");
// make sure we are connected to the Wifi
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.println("Not yet connected to Wifi...");
}
if (!MDNS.begin("whatever_this_could_be_anything")) {
Serial.println("Error setting up MDNS responder!");
}
// what should I put in here as "service"?
int n = MDNS.queryService("mqtt-broker", "tcp");
if (n == 0) {
Serial.println("No services found...");
}
else {
for (int i = 0; i < n; ++i) {
// Print details for each service found
Serial.print(" ");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(MDNS.hostname(i)); // "mqtt-broker" ??? How can I find it???
Serial.print(" (");
Serial.print(MDNS.IP(i));
Serial.print(":");
Serial.print(MDNS.port(i));
Serial.println(")");
}
}
Serial.println("Done finding the mDNS details...");
}
This function has been inspired by this example:
https://github.com/espressif/arduino-esp32/blob/master/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino
Ended up using a different method from the class on that mDNS library provided by Espressif (ESPmDNS.h), a combination of:
IPAddress serverIp = MDNS.queryHost(mDnsHost);
while loop on this check serverIp.toString() == "0.0.0.0"
This is the code that glues up all together:
// on my laptop (Ubuntu) the equivalent command is: `avahi-resolve-host-name -4 mqtt-broker.local`
String findMDNS(String mDnsHost) {
// the input mDnsHost is e.g. "mqtt-broker" from "mqtt-broker.local"
Serial.println("Finding the mDNS details...");
// Need to make sure that we're connected to the wifi first
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
if (!MDNS.begin("esp32whatever")) {
Serial.println("Error setting up MDNS responder!");
} else {
Serial.println("Finished intitializing the MDNS client...");
}
Serial.println("mDNS responder started");
IPAddress serverIp = MDNS.queryHost(mDnsHost);
while (serverIp.toString() == "0.0.0.0") {
Serial.println("Trying again to resolve mDNS");
delay(250);
serverIp = MDNS.queryHost(mDnsHost);
}
Serial.print("IP address of server: ");
Serial.println(serverIp.toString());
Serial.println("Done finding the mDNS details...");
return serverIp.toString();
}

Cannot connect to Solace Cloud

I am following the solace tutorial for Publish/Subscribe (link: https://dev.solace.com/samples/solace-samples-java/publish-subscribe/). Therefore, there shouldn't be anything "wrong" with the code.
I am trying to get my TopicSubscriber to connect to the cloud. After building my jar I run the following command:
java -cp target/SOM_Enrichment-1.0-SNAPSHOT.jar TopicSubscriber <host:port> <client-username#message-vpn> <password>
(with the appropriate fields filled in)
I get the following error:
TopicSubscriber initializing...
Jul 12, 2018 2:27:56 PM com.solacesystems.jcsmp.protocol.impl.TcpClientChannel call
INFO: Connecting to host 'blocked out' (host 1 of 1, smfclient 2, attempt 1 of 1, this_host_attempt: 1 of 1)
Jul 12, 2018 2:28:17 PM com.solacesystems.jcsmp.protocol.impl.TcpClientChannel call
INFO: Connection attempt failed to host 'blocked out' ConnectException com.solacesystems.jcsmp.JCSMPTransportException: ('blocked out') - Error communicating with the router. cause: java.net.ConnectException: Connection timed out: no further information ((Client name: 'blocked out' Local port: -1 Remote addr: 'blocked out') - )
Jul 12, 2018 2:28:20 PM com.solacesystems.jcsmp.protocol.impl.TcpClientChannel close
INFO: Channel Closed (smfclient 2)
Exception in thread "main" com.solacesystems.jcsmp.JCSMPTransportException" (Client name: 'blocked out' Local port: -1 Remote addr: 'blocked out') - Error communicating with the router.
Below is the TopicSubscriber.java file:
import java.util.concurrent.CountDownLatch;
import com.solacesystems.jcsmp.BytesXMLMessage;
import com.solacesystems.jcsmp.JCSMPException;
import com.solacesystems.jcsmp.JCSMPFactory;
import com.solacesystems.jcsmp.JCSMPProperties;
import com.solacesystems.jcsmp.JCSMPSession;
import com.solacesystems.jcsmp.TextMessage;
import com.solacesystems.jcsmp.Topic;
import com.solacesystems.jcsmp.XMLMessageConsumer;
import com.solacesystems.jcsmp.XMLMessageListener;
public class TopicSubscriber {
public static void main(String... args) throws JCSMPException {
// Check command line arguments
if (args.length != 3 || args[1].split("#").length != 2) {
System.out.println("Usage: TopicSubscriber <host:port> <client-username#message-vpn> <client-password>");
System.out.println();
System.exit(-1);
}
if (args[1].split("#")[0].isEmpty()) {
System.out.println("No client-username entered");
System.out.println();
System.exit(-1);
}
if (args[1].split("#")[1].isEmpty()) {
System.out.println("No message-vpn entered");
System.out.println();
System.exit(-1);
}
System.out.println("TopicSubscriber initializing...");
final JCSMPProperties properties = new JCSMPProperties();
properties.setProperty(JCSMPProperties.HOST, args[0]); // host:port
properties.setProperty(JCSMPProperties.USERNAME, args[1].split("#")[0]); // client-username
properties.setProperty(JCSMPProperties.PASSWORD, args[2]); // client-password
properties.setProperty(JCSMPProperties.VPN_NAME, args[1].split("#")[1]); // message-vpn
final Topic topic = JCSMPFactory.onlyInstance().createTopic("tutorial/topic");
final JCSMPSession session = JCSMPFactory.onlyInstance().createSession(properties);
session.connect();
final CountDownLatch latch = new CountDownLatch(1); // used for
// synchronizing b/w threads
/** Anonymous inner-class for MessageListener
* This demonstrates the async threaded message callback */
final XMLMessageConsumer cons = session.getMessageConsumer(new XMLMessageListener() {
#Override
public void onReceive(BytesXMLMessage msg) {
if (msg instanceof TextMessage) {
System.out.printf("TextMessage received: '%s'%n",
((TextMessage) msg).getText());
} else {
System.out.println("Message received.");
}
System.out.printf("Message Dump:%n%s%n", msg.dump());
latch.countDown(); // unblock main thread
}
#Override
public void onException(JCSMPException e) {
System.out.printf("Consumer received exception: %s%n", e);
latch.countDown(); // unblock main thread
}
});
session.addSubscription(topic);
System.out.println("Connected. Awaiting message...");
cons.start();
// Consume-only session is now hooked up and running!
try {
latch.await(); // block here until message received, and latch will flip
} catch (InterruptedException e) {
System.out.println("I was awoken while waiting");
}
// Close consumer
cons.close();
System.out.println("Exiting.");
session.closeSession();
}
}
Any help would be greatly appreciated.
java.net.ConnectException: Connection timed out
The log entry indicates that network connectivity to the specified DNS name/IP address cannot be established.
Next step includes:
Verifying that you are able to resolve the DNS name to an IP
address.
Verifying that the correct DNS name/IP address/Port is in use - You need the "SMF Host" in the Solace Cloud Connection Details.
Verifying that the IP address/Port is not blocked by an intermediate network device.

Arduino WiFi shield post with header problems

I'm trying to do a post from the arduino wifi shield to my java servlet. The servlet functions with url get, and jquery post, but I can't sort the headers out in my arduino code. Any help will be greatly appreciated!
The server returns 200, but I'm not getting the payload "content" as value. I'm not exactly sure what I'm doing wrong but I'm pretty sure it's in how my headers are setup. I've spent the last two days trying to get it.
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "jesussavesforjust19.95"; // your network SSID (name)
char pass[] = "********"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
IPAddress server(192,168,10,149); // numeric IP for Google (no DNS)
WiFiClient client;
void setup() {
Serial.begin(9600);
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.println("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
sendData("0600890876");
}
void loop() {
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.println(c);
}
//String dataString = "060088765";
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected())
{
Serial.println();
Serial.println("disconnecting.");
client.stop();
//sendData(dataString);
for(;;)
;
}
}
// this method makes a HTTP connection to the server:
void sendData(String thisData) {
// if there's a successful connection:
Serial.println("send data");
if (client.connect(server, 8080)) {
String content = "value=0600887654";
Serial.println(content);
Serial.println("connected");
client.println("POST /hos HTTP/1.1");
client.println("Host:localhost");
client.println("Connection:Keep-Alive");
client.println("Cache-Control:max-age=0");
client.println("Content-Type: application/x-www-form-urlencoded\n");
client.println("Content-Length: ");
client.println(content.length());
client.println("\n\n");
client.println(content);
}
else {
// if you couldn't make a connection:
Serial.println("form connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.println("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.println("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.println("signal strength (RSSI):");
Serial.println(rssi);
Serial.println(" dBm");
}
Perhaps, some of your "Serial.println" and "client.println" commands should be "Serial.print" and "client.print" instead. For example:
client.print("Content-Length: ");
client.println(content.length());
would avoid adding a line break between the text and the number.
This is maybe more advice on an approach than an answer.
If I was doing something like this I would not start on the Arduino. The endless compile, download, run, look at print()'s would drive me crazy. I would fully prototype the client/server interaction in whatever you have at your fingertips, preferably something with a debugger. (Java, Python, PHP, VB, whatever you know that you can slap together)
Second, I would run Wireshark on the server so that I could see exactly what was being sent and responded.
Then I would port the same interaction over to the Arduino. Again inspect with Wireshark to confirm you are getting what you expected. If you send the same bytes, you should get the same response.
Even if you choose to implement straight on Arduino, consider having Wireshark to capture the actual network traffic.
With Wireshark, you might see that the Arduino println() is not sending the correct line end for the server.
Also, there is no guarantee that last println() is actually sent. The network stack implementation is free to buffer as it sees fit. You might need a flush(). A packet trace would show this.
With a packet capture you might find that time matters. In theory TCP is a stream and you should be able to send that POST data 1 character at a time in 1 packet and everything would work. But the Arduino might be so slow executing those println()'s by the server's standards that it times out. In such case you would see the server respond before the Arduino even finished sending.

Abnormally disconnected TCP sockets and write timeout

I will try to explain the problem in shortest possible words. I am using c++ builder 2010.
I am using TIdTCPServer and sending voice packets to a list of connected clients. Everything works ok untill any client is disconnected abnormally, For example power failure etc. I can reproduce similar disconnect by cutting the ethernet connection of a connected client.
So now we have a disconnected socket but as you know it is not yet detected at server side so server will continue to try to send data to that client too.
But when server try to write data to that disconnected client ...... Write() or WriteLn() HANGS there in trying to write, It is like it is wating for somekind of Write timeout. This hangs the hole packet distribution process as a result creating a lag in data transmission to all other clients. After few seconds "Socket Connection Closed" Exception is raised and data flow continues.
Here is the code
try
{
EnterCriticalSection(&SlotListenersCriticalSection);
for(int i=0;i<SlotListeners->Count;i++)
{
try
{
//Here the process will HANG for several seconds on a disconnected socket
((TIdContext*) SlotListeners->Objects[i])->Connection->IOHandler->WriteLn("Some DATA");
}catch(Exception &e)
{
SlotListeners->Delete(i);
}
}
}__finally
{
LeaveCriticalSection(&SlotListenersCriticalSection);
}
Ok i already have a keep alive mechanism which disconnect the socket after n seconds of inactivity. But as you can imagine, still this mechnism cant sync exactly with this braodcasting loop because this braodcasting loop is running almost all the time.
So is there any Write timeouts i can specify may be through iohandler or something ? I have seen many many threads about "Detecting disconnected tcp socket" but my problem is little different, i need to avoid that hangup for few seconds during the write attempt.
So is there any solution ?
Or should i consider using some different mechanism for such data broadcasting for example the broadcasting loop put the data packet in some kind of FIFO buffer and client threads continuously check for available data and pick and deliver it to themselves ? This way if one thread hangs it will not stop/delay the over all distribution thread.
Any ideas please ? Thanks for your time and help.
Regards
Jams
There are no write timeouts implemented in Indy. For that, you will have to use the TIdSocketHandle.SetSockOpt() method to set the socket-level timeouts directly.
The FIFO buffer is a better option (and a better design in general). For example:
void __fastcall TForm1::IdTCPServer1Connect(TIdContext *AContext)
{
...
AContext->Data = new TIdThreadSafeStringList;
...
}
void __fastcall TForm1::IdTCPServer1Disconnect(TIdContext *AContext)
{
...
delete AContext->Data;
AContext->Data = NULL;
...
}
void __fastcall TForm1::IdTCPServer1Execute(TIdContext *AContext)
{
TIdThreadSafeStringList *Queue = (TIdThreadSafeStringList*) AContext->Data;
TStringList *Outbound = NULL;
TStringList *List = Queue->Lock();
try
{
if( List->Count > 0 )
{
Outbound = new TStringList;
Outbound->Assign(List);
List->Clear();
}
}
__finally
{
Queue->Unlock();
}
if( Outbound )
{
try
{
AContext->Connection->IOHandler->Write(Outbound);
}
__finally
{
delete Outbound;
}
}
...
}
...
try
{
EnterCriticalSection(&SlotListenersCriticalSection);
int i = 0;
while( i < SlotListeners->Count )
{
try
{
TIdContext *Ctx = (TIdContext*) SlotListeners->Objects[i];
TIdThreadSafeStringList *Queue = (TIdThreadSafeStringList*) Ctx->Data;
Queue->Add("Some DATA");
++i;
}
catch(const Exception &e)
{
SlotListeners->Delete(i);
}
}
}
__finally
{
LeaveCriticalSection(&SlotListenersCriticalSection);
}

Resources