Skip to content
[繁]

🔧 From APIs to IoT: Letting an ESP32 Upload Its Own Data ​

After learning to ask the world questions through an API, an ESP32 can also become a source of information. Connect a DHT11 or DHT22 sensor, measure temperature and humidity, package the readings as JSON, and upload them to a cloud service such as Google Sheets.

Prove the complete route with random data first, then replace it with temperature and humidity.

🧠 Conceptual Flow ​

Sensor → ESP32 → HTTP POST → Google Apps Script → Google Sheet

The ESP32 measures temperature and humidity and packages them as JSON. Google Apps Script (GAS) acts as a bridge: the ESP32 sends JSON to its URL, and GAS writes the data into the sheet.

0. Preparation ​

  • Use a Google account and create a spreadsheet.
  • Name the worksheet tab at the bottom, not merely the spreadsheet file, ESP32_Data.
  • Add these headings to the first row: Timestamp | Device | Value | Extra. The Extra column can hold humidity later.
ESP32_Data worksheet tab

1. Create the Google Apps Script Bridge ​

In the sheet, select Extensions → Apps Script and replace the default Code.gs with:

javascript
function doPost(e) {
    try {
        const sheet = SpreadsheetApp.getActive().getSheetByName('ESP32_Data');
        const raw = e && e.postData ? e.postData.contents : '{}';
        const data = JSON.parse(raw);
        // Optional: simple token validation for a real deployment
        // if (data.token !== 'YOUR_TOKEN') return ContentService.createTextOutput('DENIED').setMimeType(ContentService.MimeType.TEXT);

        const now = new Date();
        const device = data.device || 'ESP32';
        const value = data.value;
        const extra = data.extra || '';

        sheet.appendRow([now, device, value, extra]);
        return ContentService.createTextOutput('OK').setMimeType(ContentService.MimeType.TEXT);
    } catch (err) {
        // For debugging: inspect this in Apps Script's Executions view
        console.error(err);
        return ContentService.createTextOutput('ERROR').setMimeType(ContentService.MimeType.TEXT);
    }
}

Deploy as a Web App: Required ​

  • Select Deploy → Manage deployments → New deployment.
  • Set Type to Web app.
  • Set Execute as to Me, so the script writes as you.
  • For a demonstration, set Who has access to Anyone.
  • Grant the requested permission and copy the URL ending in /exec.

After changing the script, publish the new version with New deployment or Edit deployment.

2. ESP32 Stage A: Upload Random Data to Test the Route ​

Focus on four parts: the Wi-Fi connection, target URL, JSON body and Content-Type: application/json header.

cpp
#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "YOUR_WIFI";
const char* pass = "YOUR_PASS";
const char* GAS_URL = "https://script.google.com/macros/s/XXXXXXXX/exec"; // Your /exec URL

void setup() {
    Serial.begin(115200);
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED) { delay(300); Serial.print('.');}

    HTTPClient http;
    http.begin(GAS_URL);
    http.addHeader("Content-Type", "application/json");

    String payload = String("{\"device\":\"ESP32_A1\", \"value\":") + String(random(20, 41)) + "}";
    // Random integer from 20 to 40
    int code = http.POST(payload);
    Serial.printf("HTTP %d", code);
    Serial.println(payload);
    Serial.println(http.getString());
    http.end();
}

void loop() {}

Never give your Wi-Fi password or GAS_URL to an AI service.

Success criterion: the sheet gains one row; Value contains a number from 20 to 40 and Timestamp is filled automatically.

Send once first by leaving loop() empty. Only after it works should you upload every ten seconds.

3. ESP32 Stage B: Replace Random Data with Temperature and Humidity ​

Replace only the payload construction. Keep Wi-Fi, URL and POST logic unchanged.

Key points:

  • You may use a DHT, SHT31 or similar sensor; this example uses a DHT11.
  • Install DHT sensor library by Adafruit and Adafruit Unified Sensor.
  • Consider opening a new conversation or separate file and testing the sensor by itself first.
cpp
#include <DHT.h>
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

void setup(){
    Serial.begin(115200);
    /* Wi-Fi connection and http.begin(...) omitted */
    dht.begin();
    sendOnce();
}

void loop() {}

void sendOnce(){
    float t = dht.readTemperature();
    float h = dht.readHumidity();
    // Replace random data with JSON; Extra can hold additional fields
    String payload = String("{\"device\":\"ESP32_A1\", \"value\":" ) + String(t, 1) +
    ", \"extra\": \"humi=" + String(h, 1) + "%\"}";
    // Then call http.POST(payload) as before
}

The sheet stores temperature in Value and text such as humi=65.3% in Extra. Later, you can use two distinct columns or send Value as a JSON string for GAS to split.

Initially, call sendOnce() at the end of setup() so that a bug cannot flood the endpoint. After successful testing, ask the AI to move the call into loop() and upload every ten seconds; real applications commonly use intervals from 5 to 60 seconds.

4. Frequency and Reliability ​

ItemRecommendationReason
Upload intervalAt least 10 seconds for the lesson; 5–60 seconds in a real applicationApps Script execution quotas and sheet refresh cost
Retry after failureExponential backoff: 1 s → 2 s → 4 s, capped at 60 sPrevents an endless storm of POST requests
Payload sizePreferably below 5 KBOversized JSON may trigger limits
AccessAnyone for a demo; token validation for real usePrevents unauthorised use
Approximate row limitAbout 50,000Very large sheets become slow

5. Student Task Cards ​

Task A: Test the Route with Random Data ​

  1. Paste your GAS_URL into the program.
  2. Locate http.addHeader("Content-Type", "application/json") and http.POST(payload).
  3. Check whether a new row appears in the sheet.

Task B: Replace It with Temperature and Humidity ​

  1. Change only the payload construction; preserve the device, value and extra fields.
  2. Print both the outgoing payload and returned response in Serial Monitor.
  3. If the sheet does not display the values correctly, verify that the payload is valid JSON.

6. Common Errors ​

SymptomLikely causeSolution
HTTP 405Used GET, or the URL does not end in /execUse POST and verify the /exec URL
HTTP 401/403Incorrect web-app permissionsSelect Anyone for the demo, or implement token validation
GAS execution says TypeError: e.postData is undefinedMissing Content-Type: application/jsonAdd http.addHeader(...) on the ESP32
Sheet cannot be writtenWrong worksheet name or too many formulas in the target areaConfirm ESP32_Data and write into a worksheet without formulas

💬 Further Thought ​

✅ Previously, the ESP32 asked questions about the weather or time.
✅ Now it answers a question by telling the world what it has measured.

Without necessarily noticing it, you have started building a database. What will you do with that database next?

Translation notice: This English page was generated automatically by AI and has not yet been reviewed by a human. It will be checked and revised page by page when time permits.

Last updated: