Skip to content

14. Interface and applicationn programming

Assignment Checklist.

item Activity Status
task 1 Linked to the group assignment page DONE
task 2 Documented your process DONE
task 3 Explained the UI that you made and how you did it DONE
task 4 Explained how your application communicates with your embedded microcontroller board DONE
task 5 Explained any problems you encountered and how you fixed them DONE
task 6 Included original source code (or a screenshot of the app code if that’s not possible). DONE
task 7 Included a ‘hero shot’ of your application running & communicating with your board. DONE

ABOUT MY PROJECT

I’d like to talk a little about my personal project, which is a programmable automatic irrigation device designed to work in remote, arid locations with poor soil.

This device will have a solar panel and a backup battery for autonomous operation. We adapted its microcontroller to a SEEED XIAO RP2040 board; it was previously based on an Arduino Nano, but following FabAcademy updates, we changed and adjusted it.

SOME LIMITATIONS.

The SEEED XIAO RP2040 development board doesn’t have Bluetooth or Wi-Fi connectivity, which limited me somewhat. To integrate a mobile application or web interface, I made a change to test how it might work in a future project by migrating to a SEEED XIAO ES32C3 board. This model does have Bluetooth and Wi-Fi, which makes this week’s assignment much easier.

REVIEW OF DEVELOPMENT BOARDS AND SENSORS.

SEEED XIAO ESP32C3.

This compact development board is a very good option in terms of performance, as it supports Wi-Fi 802.11 b/g/n, as well as Bluetooth 5 (BLE), extending its range with its antenna. I was able to supplement this information from the SEEEDSTUDIO WIKI website.

A very useful website.

It’s also very useful when it comes to connections or pins.

Okay, now we’re going to install the card to enable its functionalities, by copying the link (json) that’s on the same SEEED XIAO WIKI page.

Once that step is completed, we proceed to select the card

Personally, what I do is the following: - Connect the board (SEEED XIAO ESP32C3 board).

  • Search for boards with the selected COM port.

  • Enter the name XIAO ESP32C3.

And that’s how easy it is to enable the board for use with the Arduino IDE.

ESP32 DEVKIT V1

The ESP32 DEVKIT V1 development board is a very interesting model due to its variety of connection pins. It also features integrated Wi-Fi, Bluetooth, and BLE. It is used for robotics, home automation, and more.

In this case, it will be used as a connection point and interface within a wireless connection point.

There is not much complication here because the process for integrating the electronic board into ARDUINO IDE is simple.

I will also describe the output pins, although I will not be using them.

WHAT WAS DONE

A system was developed to measure soil moisture using a capacitive sensor connected to a Seeed XIAO ESP32C3, sending data via Wi-Fi to an ESP32 DevKit V1 or a web interface accessible from a laptop or any device connected to the same network.

The goal is to allow users to view real-time moisture values ​​from any device connected to the same network.

This is intended for use in a future version.

Project description.

The XIAO ESP32C3 continuously reads the analog value from the capacitive sensor. The reading (0–4095) is converted to a humidity percentage using calibration values.

As can be seen in the image, the sensor is connected to pin A0, as well as to a 3.3VDC power supply.

Programming code (XIAO ESP32C3)

The following programming code is then written for operation. This will make the XIAO function as a web server.

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

const char* WIFI_SSID = "FAB24";
const char* WIFI_PASS = "12345678";
const char* SERVER_IP = "192.168.1.50"; // <<-- IP del ESP32 DevKitV1 (servidor)
const uint16_t SERVER_PORT = 80;

#define ANALOG_PIN A0   // PIN DE SALIDA A0 (ESTA VA AL SENSOR DE HUMEDAD CAPACITIVO)
#define SAMPLES 8       // TOMA DE MUESTRAS
#define SEND_INTERVAL 3000UL

// Valores iniciales de calibración (ajusta tras medir)
int DRY = 300;
int WET = 3100;

unsigned long lastSend = 0;

int readAverage() {
  long sum = 0;
  for (int i = 0; i < SAMPLES; i++) {
    sum += analogRead(ANALOG_PIN);
    delay(5);
  }
  return (int)(sum / SAMPLES);
}

int rawToPercent(int raw) {
  int pct = map(raw, DRY, WET, 0, 100);
  if (pct < 0) pct = 0;
  if (pct > 100) pct = 100;
  return pct;
}

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("XIAO ESP32C3 - sensor capacitivo");

  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.print("Conectando a WiFi");
  unsigned long start = millis();
  while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) {
    delay(300);
    Serial.print(".");
  }
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nConectado!");
    Serial.print("IP: "); Serial.println(WiFi.localIP());
  } else {
    Serial.println("\nNo pudo conectar a WiFi (timeout)");
  }

  Serial.printf("Calibracion DRY=%d WET=%d\n", DRY, WET);
}

void loop() {
  int raw = readAverage();
  int pct = rawToPercent(raw);

  // PARA MOSTRARLO LOCALMENTE
  Serial.printf("RAW=%d  PCT=%d%%\n", raw, pct);

  // enviar al servidor cada SEND_INTERVAL
  if (millis() - lastSend >= SEND_INTERVAL) {
    lastSend = millis();
    if (WiFi.status() == WL_CONNECTED) {
      HTTPClient http;
      String url = String("http://") + SERVER_IP + ":" + String(SERVER_PORT) +
                   "/update?raw=" + String(raw) + "&pct=" + String(pct);
      http.begin(url);
      int code = http.GET();
      if (code > 0) {
        Serial.printf("ENVIADO -> %s  (resp %d)\n", url.c_str(), code);
      } else {
        Serial.printf("Error HTTP: %d\n", code);
      }
      http.end();
    } else {
      Serial.println("WiFi no conectado, no se envía");
    }
  }

  delay(200); // ESTE ES UN RETARDO QUE SE PUEDE DEFINIR CON EL "DELAY"
}

Programming code (ESP32 DEVKIT V1)

The ESP32 DevkitV1 receives data via HTTP GET, which allows the data to be displayed on an interface through a home network.

#include <WiFi.h>
#include <WebServer.h>

const char* WIFI_SSID = "FAB24";
const char* WIFI_PASS = "12345678";

WebServer server(80);

int lastRaw = -1;
int lastPct = -1;
unsigned long lastTimestamp = 0;

void handleRoot(){
  String html = "<!doctype html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'>";
  html += "<title>Humedad suel o</title>";
  html += "<style>body{font-family:Arial;text-align:center;padding:20px;} .meter{width:300px;height:26px;background:#eee;border-radius:6px;overflow:hidden;margin:10px auto} .fill{height:100%;background:linear-gradient(90deg,#2dc26b,#18a45a);width:"+ String(lastPct) + "%;}</style>";
  html += "<script>setTimeout(()=>location.reload(),3000);</script></head><body>";
  html += "<h2>📡 Monitor Humedad (capacitivo)</h2>";
  html += "<div class='meter'><div class='fill'></div></div>";
  html += "<p>Humedad estimada: <b>" + String(lastPct) + " %</b></p>";
  html += "<p>Lectura RAW: " + String(lastRaw) + "</p>";
  html += "<p>Última actualización: " + String(lastTimestamp/1000) + " s</p>";
  html += "</body></html>";
  server.send(200, "text/html", html);
}

void handleUpdate(){
  if (server.hasArg("raw") && server.hasArg("pct")) {
    lastRaw = server.arg("raw").toInt();
    lastPct = server.arg("pct").toInt();
    lastTimestamp = millis();
    server.send(200, "text/plain", "OK");
    Serial.printf("Recibido -> RAW=%d  PCT=%d\n", lastRaw, lastPct);
  } else {
    server.send(400, "text/plain", "Missing args");
  }
}

void setup(){
  Serial.begin(115200);
  delay(100);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.print("Conectando a WiFi");
  while (WiFi.status() != WL_CONNECTED) { delay(300); Serial.print("."); }
  Serial.println("\nConectado!");
  Serial.print("IP: "); Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.on("/update", handleUpdate);
  server.begin();
  Serial.println("Servidor iniciado");
}

void loop(){
  server.handleClient();
}

This allows the ESP32 to receive the data and display it on the screen with the IP address.

VIDEO

LEARNING, FINDING AND LESSONS

The lessons I can learn from this task are the following: - Correctly adding links for managing new development boards, at least from reliable sources.

  • Verifying the correct VDC power supply to the boards and sensors.

  • Declaring the code headers for what will be used, and ensuring these are included as appropriate libraries.

  • Finally, not losing patience with each trial and error test.


Last update: November 14, 2025