Get started with TRIOE through these 5 foundational projects covering LED control, WiFi, web servers, and more.
Note: Replace WIFI_SSID and WIFI_PASS with your actual TRIOE board settings.
These codes are also available in the TRIOE Web IDE, including all Starter Kit projects.
What this teaches: Uploading code, setup() vs loop(), digital output.
// TRIOE - Project 1: Basic LED Blink
const int LED_PIN = 2; // 🔴 Change to your TRIOE onboard LED pin
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
delay(500); // 500 ms ON
digitalWrite(LED_PIN, LOW);
delay(500); // 500 ms OFF
}What this teaches: ESP32 as web server, HTTP, basic HTML UI.
// TRIOE - Project 3: Web Server LED Control (WiFi STA)
#include <WiFi.h>
#include <WebServer.h>
const char* WIFI_SSID = "YOUR_WIFI_SSID"; // 🔴
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD"; // 🔴
const int LED_PIN = 2; // 🔴 TRIOE onboard LED
WebServer server(80);
String htmlPage(bool ledState) {
String btnLabelOn = ledState ? "LED is ON" : "Turn LED ON";
String btnLabelOff = ledState ? "Turn LED OFF" : "LED is OFF";
String html = "<!DOCTYPE html><html><head>"
"<meta name='viewport' content='width=device-width, initial-scale=1'/>"
"<title>TRIOE LED Control</title></head><body>"
"<h2>TRIOE Board - LED Control</h2>";
html += "<p>LED State: " + String(ledState ? "ON" : "OFF") + "</p>";
html += "<a href='/on'><button>" + btnLabelOn + "</button></a>";
html += " ";
html += "<a href='/off'><button>" + btnLabelOff + "</button></a>";
html += "</body></html>";
return html;
}
void handleRoot() {
bool state = digitalRead(LED_PIN);
server.send(200, "text/html", htmlPage(state));
}
void handleOn() {
digitalWrite(LED_PIN, HIGH);
handleRoot();
}
void handleOff() {
digitalWrite(LED_PIN, LOW);
handleRoot();
}
void setup() {
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Serial.begin(115200);
delay(1000);
Serial.println("\nConnecting to WiFi...");
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on("/", handleRoot);
server.on("/on", handleOn);
server.on("/off", handleOff);
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
}What this teaches: RF environment, RSSI, channels.
// TRIOE - Project 5: WiFi Scanner
#include <WiFi.h>
void setup() {
Serial.begin(115200);
delay(1000);
WiFi.mode(WIFI_STA);
WiFi.disconnect(); // Just scanning, not connecting
delay(100);
Serial.println("TRIOE WiFi Scanner");
}
void loop() {
Serial.println("\nScanning...");
int n = WiFi.scanNetworks();
if (n == 0) {
Serial.println("No networks found");
} else {
Serial.printf("%d networks found:\n", n);
for (int i = 0; i < n; ++i) {
Serial.printf("%2d: %s (RSSI: %d dBm, CH: %d) %s\n",
i + 1,
WiFi.SSID(i).c_str(),
WiFi.RSSI(i),
WiFi.channel(i),
(WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? "OPEN" : "SECURED"
);
}
}
// Wait 5 seconds before next scan
delay(5000);
}What this teaches: SoftAP mode, fully offline IoE dashboard.
// TRIOE - Project 8: SoftAP Web Portal for LED Control
#include <WiFi.h>
#include <WebServer.h>
const char* AP_SSID = "TRIOE-BOARD"; // 🔴 Change if you like
const char* AP_PASS = "12345678"; // 🔴 Min 8 chars
const int LED_PIN = 2; // 🔴 TRIOE onboard LED
WebServer server(80);
String htmlPage(bool ledState) {
String html = "<!DOCTYPE html><html><head>"
"<meta name='viewport' content='width=device-width, initial-scale=1'/>"
"<title>TRIOE Local Control</title></head><body>"
"<h2>TRIOE Offline LED Control</h2>";
html += "<p>Connect to WiFi SSID: <b>TRIOE-BOARD</b></p>";
html += "<p>LED State: " + String(ledState ? "ON" : "OFF") + "</p>";
html += "<a href='/on'><button>Turn ON</button></a> ";
html += "<a href='/off'><button>Turn OFF</button></a>";
html += "</body></html>";
return html;
}
void handleRoot() {
bool state = digitalRead(LED_PIN);
server.send(200, "text/html", htmlPage(state));
}
void handleOn() {
digitalWrite(LED_PIN, HIGH);
handleRoot();
}
void handleOff() {
digitalWrite(LED_PIN, LOW);
handleRoot();
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
Serial.println("Starting TRIOE SoftAP...");
WiFi.mode(WIFI_AP);
bool result = WiFi.softAP(AP_SSID, AP_PASS);
if (result) {
Serial.println("SoftAP started");
Serial.print("AP IP address: ");
Serial.println(WiFi.softAPIP());
} else {
Serial.println("SoftAP failed!");
}
server.on("/", handleRoot);
server.on("/on", handleOn);
server.on("/off", handleOff);
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
}What this teaches: Layer 2 packets, MAC addresses, RSSI.
// TRIOE - Project 11: Simple WiFi Sniffer (Promiscuous Mode)
#include <WiFi.h>
#include "esp_wifi.h"
typedef struct {
uint8_t mac[6];
} wifi_mac_t;
// Raw WiFi packet header (simplified)
typedef struct {
uint16_t frame_ctrl;
uint16_t duration_id;
uint8_t addr1[6];
uint8_t addr2[6];
uint8_t addr3[6];
uint16_t sequence_ctrl;
} wifi_header_t;
void snifferCallback(void* buff, wifi_promiscuous_pkt_type_t type) {
wifi_promiscuous_pkt_t* pkt = (wifi_promiscuous_pkt_t*)buff;
wifi_header_t* hdr = (wifi_header_t*)pkt->payload;
int rssi = pkt->rx_ctrl.rssi;
// Source MAC is in addr2
uint8_t* mac = hdr->addr2;
Serial.printf("Packet RSSI: %d dBm, SRC MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
rssi,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("TRIOE WiFi Sniffer - PROMISCUOUS MODE");
WiFi.mode(WIFI_MODE_NULL); // Stop normal WiFi
esp_wifi_set_promiscuous(true);
esp_wifi_set_promiscuous_filter(NULL);
esp_wifi_set_promiscuous_rx_cb(&snifferCallback);
}
void loop() {
// Nothing here; packets handled in callback
}⚠️ Important: Project 5 (WiFi Sniffer) is for educational and demonstration purposes only. Please remind students about ethical use of network monitoring tools.