Making the ESP8266 sleep for longer than 72 minutes (sort of)

The max sleptime for the ESP8266 is limited to about 71-72 minutes. If for whatever reason you make it want to sleep longer between making contact with WiFi, or before it does other tasks, one can set a counter. So suppose one sets wishes the ESP8266 to have 4 hours of ‘sleep’, set the sleep time to 1 hour and on wake up, the only thing the ESP8266 then does is to increase a counter in RTC.
A skeleton program that can do that looks like this.:

#include <ESP8266WiFi.h>

const char* ssid = "yourSSID";
const char* password = "YourPW";

// Set the sleep time to 1 hour (in microseconds)
const uint64_t sleepTime = 1 * 60 * 60 * 1000000ULL;

// RTC memory address for the counter
int rtcCounterAddress = 0;

void setup() {
Serial.begin(115200);

// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");

// Read the counter from RTC memory
int counter = ESP.rtcUserMemoryRead(rtcCounterAddress, &counter, sizeof(counter));
Serial.printf("Counter: %d\n", counter);

// Increase the counter
counter++;

// If the counter reaches 4, reset the counter and make contact with WiFi
if (counter >= 4) {
counter = 0;
Serial.println("Making contact with WiFi...");

// Your code for making contact with WiFi goes here

// For example, you can make an HTTP request or perform any other necessary operation

} else {
Serial.println("Not yet time to make contact with WiFi");
}

// Save the updated counter to RTC memory
ESP.rtcUserMemoryWrite(rtcCounterAddress, &counter, sizeof(counter));

// Disconnect from Wi-Fi
WiFi.disconnect(true);

// Enter deep sleep mode
Serial.printf("Going to sleep for %lld microseconds\n", sleepTime);
ESP.deepSleep(sleepTime);
}

void loop() {
// Nothing to do here
}

As said, this is just a skeleton program and you can insert the activity you wish for, e.g. make contact with Internet, or perform another operation

Very DeepSleep and energy saving- Part 7: Using FRAM

This article discusses storage of sensor data (a BME280) in an FRAM MB85RC256V and only send the stored over WiFi when the 32k FRAM is full. that would save on WiFi time and thus battery life. It is a conceptual discussion as it might not save any energy on account of having to add extra hardware.

The FRAM uses about 200uA when in use and 27uA when in standby. It can store about 2048 BME280 records so that would save quite some energy on WiFi connections that do not need to be made. The catch however is that storing sensor data is only relevant if you know the time they were read, so you would need to for instance make connection to a time server to read the time, which means having to make a relatively power hungry WiFi connection, which is what we tried to avoid to begin with. So that doesn’t seem to be the best option. Nevertheless, below I will provide a program that does such:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_FRAM_I2C.h>
#include <ESP8266WiFi.h>
#include <FirebaseESP8266.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

// Replace with your Firebase credentials
#define FIREBASE_HOST "your-firebase-project-id.firebaseio.com"
#define FIREBASE_AUTH "your-firebase-auth-token"

// Replace with your Wi-Fi credentials
const char *ssid = "your-SSID";
const char *password = "your-PASSWORD";

// Define the sleep duration in seconds (4 hours)*
// max sleeptime on ESP8266 is 71 min. To make it sleep longer:
//https://arduinodiy.wordpress.com/2023/12/07/making-the-esp8266-sleep-for-longer-than-72-minutes/
const uint32_t SLEEP_DURATION = 4 * 60 * 60;

// Create an instance of the BME280 sensor
Adafruit_BME280 bme;

// Create an instance of the Adafruit FRAM library
Adafruit_FRAM_I2C fram = Adafruit_FRAM_I2C();

// Create an instance of the NTP client
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

void setup() {
Serial.begin(115200);
Wire.begin();

// Initialize Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}

// Initialize BME280 sensor
if (!bme.begin()) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}

// Initialize FRAM
if (!fram.begin()) {
Serial.println("Could not find a valid FRAM, check wiring!");
while (1);
}

// Connect to Firebase
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

void loop() {
// Get current time from NTP server
updateTime();

// Read sensor data
float temperature = bme.readTemperature();
float humidity = bme.readHumidity();
float pressure = bme.readPressure() / 100.0; // Pressure in hPa

// Store data in FRAM
writeDataToFram(timeClient.getEpochTime(), temperature, humidity, pressure);

// Check if FRAM is full
if (framUsedBytes() >= framSize()) {
// Upload data to Firebase
uploadDataToFirebase();
}

// Deep sleep
ESP.deepSleep(SLEEP_DURATION * 1e6);
}

void writeDataToFram(uint32_t timestamp, float temperature, float humidity, float pressure) {
// Calculate the number of records stored
uint16_t recordNumber = framUsedBytes() / sizeof(SensorData);

// Create a data structure to hold sensor data
SensorData data;
data.timestamp = timestamp;
data.temperature = temperature;
data.humidity = humidity;
data.pressure = pressure;

// Write data to FRAM
fram.write((uint8_t*)&data, recordNumber * sizeof(SensorData), sizeof(SensorData));
}

void uploadDataToFirebase() {
// Calculate the number of records stored
uint16_t recordNumber = framUsedBytes() / sizeof(SensorData);

// Read data from FRAM and upload to Firebase
for (uint16_t i = 0; i < recordNumber; i++) {
SensorData data;
fram.read((uint8_t*)&data, i * sizeof(SensorData), sizeof(SensorData));

// Upload data to Firebase
uploadRecordToFirebase(data);
}

// Clear FRAM
fram.erase();

Serial.println("Data uploaded to Firebase.");
}

void uploadRecordToFirebase(SensorData data) {
// Create a unique path for each record using the timestamp
String path = "/sensor_data/" + String(data.timestamp);

// Create a JSON object with the sensor data
FirebaseJson json;
json.set("timestamp", data.timestamp);
json.set("temperature", data.temperature);
json.set("humidity", data.humidity);
json.set("pressure", data.pressure);

// Upload data to Firebase
Firebase.set(path, json);
}

// Function to get the used bytes in FRAM
uint16_t framUsedBytes() {
uint16_t address = 0;
while (fram.read8(address) == 0xFF && address < framSize()) {
address++;
}
return address;
}

// Function to get the size of FRAM
uint16_t framSize() {
return fram.size();
}

// Data structure to hold sensor data
struct SensorData {
uint32_t timestamp;
float temperature;
float humidity;
float pressure;
};

Another possibility is to avoid the timeserver and to use an RTC such as the DS3231. At 3.6 Volt it uses 200uA when active and 110uA when not active. The Vcc range is +2.3 to +5.5Volt so at 3 Volt it will likely use a bit less. A program could look something like this:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <RTClib.h> // Library for DS3231 RTC
#include <Adafruit_FRAM_I2C.h>
#include <ESP8266WiFi.h>
#include <FirebaseESP8266.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

// Replace with your Firebase credentials
#define FIREBASE_HOST "your-firebase-project-id.firebaseio.com"
#define FIREBASE_AUTH "your-firebase-auth-token"

// Replace with your Wi-Fi credentials
const char *ssid = "your-SSID";
const char *password = "your-PASSWORD";

// Define the sleep duration in seconds (4 hours) Max sleep time is 72 min
// to make it sleep longer, check:
//https://arduinodiy.wordpress.com/2023/12/07/making-the-esp8266-sleep-for-longer-than-72-minutes/
const uint32_t SLEEP_DURATION = 4 * 60 * 60;

// Create an instance of the BME280 sensor
Adafruit_BME280 bme;

// Create an instance of the Adafruit FRAM library
Adafruit_FRAM_I2C fram = Adafruit_FRAM_I2C();

// Create an instance of the RTClib library for DS3231
RTC_DS3231 rtc;

// Create an instance of the NTP client
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");

void setup() {
Serial.begin(115200);
Wire.begin();

// Initialize Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}

// Initialize BME280 sensor
if (!bme.begin()) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}

// Initialize DS3231 RTC
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}

// Initialize FRAM
if (!fram.begin()) {
Serial.println("Could not find a valid FRAM, check wiring!");
while (1);
}

// Connect to Firebase
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

void loop() {
// Get current time from DS3231 RTC
DateTime now = rtc.now();

// Read sensor data
float temperature = bme.readTemperature();
float humidity = bme.readHumidity();
float pressure = bme.readPressure() / 100.0; // Pressure in hPa

// Store data in FRAM
writeDataToFram(now.unixtime(), temperature, humidity, pressure);

// Check if FRAM is full
if (framUsedBytes() >= framSize()) {
// Upload data to Firebase
uploadDataToFirebase();
}

// Deep sleep
ESP.deepSleep(SLEEP_DURATION * 1e6);
}

void writeDataToFram(uint32_t timestamp, float temperature, float humidity, float pressure) {
// Calculate the number of records stored
uint16_t recordNumber = framUsedBytes() / sizeof(SensorData);

// Create a data structure to hold sensor data
SensorData data;
data.timestamp = timestamp;
data.temperature = temperature;
data.humidity = humidity;
data.pressure = pressure;

// Write data to FRAM
fram.write((uint8_t*)&data, recordNumber * sizeof(SensorData), sizeof(SensorData));
}

void uploadDataToFirebase() {
// Calculate the number of records stored
uint16_t recordNumber = framUsedBytes() / sizeof(SensorData);

// Read data from FRAM and upload to Firebase
for (uint16_t i = 0; i < recordNumber; i++) {
SensorData data;
fram.read((uint8_t*)&data, i * sizeof(SensorData), sizeof(SensorData));

// Upload data to Firebase
uploadRecordToFirebase(data);
}

// Clear FRAM
fram.erase();

Serial.println("Data uploaded to Firebase.");
}

void uploadRecordToFirebase(SensorData data) {
// Create a unique path for each record using the timestamp
String path = "/sensor_data/" + String(data.timestamp);

// Create a JSON object with the sensor data
FirebaseJson json;
json.set("timestamp", data.timestamp);
json.set("temperature", data.temperature);
json.set("humidity", data.humidity);
json.set("pressure", data.pressure);

// Upload data to Firebase
Firebase.set(path, json);
}

// Function to get the used bytes in FRAM
uint16_t framUsedBytes() {
uint16_t address = 0;
while (fram.read8(address) == 0xFF && address < framSize()) {
address++;
}
return address;
}

// Function to get the size of FRAM
uint16_t framSize() {
return fram.size();
}

// Data structure to hold sensor data
struct SensorData {
uint32_t timestamp;
float temperature;
float humidity;
float pressure;
};

Mind you though that the two programs above are not as foolproof as they could be. The position to write a new record to after a wake up, is determined by the function ‘framUsedBytes()’. This function simply looks for code 0xFF that is stored in memory that is unused or after a clean up. It is also possible to store a recordnumber , either in the FRAM or in the ESP8266 NVRAM and retrieve that after a wake up and calculate the new position

Is it useful?
I think instinctively one can already say that having the ESP8266 make contact with a time server every to get the time, but not send the data yet, doesnt seem to make much sense.
That leaves the option with the RTC: So if the RTC is using <100uA in rest and the FRAM 27uA (lets say the total is 120uA) extra for 4 hrs in order to save ca 300mA for a short burst (say 2 secs), that is 480uAh vs 600mAs = 480uAh vs 0.167 mAh= 480uAh vs 167uAh. And this did not even include the extra energy used during the active phase of the added hardware.
That hardly seems to make sense from a battery saving point of view, it could be an interesting option though if no internet is around and one brings the device to an available internet from time to time

So what can we do
in order to make this more energy efficient (and thus useful) there are possibilities: Commenter Craig Larson describes a system he had on a pro mini in which a counter was indexed to work out the time.
it is also possible to use the internal clock of the ESP8266 and or store millis(), but that is all not very secure/accurate.
So, let’s try something that is a bit akin to what Craig did on the pro-mini (that had an ESP attached to it):
We only attach the FRAM memory to the ESP8266, no RTC.
On it’s start, we let the ESP8266 contact a time server only once and store that time in FRAM.
We then let the ESP8266 read the BME and store the values in FRAM with a recordnumber of ‘0’ attached to it. Then go to sleep for 4 hours.
On wake up, we do not read the time server again, but immediately read the BME280 and store the values as a new record, but now with the previous recordnumber increased by ‘1’.
Then when the FRAM is full (based on calculating the amount of records multiplied with the length of the records) the records are sent off to Firebase, but before sending, the recordnumber is replaced by the originally stored time from the server (which is in Unix format) and then 4 hours, multiplied by the recordnumber, is added to it.

Such a program should look something like this:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <MB85RC256V.h>

#define BME_SDA D2
#define BME_SCL D1

MB85RC256V fram;
Adafruit_BME280 bme;

const char* ssid = "your-ssid";
const char* password = "your-password";

const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 0; // Your timezone offset in seconds
const int daylightOffset_sec = 0; // Daylight saving time offset in seconds

void connectWiFi() {
Serial.println("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
}

void sendToFirebase(int recordNumber, float temperature, float humidity, float pressure, time_t timestamp) {
// Implement Firebase data sending logic here
// Use the Firebase API or library of your choice
// Include the necessary headers and set up the connection
// Send the data to Firebase with the adjusted timestamp
}

void setup() {
//Serial.begin(115200);
Wire.begin(BME_SDA, BME_SCL);

if (!bme.begin()) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}

fram.begin();

if (!fram.begin()) {
//Serial.println("Could not find a valid FRAM chip, check wiring!");
while (1);
}

int recordNumber = fram.read(0);
if (recordNumber == -1) {
// First start, contact NTP server
connectWiFi();
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, ntpServer, gmtOffset_sec, daylightOffset_sec);
timeClient.begin();
time_t currentTime = timeClient.getEpochTime();
timeClient.end();
fram.write(0, currentTime);

// Read BME280 and store the initial record
float temperature = bme.readTemperature();
float humidity = bme.readHumidity();
float pressure = bme.readPressure() / 100.0F; // Convert Pa to hPa

fram.write(4, recordNumber);
fram.writeFloat(8, temperature);
fram.writeFloat(12, humidity);
fram.writeFloat(16, pressure);

Serial.println("Initial record stored.");
}

// Enter deep sleep for 4 hours
//Serial.println("Going to sleep for 4 hours");// See Note *
ESP.deepSleep(4 * 60 * 60 * 1000000);
}

void loop() {
// This part won't be executed as the ESP8266 is in deep sleep
}

void wakeUpAndSendData() {
// Waking up from deep sleep
connectWiFi();

int recordNumber = fram.read(4);
recordNumber++;

float temperature = bme.readTemperature();
float humidity = bme.readHumidity();
float pressure = bme.readPressure() / 100.0F; // Convert Pa to hPa

fram.write(4, recordNumber);
fram.writeFloat(8 + recordNumber * 16, temperature);
fram.writeFloat(12 + recordNumber * 16, humidity);
fram.writeFloat(16 + recordNumber * 16, pressure);

//Serial.println("Data recorded.");

if (recordNumber * 4 * 60 * 60 >= fram.capacity()) {
// FRAM memory full, send data to Firebase
time_t initialTime = fram.read(0);
for (int i = 0; i <= recordNumber; i++) {
float temp = fram.readFloat(8 + i * 16);
float hum = fram.readFloat(12 + i * 16);
float pres = fram.readFloat(16 + i * 16);

time_t timestamp = initialTime + i * 4 * 60 * 60;
sendToFirebase(i, temp, hum, pres, timestamp);
}

// Serial.println("Data sent to Firebase.");

// Clear FRAM memory after sending data
fram.format();
}

// Enter deep sleep for 4 hours
//Serial.println("Going to sleep for 4 hours");
ESP.deepSleep(4 * 60 * 60 * 1000000);// This is a simplification. See the note below
}

This program assumes you have a routine called ‘sendToFirebase()’ which may be different for various people (e.g. you may want to use the firebase library or not), or you may want to send it to another database (e.g. SQL or maybe just googlesheet).

So is the continuous use of 27uA worth the savings? 27uh over 4 hrs is 108uAh vs 167uAh, so roughly speaking one would save 60uAh. The downside is that you would have to wait long for the data. As the FRAM will be able to store some 2048 records, in which 6 records form a day, it will take 341 days before the data is sent. That may be a downside, but in some instances it might be an upside :-).

There are caveats with this program. What if the power suddenly fails? you may find your data over written. So you would have to build in some safeguards:
One could have the program on initial start check if there already is a valid unix date in the FRAM and then check till howfar the FRAM is already filled (going by the fact an empty memory is usually filled with 0xFF) and then take it from there.

Another option would be to use the MB85RS64V FRAM chip, as that uses only 10uA in standby. I’s memory capacity is only 8kByte so you would only be able to store 85 days of data, so your energy savings in the long run would be less, but you would have your data sooner.

Whether it is worth doing it is up to you.

* the max sleeptime on the ESP8266 is 72 minutes.(although some will still work with 3 hrs sleep time, but will have a drift). To make it sleep for 4 hrs, look here: https://arduinodiy.wordpress.com/2023/12/07/making-the-esp8266-sleep-for-longer-than-72-minutes/

Sending sensor data to Googlesheets

In the past I have written an article on sending data to google sheet , without a third party service such as IFTTT. As it has been a while ago, It is time for an update of that article.
Suppose we have a google sheet with 4 columns:
date, temperature, humidity and pressure.

and you want it to store data that you send there with an esp8266.
-Open the specific googlesheet
-Check the url.
this will look something like https://docs.google.com/spreadsheets/d/12aCZVLKlgO1Fy18hnC7eb49dhY8Tu3P6qUe6j9-5j8o/edit#gid=0
make note of that long number (12aCZ……5j8o) as you will need it soon.
We now will make a script that will serve as an endpoint for an https request and that will store the presented data in the spread sheetsheet.
In order to make the script, do de following:
While in the sheet, go to ‘Extensions-App Scripts’
an Editor will open up. Now paste in the following code:

var sheet_id = "12aCZVLKlgO1Fy18hnC7eb49dhY8Tu3P6qUe6j9-5j8o";
var sheet_name = "Sheet1";
function doGet(e){
var ss = SpreadsheetApp.openById(sheet_id);
var sheet = ss.getSheetByName(sheet_name);
// Parse the date parameter as a string
var dateString = e.parameter.date;

// Convert the date string to a JavaScript Date object
var date = new Date(dateString);
var temperature = Number(e.parameter.temperature);
var humidity= Number(e.parameter.humidity)
var pressure= Number (e.parameter.pressure)
var formattedDate = Utilities.formatDate(date, "GMT", "yyyy-MM-dd HH:mm:ss");
sheet.appendRow([date,temperature,humidity,pressure]);
}

Where of course you have to replace the number “12aCZVLKlgO1Fy18hnC7eb49dhY8Tu3P6qUe6j9-5j8o” with the ID number of your spreadsheet that i referred to earlier.
When you have done that, click on the ‘Deploy’ button. this will give you yet another number, that you can consider as the ‘API’ for your script. You will also get a preformatted https request with that API already inserted.
It may look like this:
https://script.google.com/macros/s/AKfycbxxxxxxxxxxxxxx/exec

Now it is time for an ESP8266 program.
Given the fact our GoogleSheet has ‘temperature, humidity and pressure,it would fit to use an BME280 as sensor, but to keep the program simple, I will just assign some arbitrary values to these parameters. and you can add code for any sensor you like

We could use the following program

#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#endif
#include <WiFiClientSecure.h>
#include <Wire.h>

const char* ssid = "Your_SSID"; //--> Your wifi name or SSID.
const char* password = "Your_PW"; //--> Your wifi password.
const char* host = "script.google.com";
const int httpsPort = 443;
//----------------------------------------

WiFiClientSecure client;

String GAS_ID = "AKfycxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBXdZQSl"; //--> spreadsheet script ID


String datum = ("2023-12-02T12:30:10");//your date-time needs to be formatted like this
float temperature;
int humidity;
float pressure;

void setup() {

Serial.begin(115200);
delay(500);
WiFi.begin(ssid, password); //--> Connect to your WiFi router
Serial.println("");
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(250);
}
Serial.println("");
Serial.print("Successfully connected to : ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.println();
//----------------------------------------
client.setInsecure();
}

void loop() {
humidity = random(50, 60);
temperature = (random(-6,6)*10-random(9))/10.0;
pressure = 1000.0+random(-15,15);
sendData(datum, temperature, humidity, pressure);

delay(60000); //not an elegant method, but fine for testing
}


void sendData(String d, float t, int h, float p) {
Serial.print("connecting to ");
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
}

String string_temperature = String(t, 2);
String string_humidity = String(h);
String string_pressure = String(p, 0);
Serial.println(string_temperature);
Serial.println(string_humidity);
Serial.println(string_pressure);

String url = "/macros/s/" + GAS_ID + "/exec?date=" + datum + "&temperature=" + string_temperature + "&humidity=" + string_humidity + "&pressure=" + string_pressure;
Serial.print("requesting URL: ");
Serial.println(url);

client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: BuildFailureDetectorESP32 \r\n" +
"Connection: close\r\n\r\n");

Serial.println("request sent");

while (client.connected()) {
String line = client.readStringUntil('\n');
if (line == "\r") {
Serial.println("headers received");
break;
}
}
String line = client.readStringUntil('\n');
Serial.println(line);

Serial.print("reply was : ");
Serial.println(line);
Serial.println("closing connection");
Serial.println();
}

It is a rather standard program except for that it uses the WiFiClientSecure library rather than the WiFi library. That is necessary for the https connection to Google. However, to avoid problems with fingerprinting, BearSSLand SSL certificates, the client is later set to “insecure” with the statement client.setInsecure();

The program alludes to using a ‘date’ variable, which is not uncustomary when storing data.
Dates can come from an RTC or from internet time, e.g. with the NTPClient library. Coming from an RTC, the time is usually delivered as a date-time in string form. It is important to format such a date according to a universally accepted format, which is given in the program. This comes down to putting a capital “T” in between the date and the time parameters.
Time pulled from the internet, usually is delivered in Unix format. Unix time is the number of Seconds since Jan 01 1970. For this exact moment that I write this, the Unix time is 17001602004..
If you use Unix time in your program and want to send that to Google Sheets, then you can do that just as well, by inserting that as the time parameter in the request string…but you need to make some changes to the javascript program in the Googlesheet.

var sheet_id = "1OCZVLMlgO1Fy17hbC6pWNnN19ggtre-3i2I";
var sheet_name = "Sheet";

function doGet(e){
var ss = SpreadsheetApp.openById(sheet_id);
var sheet = ss.getSheetByName(sheet_name);

// Convert the Unix timestamp to milliseconds
var timestamp = Number(e.parameter.date);
var date = new Date(timestamp);

var temperature = Number(e.parameter.temperature);
var humidity = Number(e.parameter.humidity);
var pressure = Number(e.parameter.pressure);

// Format the date as a string (adjust the format as needed)
var formattedDate = Utilities.formatDate(date, "GMT", "yyyy-MM-dd HH:mm:ss");

// Append the row with the formatted date
sheet.appendRow([formattedDate, temperature, humidity, pressure]);
}

Again, make sure that you put in your own sheet_ID (the long number in the url of your Googlesheet). Don’t forget to “deploy” any changes in the application script.

There is another way to send data to google sheets, other than through a third party like IFTTT, and that is through the Google API. I may write an article about that in the future.