Phil Gaudet in MATLAB Answers
최근 활동: 2022년 4월 11일

Using new Adafruit Huzzah breakout with Arduino IDE 1.8.10, TS library 1.5.0 on MacOS 10.15.1 . Board always connects to fixed IP address on my network. It never connects to ThingSpeak, throwing a -301 error code. This same board works fine as a webserver and gets network time without a problem using other custom code. I have tried the TS Wifi example with no luck and used the thermistor example to create this code. Had an existing account in TS and just added a new channel. The new channelID and write API key along with SSID and PW are in a separate file called Credentials.h (not shown here). Tried generating new write API key, no joy. /* * Monitor solar battery charger sending current, voltage, temperature * to Thingspeak * * Running on Adafruit ESP Hazzah breakout PID:2471 * Using FTDI Friend V1.0 PID:284 Jumpered for 5V power * * Board settings: * BOARD: Adafruit Feather HUZZAH ESP8266 * Flash Size: 4M (1M SPIFFS) * * ESP8266 Connections: * PIN VBATT - 6V BATTERY (+) (wht) WITH 1N4004 IN SERIES TO DROP SUPPLY BELOW 6V * PIN GND - BATT (-) (blk) * PIN 3V - INA219 VCC (red) * PIN GND - INA219 GND (blk) * PIN 5 SCL - I2C (grn) INA219(0x40) * PIN 4 SDA - I2C (yel) * * Loosely based on https://www.mathworks.com/help/thingspeak/read-and-post-temperature-data.html * * v2 11/18/19 pg * Add one-wire temp sensor * */ #include <ESP8266WiFi.h> #include <Wire.h> #include "ThingSpeak.h" #include "Credentials.h" #include <Adafruit_INA219.h> const uint8_t INA_ADDR = 0x40; Adafruit_INA219 ina219; bool INAConnected = false; float shuntvoltage = 0; float battvoltage = 0; float current_mA = 0; float loadvoltage = 0; float power_mW = 0; float batttemp = 0; unsigned int dataFieldOne = 1; // Field to write current data unsigned int dataFieldTwo = 2; // Field to write voltage data unsigned int dataFieldThree = 3; // Field to write temperature data WiFiClient client; uint32_t lastConnectionTime = 0; const unsigned long POSTING_INTERVAL = 20L * 1000L; // Post data every 20 seconds. /******************************************************/ void setup() { Serial.begin(115200); Serial.println(); // Initialize the INA219. // By default the initialization will use the largest range (32V, 2A). However // you can call a setCalibration function to change this range (see comments). ina219.begin(); // CHECK IF INA IS CONNECTED Wire.beginTransmission (INA_ADDR); if (Wire.endTransmission() == 0) { Serial.print (F("I2C device found at 0x")); Serial.println(INA_ADDR, HEX); INAConnected = true; } else Serial.println(F("******** NO INA219 *********")); Serial.printf("Connecting to %s ", ssid); WiFi.begin(ssid, pass); WiFi.config(ip, gateway, subnet); // Connect to WiFi network as fixed IP while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.print("\nConnected at IP:"); Serial.println( WiFi.localIP().toString().c_str()); ThingSpeak.begin(client); } // end setup /**********************************************************/ void loop() { // If interval time has passed since the last connection, send data to ThingSpeak. if (millis() - lastConnectionTime > POSTING_INTERVAL) { lastConnectionTime = millis(); if(INAConnected) { shuntvoltage = ina219.getShuntVoltage_mV(); loadvoltage = ina219.getBusVoltage_V(); current_mA = ina219.getCurrent_mA(); power_mW = ina219.getPower_mW(); battvoltage = loadvoltage + (shuntvoltage / 1000); batttemp = 0; Serial.println(""); Serial.print("Load Voltage: "); Serial.print(loadvoltage); Serial.println(" V"); Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV"); Serial.print("Batt Voltage: "); Serial.print(battvoltage); Serial.println(" V"); Serial.print("Current: "); Serial.print(current_mA); Serial.println(" mA"); Serial.print("Power: "); Serial.print(power_mW); Serial.println(" mW"); Serial.print("Bat Temp: "); Serial.print(batttemp); Serial.println(" degC"); } int httpCode = write2TSData(myChannelID,dataFieldOne, current_mA, dataFieldTwo, battvoltage, dataFieldThree, batttemp); if (httpCode == 200) { Serial.println("Channel write successful."); } else { Serial.println("Problem writing to channel. HTTP error code " + String(httpCode)); } } // end of interval timer } // end loop /******************************************************************************************** * Read data from a single field on a channel with readTSData. You can write a single value * to ThingSpeak using writeTSData and write multiple values simultaneously with write2TSdata. */ float readTSData( long TSChannel,unsigned int TSField ){ float data = ThingSpeak.readFloatField( TSChannel, TSField, myReadAPIKey ); Serial.println( " Data read from ThingSpeak: " + String( data, 9 ) ); return data; } // Use this function if you want to write a single field. int writeTSData( long TSChannel, unsigned int TSField, float data ){ int writeSuccess = ThingSpeak.writeField( TSChannel, TSField, data, myWriteAPIKey ); // Write the data to the channel if ( writeSuccess ){ Serial.println( String(data) + " written to Thingspeak." ); } return writeSuccess; } // Use this function if you want to write multiple fields simultaneously. int write2TSData( long TSChannel, unsigned int TSField1, float field1Data, unsigned int TSField2, long field2Data, unsigned int TSField3, long field3Data ){ ThingSpeak.setField( TSField1, field1Data ); ThingSpeak.setField( TSField2, field2Data ); ThingSpeak.setField( TSField3, field3Data ); int writeSuccess = ThingSpeak.writeFields( TSChannel, myWriteAPIKey ); return writeSuccess; }
David Evans in MATLAB Answers
최근 활동: 2022년 1월 17일

The following code runs on an Adafruit ESP32 Feather that connects to the internet via my ASUS RT-N66U router. The ESP32 is "remote" and is accessible only via wifi. It posts to ThingSpeak every 10 minutes and works fine for a day, sometimes a few days, but then it stops posting and returns error -301 ("failed to connect") with every attempt. It only starts posting again after a hard reboot. I suspected heap fragmentation, but free heap is constant at 247k (after an initial quick decline from 250k) and max allocatable heap is constant at 114k from the start. ESP32 hasn't lost wifi connectivity, since I can access the ESP32 via the router (and run the "server.on" commands). I also have an ESP8266 posting to ThingSpeak every five minutes and it has been online for months, so the problem probably isn't with the router or ISP. Even after the ESP32 stops posting, I can successfully manually post from a browser with https://api.thingspeak.com/update.json?api_key=xyz&field5=199, so it seems the problem is with the code. I'm running the latest ThingSpeak library, ESP library and core (but not developmental version), and Arduino IDE. Would appreciate suggestions on things to try or monitor. #include <WiFi.h> #include <WiFiClient.h> #include <WebServer.h> #include <ArduinoOTA.h> #include <ESP_Mail_Client.h> #include <esp_int_wdt.h> // for hard reboot #include <esp_task_wdt.h>// ditto #include "ThingSpeak.h" // "always put this last in the list of includes" WebServer server(80); // OTA and server.on WiFiClient client; // TS only //**** definitions etc **** #define SMTP_HOST "smtp.gmail.com" #define SMTP_PORT 465 #define AUTHOR_EMAIL "xyz@gmail.com" #define AUTHOR_PASSWORD "abc" SMTPSession smtp; void smtpCallback(SMTP_Status status); ESP_Mail_Session session; SMTP_Message message; const char * myWriteAPIKey = "efg"; // TS const byte deltaDecreaseCM = 30; // threshold in cm... 12" = 30.48 cm const int distAvg = 1060; // average distance const unsigned long myChannelNumber = 123; // TS bool paused = false; bool savedPaused; bool intruder = false; bool alarmSounded = false; bool snowing = false; bool snowTriggeredOnce = false; bool distSaving = true; byte reqdNumBreaks = 6; byte lastTSalarmFlag; byte snowFactor = 1; byte savedSnowFactor; byte snowCount; byte saveDist[100]; byte saveIdx = 99; int distCurrent; int savedDistance; int lastTScode = 200; int wiFiFailsTS; unsigned long numIntruders; // can be very large if beam is blocked for a long time (eg. by parked car) unsigned long alarmTriggeredTime; unsigned long prevTSfailTime = 0; unsigned long startSnowingTime; unsigned long firstSnowTrigger; unsigned long pauseStartTime; unsigned long pauseDuration; //**** setup **** void setup() { Serial1.begin(115200); // TF03 default rate = 115200 WiFi.begin(); while (WiFi.waitForConnectResult() != WL_CONNECTED) { delay(5000); ESP.restart(); } setupMail(); server.on("/", handleRoot); server.on("/reboot", reBootMe); server.on("/postTS", doTSpost); server.on("/showTS", showTScode); server.onNotFound(handleNotFound); ArduinoOTA.begin(); server.begin(); ThingSpeak.begin(client); readTFxTimes(50); // clear serial1 buffer } //*************************************************************************************** //**** loop **** //*************************************************************************************** void loop() { ArduinoOTA.handle(); // this works even if posting to TS does not work server.handleClient(); // ditto unsigned long currTime = millis(); const unsigned long writeTSinterval = 600000UL; // post to TS every 10 min (and upon sounding alarm) static unsigned long prevTSwriteTime = 0; const unsigned long maxAlertInterval = 600000UL; // no duplicate alarms for 10 min after an alarm // reset pause flag if time is up if (paused && (currTime - pauseStartTime > pauseDuration)) { paused = false; } // reset alarm flag if time is up if (alarmSounded && (currTime - alarmTriggeredTime > maxAlertInterval)) { alarmSounded = false; } readTFxTimes(1); // read TF03 once every loop if (! paused && ! alarmSounded) { // chk for intruder, but only if not paused and not w/in 10 min of an alarm chkForIntruder(); if (intruder && (numIntruders == reqdNumBreaks * snowFactor)) soundAlarm(); // sound alarm if sufficient number of sequential brks } // post to thingSpeak if (prevTSfailTime) { // if an alarmFlag=1 write failed (posted too soon after an alarmFlag=0 post) if (currTime - prevTSfailTime > 20000UL) { // try again after 20 sec (15.1 sec didn't seem to work on 1/27 when there was a collision) prevTSfailTime = 0; prevTSwriteTime = currTime; writeThingSpeak(1, savedDistance, savedSnowFactor, savedPaused); //this will only do one re-try. If this fails again with -401 (for whatever reason) //it will just continue on with normal (alarmFlag=0) posts after 10 minutes. } } else if ((currTime - prevTSwriteTime > writeTSinterval) && (! intruder)) { prevTSwriteTime = currTime; writeThingSpeak(0, distCurrent, snowFactor, paused); // zero indicates no alarmFlag } } //*************************************************************************************** //**** writeThingSpeak **** //*************************************************************************************** void writeThingSpeak(byte alarmF, int distC, byte snowF, bool pausD) { if (WiFi.status() != WL_CONNECTED) { // should already be connected, but check again anyway wiFiFailsTS++; //this has never been > 1 while (WiFi.status() != WL_CONNECTED) { WiFi.begin(); delay(5000); } } int freeHeap = ESP.getFreeHeap(); int maxAllocatable = ESP.getMaxAllocHeap(); ThingSpeak.setField(1, distC); ThingSpeak.setField(2, alarmF); // 0 = no intruder; 1 = intruder; 4 = manual test post ThingSpeak.setField(3, snowF); // 1 = no snow; other = snowing ThingSpeak.setField(4, pausD); ThingSpeak.setField(5, lastTScode); ThingSpeak.setField(6, freeHeap); ThingSpeak.setField(7, maxAllocatable); ThingSpeak.setField(8, wiFiFailsTS); lastTScode = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey); readTFxTimes(50); // in case the above takes "a while". 100 = about one second of reads, so 50 is about half a second /* https://github.com/mathworks/thingspeak-arduino Return Codes Value Meaning 200 OK / Success 404 Incorrect API key (or invalid ThingSpeak server address) -101 Value is out of range or string is too long (> 255 characters) -201 Invalid field number specified -210 setField() was not called before writeFields() -301 Failed to connect to ThingSpeak <------------------------------- -302 Unexpected failure during write to ThingSpeak -303 Unable to parse response -304 Timeout waiting for server to respond -401 Point was not inserted (most probable cause is the rate limit of once every 15 seconds) 0 Other error */ } //**** chkForIntruder **** void chkForIntruder() { int deltaDist = distAvg - distCurrent; if (distSaving) { // not currently accessible (deleted the associated server.on) saveIdx = (saveIdx + 1) % 100; if (deltaDist < 0) { saveDist[saveIdx] = 0; } else { saveDist[saveIdx] = deltaDist; } } if (deltaDist > deltaDecreaseCM) { // if distance descreases more than the limit, then there's an intruder intruder = true; numIntruders++; // number of sequential breaks, actually } else { if (snowing) { if (millis() - startSnowingTime < 1800000UL) { if ((reqdNumBreaks / 2 < numIntruders) && (numIntruders < reqdNumBreaks)) snowCount++; } else { // time is up if (! snowCount) { // if snowCount == 0, reset flag and factor snowing = false; snowFactor = 1; } else { // snowCount was > 0, so need to keep checking... startSnowingTime = millis(); // reset time, so check again later snowCount = 0; // restart count for this new period } // end "else" (snow count > 0) } // end "else" (time is up) } else { // end "if snowing" if (snowTriggeredOnce) { if (millis() - firstSnowTrigger > 300000UL) { // triggered once, but time expired, so re-set flag snowTriggeredOnce = false; } else if ((reqdNumBreaks / 2 < numIntruders) && (numIntruders < reqdNumBreaks)) { // triggered once, time not expired, meets criteria...set snowing flag, etc. startSnowingTime = millis(); snowing = true; snowFactor = 4; snowTriggeredOnce = false; distSaving = false; } //end snowTriggeredOnce } else if ((reqdNumBreaks / 2 < numIntruders) && (numIntruders < reqdNumBreaks)) { // not triggered yet, but meets criteria, so set triggered once flag, etc. snowTriggeredOnce = true; firstSnowTrigger = millis(); } // end not triggered yet but meets criteria } // end "not snowing" intruder = false; numIntruders = 0; } // end "else" distance not decreased...so no intruder, and numIntruders reset to zero } //**** soundAlarm **** void soundAlarm() { alarmTriggeredTime = millis(); alarmSounded = true; sendMyMailNow(); //send an alert if (snowing && (startSnowingTime - alarmTriggeredTime < 5000)) { snowing = false; snowFactor = 1; } writeThingSpeak(1, distCurrent, snowFactor, paused); // 1 indicates intruder if (lastTScode == -401) { prevTSfailTime = millis(); savedDistance = distCurrent; savedSnowFactor = snowFactor; savedPaused = paused; } } //**** readTFxTimes **** void readTFxTimes(byte numOfReads) { for (byte i = 0; i < numOfReads; i++) { while (! readTF03once()) { //read until a number is obtained } } } //**** readTF03once **** bool readTF03once() { int check; // checksum byte uart[9]; // stores each byte of data returned by LiDAR (was int... I changed to byte) const byte HEADER = 0x59; // data package frame header...the letter "Y" in ASCII (was int... I changed to byte) if (Serial1.available()) { //check whether the serial port has data input if (Serial1.read() == HEADER) { // determine data package frame header = 0x59 uart[0] = HEADER; if (Serial1.read() == HEADER) { // determine data package frame header = 0x59 uart[1] = HEADER; for (byte i = 2; i < 9; i++) { // store rest of data to array uart[i] = Serial1.read(); } check = uart[0] + uart[1] + uart[2] + uart[3] + uart[4] + uart[5] + uart[6] + uart[7]; if (uart[8] == (check & 0xff)) { // check the received data as per protocols 0xff = 0b11111111 // Not sure why bitwise and (&) is used. distCurrent = uart[2] + uart[3] * 256; // calculate distance value return true; //got a reading } } } } distCurrent = 0; return false; //didn't get a reading } void handleRoot() { if (server.arg("pause") != "") { // i.e., if not zero, then user entered ...?pause=(a number) paused = true; pauseDuration = (unsigned long) server.arg("pause").toInt(); // in minutes pauseStartTime = millis(); if (pauseDuration <= 0) { // if neg, do nothing paused = false; } else if (pauseDuration > 1200) { // if large, limit to 1200 minutes = 20 hours pauseDuration = 1200UL; intruder = false; // so posting to TS continues during pause numIntruders = 0; } else { // otherwise, use received value intruder = false; // so posting to TS continues during pause numIntruders = 0; } pauseDuration *= 60000UL; // convert minutes to milliseconds server.send(200, "text/plain", "pausing"); } else { // not break or pause server.send(200, "text/plain", "ESP32 eye .151"); } } void reBootMe() { // run with /reboot // see e32hardReset in test_espB folder for basis of this server.send(200, "text/plain", "reboot in 2"); delay(2000); esp_task_wdt_init(1, true); esp_task_wdt_add(NULL); while (true); } void doTSpost() { // run with /postTS server.send(200, "text/plain", "posting a 2 to TS"); writeThingSpeak(2, distCurrent, snowFactor, paused); } void showTScode() { // run with /showTS char myCstr[15]; snprintf(myCstr, 15, "TScode=%d", lastTScode); server.send(200, "text/plain", myCstr); } void handleNotFound() { server.send(404, "text/plain", "404: Not found"); } void smtpCallback(SMTP_Status status) { Serial.println(status.info()); if (status.success()) { Serial.println("----------------"); Serial.printf("Message sent success: %d\n", status.completedCount()); Serial.printf("Message sent failled: %d\n", status.failedCount()); Serial.println("----------------\n"); struct tm dt; for (size_t i = 0; i < smtp.sendingResult.size(); i++) { SMTP_Result result = smtp.sendingResult.getItem(i); localtime_r(&result.timesstamp, &dt); Serial.printf("Message No: %d\n", i + 1); Serial.printf("Status: %s\n", result.completed ? "success" : "failed"); Serial.printf("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec); Serial.printf("Recipient: %s\n", result.recipients); Serial.printf("Subject: %s\n", result.subject); } Serial.println("----------------\n"); } } void setupMail() { smtp.debug(0); // 0 = none smtp.callback(smtpCallback); session.server.host_name = SMTP_HOST; session.server.port = SMTP_PORT; session.login.email = AUTHOR_EMAIL; session.login.password = AUTHOR_PASSWORD; session.login.user_domain = "mydomain.net"; message.sender.name = "ESP Mail"; message.sender.email = AUTHOR_EMAIL; message.subject = "Test sending plain text Email"; message.addRecipient("Someone", "phoneNum@mms.cricketwireless.net"); message.text.content = "This is simple plain text message"; message.text.charSet = "us-ascii"; message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit; message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_normal; message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay; message.addHeader("Message-ID: <abcde.fghij@gmail.com>"); } void sendMyMailNow() { if (!smtp.connect(&session)) { Serial.println("failed to connec to smtp sesh"); return; } else if (!MailClient.sendMail(&smtp, &message)) { /* Start sending Email and close the session */ //Serial.println("Error sending Email, " + smtp.errorReason()); } }
Jonathan Baker in MATLAB Answers
최근 활동: 2021년 9월 7일

I am using an Arduino Uno R3 board and Ethernet shield. I replaced the Channel ID and the write API key with my own in the secrets.h file. It connects with DHCP ok. Arduino IDE 1.8.12 But comes back with error code -301. Serial Monitor: Initialize Ethernet with DHCP: DHCP assigned IP 10.10.1.170 Problem updating channel. HTTP error code -301 What am I missing? /* WriteMultipleFields Description: Writes values to fields 1,2,3 and 4 in a single ThingSpeak update every 20 seconds. Hardware: Arduino Ethernet !!! IMPORTANT - Modify the secrets.h file for this project with your network connection and ThingSpeak channel details. !!! Note: - Requires the Ethernet library ThingSpeak ( https://www.thingspeak.com ) is an analytic IoT platform service that allows you to aggregate, visualize, and analyze live data streams in the cloud. Visit https://www.thingspeak.com to sign up for a free account and create a channel. Documentation for the ThingSpeak Communication Library for Arduino is in the README.md folder where the library was installed. See https://www.mathworks.com/help/thingspeak/index.html for the full ThingSpeak documentation. For licensing information, see the accompanying license file. Copyright 2018, The MathWorks, Inc. */ #include "ThingSpeak.h" #include <Ethernet.h> #include "secrets.h" byte mac[] = SECRET_MAC; // Set the static IP address to use if the DHCP fails to assign IPAddress ip(10, 10, 1, 76); IPAddress myDns(10, 10, 1, 1); EthernetClient client; unsigned long myChannelNumber = SECRET_CH_ID; const char * myWriteAPIKey = SECRET_WRITE_APIKEY; // Initialize our values int number1 = 0; int number2 = random(0,100); int number3 = random(0,100); int number4 = random(0,100); void setup() { Ethernet.init(10); // Most Arduino Ethernet hardware Serial.begin(115200); //Initialize serial // start the Ethernet connection: Serial.println("Initialize Ethernet with DHCP:"); if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // Check for Ethernet hardware present if (Ethernet.hardwareStatus() == EthernetNoHardware) { Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); while (true) { delay(1); // do nothing, no point running without Ethernet hardware } } if (Ethernet.linkStatus() == LinkOFF) { Serial.println("Ethernet cable is not connected."); } // try to congifure using IP address instead of DHCP: Ethernet.begin(mac, ip, myDns); } else { Serial.print(" DHCP assigned IP "); Serial.println(Ethernet.localIP()); } // give the Ethernet shield a second to initialize: delay(1000); ThingSpeak.begin(client); // Initialize ThingSpeak } void loop() { // set the fields with the values ThingSpeak.setField(1, number1); ThingSpeak.setField(2, number2); ThingSpeak.setField(3, number3); ThingSpeak.setField(4, number4); // write to the ThingSpeak channel int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey); if(x == 200){ Serial.println("Channel update successful."); } else{ Serial.println("Problem updating channel. HTTP error code " + String(x)); } // change the values number1++; if(number1 > 99){ number1 = 0; } number2 = random(0,100); number3 = random(0,100); number4 = random(0,100); delay(20000); // Wait 20 seconds to update the channel again

ThingSpeak 정보

The community for students, researchers, and engineers looking to use MATLAB, Simulink, and ThingSpeak for Internet of Things applications. You can find the latest ThingSpeak news, tutorials to jump-start your next IoT project, and a forum to engage in a discussion on your latest cloud-based project. You can see answers to problems other users have solved and share how you solved a problem.