The most common ways to transmit data are CSV (Comma-Separated Values) and JSON.
CSV
Best used when data will be processed later in tools like Excel or similar spreadsheet applications.
Each row represents a record, and commas separate individual values.
JSON
A more advanced format.
Represents data as key-value pairs (variable: value), making it easier to work with in programming environments.
Supports nested structures, arrays, and objects, providing flexibility for complex datasets.
JSON Objects
A JSON object is a collection of key-value pairs, where each key is a string and each value can be a number, string, boolean, array, or even another object.
Examples
Simple object:
myJSON = {"name": "John", "age": 31, "city": "New York"}
Object with an array:
myJSON = {"data": [100, 20, 34, 120], "name": "Voltage"}
More complex object with multiple types:
myJSON = {"Name": "circuits", "Data": 45, "DataSet": [3, 4, 56, 2, 2, 56], "check": true}
Notes
- Viewing JSON: Tools like JSON Formatter & Viewer make it easy to read and debug JSON files.
- Usage: JSON is widely used for data exchange. Both Arduino and Processing support parsing and generating JSON objects.
When to Use Which Format
- Use JSON when your data has multiple types, nested structures, or arrays.
- Use CSV for simpler tabular data.
Example: JSON Web Server
Here's a complete example that creates a web server that serves JSON data:
#include <ESP8266WiFi.h> // WiFi library for ESP8266
#include <ESP8266WebServer.h> // Web server library
#include <ArduinoJson.h> // JSON handling library
// WiFi credentials
#define SSID "aalto open" // WiFi network name
#define PASSWORD "" // Open network, no password
ESP8266WebServer server(80); // Create a web server on port 80
// Function to send JSON data
void sendData() {
// Create a static JSON document with 300 bytes of memory
StaticJsonDocument<300> JSONData;
// Add key-value pairs
JSONData["key"] = "Value"; // Example static key
JSONData["number"] = String(random(100)); // Random number as string
char data[300]; // Buffer to store serialized JSON
serializeJson(JSONData, data); // Convert JSON object to string
// Send JSON response to client
// Access in browser: http://<ESP_IP>/test
server.send(200, "application/json", data);
}
void setup() {
Serial.begin(115200); // Initialize serial monitor
Serial.println();
// Connect to WiFi
WiFi.begin(SSID, PASSWORD);
Serial.print("Connecting to WiFi");
// Wait until connected
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.println("\nConnected!");
Serial.print("ESP IP address: ");
Serial.println(WiFi.localIP()); // Print ESP IP address for browser access
// Define HTTP route "/test" to send JSON
server.on("/test", HTTP_GET, sendData);
// Start web server
server.begin();
Serial.println("Server started. Access /test in your browser");
}
void loop() {
// Handle incoming HTTP requests
server.handleClient();
}
How to test:
- Upload the code to your ESP8266
- Check the Serial Monitor for the IP address
- Open your browser and go to:
http://[ESP_IP]/test
- You should see JSON data like:
{"key":"Value","number":"42"}
Here's how to connect to the JSON server using Processing:
import http.requests.*; // Import HTTP requests library for Processing
public void setup() {
size(400, 400);
// Create a GET request to the ESP8266 JSON server
// Replace the IP below with your ESP8266's IP
// Example: http://192.168.4.1/test if using aalto open
GetRequest get = new GetRequest("http://192.168.4.1/test");
get.send(); // Send the request and wait until completed
// Print the raw response from the ESP
println("response: " + get.getContent());
// Parse the JSON content
JSONObject response = parseJSONObject(get.getContent());
// Extract and print the "number" value from the JSON
println("number: " + response.getString("number"));
}
Note: You need to install the "HTTP Requests for Processing" library in Processing IDE before using this code.
MQTT Communication
MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol perfect for IoT devices.
It works on a publish/subscribe model where devices can send (publish) messages to topics and receive (subscribe) messages from topics through a central broker.
MQTT Broker: Shiftr.io
We'll use Shiftr.io as our MQTT broker. It's free and easy to use.
Public test broker credentials:
- Broker:
public.cloud.shiftr.io
- Username:
public
- Password:
public
- WebSocket Port:
443 (for web browsers)
- MQTT Port:
1883 (for ESP8266/Processing)
- đ¤ Web sends to:
test/web
- đ¤ ESP8266 sends to:
test/esp8266
- đ¤ Processing sends to:
test/processing
- đĨ Everyone subscribes to:
test/# (wildcard - receives all)
This web-based client connects to MQTT broker and can send/receive messages.
Library: MQTT.js loaded from CDN (no installation needed)
Note: This is a complete working example you can save as an HTML file and open in your browser.
<!DOCTYPE html>
<html>
<head>
<title>MQTT Web Client</title>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
background: #f0f0f0;
max-width: 600px;
margin: 0 auto;
}
.container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
input {
width: 100%;
padding: 10px;
margin: 5px 0;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
button {
padding: 10px 20px;
background: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin: 5px 5px 5px 0;
}
button:hover { background: #45a049; }
button:disabled { background: #ccc; cursor: not-allowed; }
#disconnectBtn { background: #f44336; }
#disconnectBtn:hover { background: #da190b; }
#sendBtn { background: #2196F3; }
#sendBtn:hover { background: #0b7dda; }
.status {
padding: 10px;
margin: 10px 0;
border-radius: 4px;
font-weight: bold;
}
.connected { background: #d4edda; color: #155724; }
.disconnected { background: #f8d7da; color: #721c24; }
.log {
background: #1e1e1e;
color: #4CAF50;
padding: 10px;
margin: 10px 0;
border-radius: 4px;
font-family: monospace;
font-size: 12px;
max-height: 300px;
overflow-y: auto;
}
</style>
</head>
<body>
<div class="container">
<h1>MQTT Web Client</h1>
<div id="status" class="status disconnected">Disconnected</div>
<h3>Connection</h3>
<button id="connectBtn" onclick="connectMQTT()">Connect MQTT</button>
<button id="disconnectBtn" onclick="disconnectMQTT()" disabled>Disconnect</button>
<h3>Send Message</h3>
<input type="text" id="field1Name" placeholder="Field 1 name" value="speed">
<input type="text" id="field1Value" placeholder="Field 1 value" value="100">
<input type="text" id="field2Name" placeholder="Field 2 name" value="direction">
<input type="text" id="field2Value" placeholder="Field 2 value" value="forward">
<button id="sendBtn" onclick="sendMessage()" disabled>Send Message</button>
<h3>Message Log</h3>
<div id="log" class="log">Click "Connect MQTT" to start...</div>
</div>
<script>
let client = null;
function connectMQTT() {
if (client && client.connected) {
addLog('â ī¸ Already connected');
return;
}
document.getElementById('status').textContent = 'Connecting...';
document.getElementById('status').className = 'status';
client = mqtt.connect('wss://public:public@public.cloud.shiftr.io');
client.on('connect', () => {
addLog('â
Connected to MQTT broker');
document.getElementById('status').textContent = 'Connected â
';
document.getElementById('status').className = 'status connected';
document.getElementById('connectBtn').disabled = true;
document.getElementById('disconnectBtn').disabled = false;
document.getElementById('sendBtn').disabled = false;
// Subscribe to all test messages
client.subscribe('test/#');
addLog('đĨ Subscribed to test/#');
});
client.on('message', (topic, message) => {
const data = message.toString();
addLog('đ¨ [' + topic + ']: ' + data);
});
client.on('error', (err) => {
addLog('â Error: ' + err.message);
document.getElementById('status').textContent = 'Error â';
document.getElementById('status').className = 'status disconnected';
});
client.on('close', () => {
addLog('đ Connection closed');
document.getElementById('status').textContent = 'Disconnected';
document.getElementById('status').className = 'status disconnected';
document.getElementById('connectBtn').disabled = false;
document.getElementById('disconnectBtn').disabled = true;
document.getElementById('sendBtn').disabled = true;
});
}
function disconnectMQTT() {
if (client) {
client.end();
client = null;
addLog('đ Disconnected from MQTT broker');
}
}
function sendMessage() {
if (!client || !client.connected) {
alert('Not connected! Click "Connect MQTT" first.');
return;
}
const name1 = document.getElementById('field1Name').value;
const value1 = document.getElementById('field1Value').value;
const name2 = document.getElementById('field2Name').value;
const value2 = document.getElementById('field2Value').value;
const message = {
source: 'web',
[name1]: value1,
[name2]: value2,
timestamp: Date.now()
};
const jsonMessage = JSON.stringify(message);
client.publish('test/web', jsonMessage);
addLog('đ¤ Sent to test/web: ' + jsonMessage);
}
function addLog(message) {
const log = document.getElementById('log');
const timestamp = new Date().toLocaleTimeString();
log.innerHTML = timestamp + ' ' + message + '<br>' + log.innerHTML;
}
// Disconnect when page is closed
window.addEventListener('beforeunload', () => {
if (client && client.connected) {
disconnectMQTT();
}
});
</script>
</body>
</html>
Required library: Install "PubSubClient" by Nick O'Leary from Arduino Library Manager
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// WiFi credentials
const char* ssid = "aalto open";
const char* password = "";
// MQTT Broker settings
const char* mqtt_server = "public.cloud.shiftr.io";
const int mqtt_port = 1883;
const char* mqtt_user = "public";
const char* mqtt_pass = "public";
WiFiClient espClient;
PubSubClient client(espClient);
int counter = 0;
unsigned long lastSend = 0;
void setup() {
Serial.begin(115200);
// Connect to WiFi
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Setup MQTT
client.setServer(mqtt_server, mqtt_port);
client.setCallback(messageReceived);
// Connect to MQTT
connectMQTT();
}
void loop() {
// Maintain MQTT connection
if (!client.connected()) {
connectMQTT();
}
client.loop();
// Send message every second to ESP8266 topic
if (millis() - lastSend > 1000) {
lastSend = millis();
sendMessage();
}
}
void connectMQTT() {
while (!client.connected()) {
Serial.print("Connecting to MQTT...");
// Create unique client ID
String clientId = "ESP8266_";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str(), mqtt_user, mqtt_pass)) {
Serial.println("Connected!");
// Subscribe to all test topics
client.subscribe("test/#");
Serial.println("Subscribed to test/#");
// Send hello message
client.publish("test/esp8266", "{\"source\":\"esp8266\",\"status\":\"online\"}");
} else {
Serial.print("Failed, rc=");
Serial.print(client.state());
Serial.println(" Retrying in 5 seconds...");
delay(5000);
}
}
}
void sendMessage() {
// Create JSON message
String msg = "{\"source\":\"esp8266\",\"counter\":" + String(counter) + ",\"millis\":" + String(millis()) + "}";
// Publish to ESP8266 topic
if (client.publish("test/esp8266", msg.c_str())) {
Serial.print("Sent: ");
Serial.println(msg);
counter++;
} else {
Serial.println("Failed to send!");
}
}
void messageReceived(char* topic, byte* payload, unsigned int length) {
// Convert payload to string
String message = "";
for (unsigned int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("Received from ");
Serial.print(topic);
Serial.print(": ");
Serial.println(message);
}
Required library: Install "MQTT" library from Processing's Library Manager (Sketch â Import Library â Add Library)
import mqtt.*;
MQTTClient client;
int counter = 0;
int lastSend = 0;
String lastMessage = "";
void setup() {
size(500, 400);
textAlign(LEFT, TOP);
// Connect to MQTT broker
client = new MQTTClient(this);
client.connect("mqtt://public:public@public.cloud.shiftr.io", "processing_" + hex(int(random(0xffff))));
// Subscribe to all test topics
client.subscribe("test/#");
println("Connected to MQTT broker");
println("Subscribed to test/#");
// Send hello message
client.publish("test/processing", "{\"source\":\"processing\",\"status\":\"online\"}");
}
void draw() {
background(30);
fill(255);
// Display connection status
textSize(16);
text("MQTT Communication Demo", 20, 20);
if (client.connected()) {
fill(0, 255, 0);
text("Status: Connected â", 20, 50);
} else {
fill(255, 0, 0);
text("Status: Disconnected â", 20, 50);
}
// Display counter
fill(255);
textSize(14);
text("Counter: " + counter, 20, 80);
text("Sending to: test/processing", 20, 105);
// Display last received message
fill(100, 200, 255);
text("Last received:", 20, 140);
fill(255, 255, 100);
textSize(12);
text(lastMessage, 20, 165, width - 40, 200);
// Instructions
fill(150);
textSize(11);
text("Messages are sent every second", 20, height - 60);
text("Open web page and ESP8266 to see all communicate!", 20, height - 40);
text("Check shiftr.io/try to visualize the network", 20, height - 20);
// Send message every second (60 frames at 60fps = 1 second)
if (millis() - lastSend > 1000) {
lastSend = millis();
sendMessage();
}
}
void sendMessage() {
// Create JSON message
String json = "{" +
"\"source\":\"processing\"," +
"\"counter\":" + counter + "," +
"\"millis\":" + millis() +
"}";
// Publish to Processing topic
client.publish("test/processing", json);
println("Sent: " + json);
counter++;
}
// Callback for received messages
void messageReceived(String topic, byte[] payload) {
String message = new String(payload);
println("Received from " + topic + ": " + message);
// Update display
lastMessage = "[" + topic + "]\n" + message;
}
void clientConnected() {
println("Client connected to broker");
}
void connectionLost() {
println("Connection lost");
}
đĄ Testing tip: Open this page in two browser windows side by side. When you send a message from one window, you'll see it appear in the other window's log! This demonstrates real-time MQTT communication.
Live MQTT Demo:
âšī¸ Connection Status: Disconnected
MQTT Messages Log:
Click "Connect MQTT" to start...
Let's create a simple robot control exercise using two servos. This serves as a starting platform for future development work.
#include <ESP8266WiFi.h> // WiFi library for ESP8266
#include <Servo.h> // Servo control library
// ------------------- Pin Definitions -------------------
#define servoPin1 5 // Servo 1 (forward/backward)
#define servoPin2 14 // Servo 2 (left/right)
// ------------------- Default Speed -------------------
int speed = 90; // Default speed (0-180)
// ------------------- WiFi Access Point -------------------
const char* ssid = "ESP8266_Car1"; // AP name
const char* password = ""; // Open network
// ------------------- Web Server -------------------
WiFiServer server(80);
// ------------------- Servo Objects -------------------
Servo servo1;
Servo servo2;
// ------------------- Setup Function -------------------
void setup() {
Serial.begin(115200); // Initialize Serial for debugging
// Attach servos
servo1.attach(servoPin1);
servo2.attach(servoPin2);
// Start Wi-Fi in Access Point mode
WiFi.softAP(ssid, password);
Serial.println("Access Point Started");
Serial.print("IP Address: ");
Serial.println(WiFi.softAPIP());
// Start web server
server.begin();
Serial.println("Server started. Connect via browser to control the robot.");
}
// ------------------- Main Loop -------------------
void loop() {
WiFiClient client = server.available(); // Check for incoming client
if (client) {
String currentLine = "";
// Handle client requests
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c); // Debug: print received characters
if (c == '\n') {
// End of HTTP request header
if (currentLine.length() == 0) {
// Send HTML response
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
// HTML interface
client.println("<html>");
client.println("<head><title>Robot Controller</title></head>");
client.println("<body>");
client.println("<h1>Control Your Car</h1>");
// Movement buttons
client.println("<form action=\"/forward\" method=\"get\"><button type=\"submit\">Forward</button></form>");
client.println("<form action=\"/backward\" method=\"get\"><button type=\"submit\">Backward</button></form>");
client.println("<form action=\"/left\" method=\"get\"><button type=\"submit\">Left</button></form>");
client.println("<form action=\"/right\" method=\"get\"><button type=\"submit\">Right</button></form>");
client.println("<form action=\"/stop\" method=\"get\"><button type=\"submit\">Stop</button></form>");
// Speed slider
client.println("<h3>Speed Control</h3>");
client.println("<form action=\"/speed\" method=\"get\">");
client.println("<input type=\"range\" name=\"speed\" min=\"0\" max=\"180\" value=\"" + String(speed) + "\" onchange=\"this.form.submit()\">");
client.println("<p>Speed: <span id=\"speedValue\">" + String(speed) + "</span></p>");
client.println("</form>");
client.println("<script>");
client.println("document.querySelector('input[type=range]').addEventListener('input', function() {");
client.println(" document.getElementById('speedValue').textContent = this.value;");
client.println("});");
client.println("</script>");
client.println("</body>");
client.println("</html>");
break; // Stop reading request
} else {
// Parse HTTP GET commands
if (currentLine.indexOf("GET /forward") >= 0) moveForward();
else if (currentLine.indexOf("GET /backward") >= 0) moveBackward();
else if (currentLine.indexOf("GET /left") >= 0) turnLeft();
else if (currentLine.indexOf("GET /right") >= 0) turnRight();
else if (currentLine.indexOf("GET /stop") >= 0) stopMovement();
else if (currentLine.indexOf("GET /speed") >= 0) setSpeed(currentLine);
}
currentLine = ""; // Clear line buffer
} else if (c != '\r') {
currentLine += c; // Accumulate HTTP request line
}
}
}
client.stop(); // Disconnect client
Serial.println("Client disconnected");
}
}
// ------------------- Movement Functions -------------------
void moveForward() {
Serial.println("Moving Forward");
servo1.write(90 - speed); // Forward for servo1
servo2.write(90 + speed); // Forward for servo2
}
void moveBackward() {
Serial.println("Moving Backward");
servo1.write(90 + speed);
servo2.write(90 - speed);
}
void turnLeft() {
Serial.println("Turning Left");
servo1.write(90);
servo2.write(0);
}
void turnRight() {
Serial.println("Turning Right");
servo1.write(90);
servo2.write(180);
}
void stopMovement() {
Serial.println("Stopping");
servo1.write(90); // Center position
servo2.write(90); // Center position
}
void setSpeed(String request) {
// Extract speed value from GET request
int speedStart = request.indexOf("speed=") + 6;
int speedEnd = request.indexOf(" ", speedStart);
if (speedEnd == -1) speedEnd = request.length();
String speedStr = request.substring(speedStart, speedEnd);
speed = speedStr.toInt();
Serial.println("Speed set to: " + String(speed));
}
How to Use
- Connect two servos to pins 5 and 14
- Upload the code to your ESP8266
- Connect to WiFi network "ESP8266_Car1"
- Open browser and go to the IP address shown in Serial Monitor
- Use the web interface to control your robot!
Features
- Web Interface: HTML buttons for Forward, Backward, Left, Right, Stop
- Speed Control: Slider to adjust speed from 0-180
- Access Point Mode: Creates its own WiFi network
- Real-time Control: Immediate response to button presses
Note about UDP
In this context, we'll skip UDP (User Datagram Protocol) â packet sending. UDP packets are sent out, but their delivery is not verified. TCP provides reliable communication which is more suitable for most ESP8266 applications.