Store data on MKR and update on Thingspeak every 5 minutes

Hello everyone,

As updating data every 20 seconds will consume a lot of power and MKR 1010 gets stuck sometimes. So I want to store the data for 5 minutes on board and update on ThingSpeak every 5 minute. But as MKR1010 doesn't have EEPROM I am not quite sure how to achieve this?

I read some other posts and projects. And it suggests that storing permanent variables as WiFi names and passwords, is a good to use Flash memory on MKR 1010 but for data logging it i not a good idea.

I was hoping if somebody could give me right direction here.

You could just store the data in RAM for 5 minutes - EEPROM would retain data if it’s switched off, but that doesn’t seem to be the case here - unless you have a way for it to wake up and power to switch on every 5 minutes?
You could get an I2C EEPROM (https://www.microchip.com/design-centers/memory/serial-eeprom), they are very cheap, and hook it up - that’s what I’m intending to do to store wifi config etc.

Thank you Kierenj. That seems good idea. But I am trying not to use any external hardware. I am trying to do this solely on MKR1010.

Do you have any idea how to store data on RAM?

What I really want to do is, say store 5 data points on board and when the power is connected upload all of them on ThingSpeak. Problem is all 5 data points are of same variable say temperature sensor.

I am confused how to make it work like that.

Use an array to store the data in ram:
https://www.arduino.cc/reference/en/language/variables/data-types/array/
So if your temperature reading is a float and you want to store 5 data points, you would declare a global array variable like this:

float temperatureData[5];

Won't it consume same power to upload all 5 data points in array to same field of ThingSpeak?

Purely guessing, but I would say no. Making and then closing the connection to ThingSpeak is likely the majority of the time the WiFi radio will be active on each upload. Sure, the radio will need to then be on longer to upload 5 data points than if would have to upload 1, but I suspect the difference will not be very significant.

It also may be that the power usage is not a fixed value at radio active vs radio inactive. I don't have the equipment to be able to measure momentary current, but the power supply requirements of WiFi devices leads me to believe there are spikes of high current draw during the radio usage. So it might be that 80% of the current used for each connection to Thingspeak is consumed just to make that connection and the rest of the session is happening at a lower current usage level.

I found some interesting information about the ESP32 (which is the module used for WiFi communication on the MKR WiFi 1010) that seems to somewhat corroborate my hypothesis:
https://forum.makehackvoid.com/t/playing-with-the-esp-32/1144

It wakes at 60-70mA, rising to around 140mA once wifi is turned on, with short spikes to over 350mA.

You can see these spikes in the teal trace below:

If I understand correctly, they didn't actually do any WiFi communication in this test. So we're just seeing the effect of activating and deactivating the WiFi radio. Since you're concerned about power consumption, I assume you're going to be deactivating the WiFi radio whenever it's not in use and sleeping the ESP32 when it doesn't need to do anything, so this information is still relevant. It would be nice to see a reading of the entire process of activating the radio, connecting to Thingspeak, uploading the date, disconnecting, and then deactivating the radio.

Thank you Pert that was really helpful.

You're welcome. I'm glad if I was able to be of assistance. Enjoy!
Per

Hello,

I am trying to read data from temperature sensor after every 15 seconds and upload on ThingSpeak after 2 minutes.

My problem here is, since with 15 seconds interval I will have 8 values, ThingSpeak won't let me upload all values on the same graph with the same timestamp.

I tried using JSON buffer but I am not able to understand how to pass temperature values through the code as I am new to this.

Can someone help me uploading 8 values on ThingSpeak on the same graph with the interval of 15 seconds?

Hello all,

I am trying to implement the tutorial of “Bulk-Update Using An Arduino” to upload multiple data-points after every 5 minutes. The data is collected from temperature sensor with an interval of 15 seconds and uploaded after every 5 minutes.

I am not able to understand the JSON bufffer they have used here to send the data and timestamps. How can I dump the data in the JSON buffer with the timestamp? More ever, as the MKRWiFi1010 has the RTC on the chip, I didn’t quite understand how to change that in the program?

Can somebody help me with that?

The Code for the this is given below:

(You can also find it on the website of ThingSpeak

Bulk-Update Using an Arduino or an ESP8266 - MATLAB & Simulink )

/1) Begin by including the appropriate libraries for your hardware./
#include<SPI.h>
#include<WiFiNINA.h>

/2) Initialize the jsonBuffer to hold the JSON data./

char jsonBuffer[500] = “[”; // Initialize the jsonBuffer to hold data

/* 3) Define the WiFi credentials to connect your Arduino board to the network,

  • and initialize the WiFi client library.*/

char ssid = “SSID”; // Your network SSID (name)
char pass = “PASSWORD”; // Your network password
WiFiClient client; // Initialize the WiFi client library

/4) Define the ThingSpeak server./

char server = “api.thingspeak.com”; // ThingSpeak Server

/* 5) Define other global variables that track the last connection time and last update time.

  • Also, define time intervals to update the data, and post the data to ThingSpeak.*/

/* Collect data once every 15 seconds and post data to ThingSpeak channel once every 2 minutes */
unsigned long lastConnectionTime = 0; // Track the last connection time
unsigned long lastUpdateTime = 0; // Track the last update time
const unsigned long postingInterval = 120L * 1000L; // Post data every 2 minutes
const unsigned long updateInterval = 15L * 1000L; // Update once every 15 seconds

/6) Use the setup method to initialize serial data transfer and to connect to WiFi network./

void setup() {
Serial.begin(9600);
// Attempt to connect to WiFi network
while (WiFi.status() != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
delay(10000); // Wait 10 seconds to connect
}
Serial.println(“Connected to wifi”);
printWiFiStatus(); // Print WiFi connection information
}

/7) In the loop method, call the updatesJson method to update the jsonBuffer with data once every second./

void loop() {
// If update time has reached 1 second, then update the jsonBuffer
if (millis() - lastUpdateTime >= updateInterval) {
updatesJson(jsonBuffer);
}

}

/*8) Define the updatesJson method to continuously update the jsonBuffer with data.

  • Since Arduino MKR1000 does not have a real-time clock,
  • you use the ‘delta_t’ parameter to define a relative time stamp in seconds between successive messages.
  • If your device has a real-time clock, you can use an absolute timestamp.
  • Replace ‘delta_t’ parameter with ‘created_at’ parameter.
  • Format the messages as JSON in a format mentioned in Bulk-Write JSON Data.
  • Call the httpRequest method to send data to ThingSpeak once every 2 minutes.*/

// Updates the josnBuffer with data
void updatesJson(char* jsonBuffer){
/* JSON format for updates paramter in the API

  • This examples uses the relative timestamp as it uses the “delta_t”.
  • You can also provide the absolute timestamp using the “created_at” parameter
  • instead of “delta_t”.
  • “[{“delta_t”:0,“field1”:-70},{“delta_t”:3,“field1”:-66}]”
    */

// Format the jsonBuffer as noted above
strcat(jsonBuffer,"{“delta_t”:");
unsigned long deltaT = (millis() - lastUpdateTime)/1000;
size_t lengthT = String(deltaT).length();
char temp[4];
String(deltaT).toCharArray(temp,lengthT+1);
strcat(jsonBuffer,temp);
strcat(jsonBuffer,",");
long rssi = WiFi.RSSI();
strcat(jsonBuffer, ““field1”:”);
lengthT = String(rssi).length();
String(rssi).toCharArray(temp,lengthT+1);
strcat(jsonBuffer,temp);
strcat(jsonBuffer,"},");

// If posting interval time has reached 2 minutes, update the ThingSpeak channel with your data
if (millis() - lastConnectionTime >= postingInterval) {
size_t len = strlen(jsonBuffer);
jsonBuffer[len-1] = ‘]’;
httpRequest(jsonBuffer);
}
lastUpdateTime = millis(); // Update the last update time
}

/9) Define the httpRequest method to send data to ThingSpeak and to print the response code from the server.
A response code 202 indicates that the server has accepted the request for precessing.
/

// Updates the ThingSpeakchannel with data
void httpRequest(char* jsonBuffer) {
/* JSON format for data buffer in the API

  • This examples uses the relative timestamp as it uses the “delta_t”.
  • You can also provide the absolute timestamp using the “created_at” parameter
  • instead of “delta_t”.
  • "{“write_api_key”:“YOUR-CHANNEL-WRITEAPIKEY”,“updates”:[{“delta_t”:0,“field1”:-60},
  • {“delta_t”:15,“field1”:200},{“delta_t”:15,“field1”:-66}]
    */
    // Format the data buffer as noted above
    char data[500] = “{“write_api_key”:“YOUR-CHANNEL-WRITEAPIKEY”,“updates”:”;
    // Replace YOUR-CHANNEL-WRITEAPIKEY with your ThingSpeak channel write API key

strcat(data,jsonBuffer);
strcat(data,"}");
// Close any connection before sending a new request
client.stop();
String data_length = String(strlen(data)+1); //Compute the data buffer length
Serial.println(data);
// POST data to ThingSpeak
if (client.connect(server, 80)) {
client.println(“POST /channels/YOUR-CHANNEL-ID/bulk_update.json HTTP/1.1”);
// Replace YOUR-CHANNEL-ID with your ThingSpeak channel ID

client.println(“Host: api.thingspeak.com”);
client.println(“User-Agent: mw.doc.bulk-update (Arduino ESP8266)”);
client.println(“Connection: close”);
client.println(“Content-Type: application/json”);
client.println("Content-Length: "+data_length);
client.println();
client.println(data);
}
else {
Serial.println(“Failure: Failed to connect to ThingSpeak”);
}
delay(250); //Wait to receive the response
client.parseFloat();
String resp = String(client.parseInt());
Serial.println(“Response code:”+resp);
// Print the response code. 202 indicates that the server has accepted the response
jsonBuffer[0] = ‘[’; //Reinitialize the jsonBuffer for next batch of data
jsonBuffer[1] = ‘\0’;
lastConnectionTime = millis(); //Update the last conenction time
}

/10) Define the printWiFiStatus method to print your device IP address and signal strength./

void printWiFiStatus() {
// Print the SSID of the network you’re attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());

// Print your device IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// Print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print(“signal strength (RSSI):”);
Serial.print(rssi);
Serial.println(" dBm");
}

Any help here please?