Arduino IoT Sensors: From Microsoft's Connect The Dots to Custom ESP32 Libraries (2015-2023)
Arduino IoT Sensors: From Microsoft’s Connect The Dots to Custom ESP32 Libraries (2015-2023)
This repository archives nearly a decade of Arduino and MediaTek LinkIt IoT sensor development work, spanning from my time with the Microsoft Singapore Developer Experience Team in 2015 to custom ESP32 library development in 2023.
Repository: https://github.com/tanchunsiong/arduino-iot-sensors
Timeline: 2015-2023
Organization: Microsoft Singapore DX Team (2015), Personal Projects (2023)
Location: Singapore Microsoft Innovation Center (SG MIC)
Table of Contents
- Project Overview
- Historical Context
- The Connect The Dots Framework
- Sensor Exploration Projects
- MediaTek Maracas: Azure IoT Monitoring
- Custom ESP32 Libraries
- Technical Architecture
- Hardware Specifications
- Lessons Learned
Project Overview
This collection represents three distinct phases of IoT development:
Phase 1: Sensor Exploration (April-June 2015)
Initial exploration of various sensor types including accelerometers, ultrasonic distance sensors, and temperature/humidity sensors. This phase focused on understanding sensor fundamentals and Arduino programming patterns.
Phase 2: Cloud Connectivity (September-November 2015)
Development of cloud-connected IoT systems using Microsoft’s “Connect The Dots” framework. Projects integrated Arduino/MediaTek LinkIt hardware with Raspberry Pi gateways and Azure Event Hub for real-time sensor data streaming.
Phase 3: Custom Library Development (2023)
Creation of custom sensor libraries for ESP32 platforms, including music/tone generation and XHT11 temperature/humidity sensor support.
Historical Context
Microsoft Singapore DX Team (2015)
In 2015, Microsoft was heavily investing in IoT initiatives. The Singapore Developer Experience (DX) Team at the Microsoft Innovation Center was tasked with creating demonstration projects showcasing how developers could integrate Arduino hardware with Microsoft Azure cloud services.
Organization: Microsoft Singapore DX Team
Location: SG MIC (Singapore Microsoft Innovation Center)
Initiative: Connect The Dots - Microsoft’s IoT framework for device-to-cloud data streaming
Platforms: Arduino, MediaTek LinkIt ONE, Raspberry Pi, Windows 10 IoT Core, Azure Event Hub
The “Connect The Dots” framework was Microsoft’s answer to simplifying IoT development by providing:
- Pre-built gateway software for Raspberry Pi (Python and Windows versions)
- Standardized JSON data format for sensor readings
- Azure Event Hub integration for scalable data ingestion
- Visualization dashboards for real-time monitoring
The Connect The Dots Framework
The repository contains four variants of the Connect The Dots implementation, showcasing different architectural approaches:
Architecture 1: Arduino + Raspberry Pi + Python Gateway
Timeline: November 2, 2015
Data Flow: Arduino → Serial (JSON) → Raspberry Pi (Python) → HTTPS → Azure Event Hub
This was the reference implementation demonstrating the classic IoT gateway pattern:
┌─────────────┐ USB Serial ┌──────────────┐ HTTPS ┌────────────┐
│ Arduino │ ─────────────────> │ Raspberry Pi │ ───────────────> │ Azure │
│ + Sensors │ JSON @ 9600 │ (Python) │ Authenticated │ Event Hub │
└─────────────┘ └──────────────┘ └────────────┘
Sensors:
- DHT11 Temperature & Humidity (pin A1)
- Photoresistor Light Sensor (pin A0)
- PIR Motion Sensor (pin 2)
Key Features:
- GUID Generation: Uses EEPROM and analog noise for unique device IDs
- Two-way Communication: Receives LED control commands via serial
- Status Indicators: Red/Green LEDs for system state
- Error Handling: DHT11 timeout and checksum validation
JSON Output Format:
{
"guid": "12345678-1234-1234-1234-123456789abc",
"organization": "Microsoft Singapore DX Team",
"timecreated": "2015-11-02T13:49:00.0000000Z",
"displayname": "Arduino + Raspberry Pi 2 on Raspbian + Python",
"location": "SG MIC",
"measurename": "temperature",
"unitofmeasure": "C",
"value": 28.50
}
The Arduino continuously reads sensors and outputs four JSON messages per cycle (temperature, humidity, light, motion). The Raspberry Pi gateway:
- Reads JSON from serial port
- Adds accurate timestamps
- Authenticates with Azure using Shared Access Signatures
- Sends HTTPS POST to Event Hub
- Optionally sends commands back to Arduino (LED control)
Architecture 2: MediaTek LinkIt + Windows Gateway
Timeline: September 23, 2015
Platform Change: MediaTek LinkIt ONE replaces Arduino
Gateway OS: Windows replaces Linux (Raspbian)
This variant explored MediaTek’s LinkIt ONE platform, a more integrated board combining MCU + WiFi/GPRS/Bluetooth in a single package:
Pin Configuration Changes:
- DHT11: Pin 1 (vs A1 on Arduino)
- PIR: Pin 12 (vs 2 on Arduino)
- Red LED: Pin 8 (vs 6 on Arduino)
- Green LED: Pin 6 (vs 8 on Arduino)
LinkIt-Specific Adaptations:
- Custom
dtostrf()implementation (LinkIt SDK didn’t include standard C library version) - Included DHT11 library directly in sketch folder for portability
- Modified for Windows-based gateway software
Display Name: “Arduino + Raspberry Pi 2 on Windows”
This variant demonstrated Microsoft’s commitment to Windows 10 IoT Core, showing the same architecture could work with Windows-based gateways.
Architecture 3: LinkIt Randomizer (Testing Version)
Timeline: September 22, 2015
Purpose: Development and testing without physical sensors
A brilliant engineering decision - create a testing variant that generates fake sensor data:
float temperatureC = random(25, 35); // Random 25-35°C
float humidity = random(0, 100); // Random 0-100%
float lightsensorValue = random(20, 500) / 1000.0; // Random 0.020-0.500 lumens
int motionvalue = random(0, 2); // Random 0 or 1
Benefits:
- Azure Testing: Validate Event Hub connectivity without hardware setup
- Gateway Development: Test gateway software independently
- Dashboard Testing: Generate continuous data for visualization development
- Demo Preparation: Ensure system works before live demonstrations
This version uses the exact same JSON format, making it a perfect drop-in replacement for testing purposes.
Architecture 4: Direct Azure HTTPS (No Gateway)
Timeline: October 14-15, 2015
Innovation: Eliminates Raspberry Pi gateway entirely
┌─────────────┐ ┌────────────┐
│ MediaTek │ ────────── WiFi ────────> │ Azure │
│ LinkIt │ HTTPS + SAS Auth │ Event Hub │
│ + WiFi │ │ │
└─────────────┘ └────────────┘
This was a significant architectural evolution - direct device-to-cloud connectivity:
Custom IoT HTTP Client (IotHttpClient.h/cpp):
- SSL/TLS support using LinkIt’s
vmssl.h - HTTPS POST request building
- Asynchronous SSL callbacks
- HTTP status code parsing (201=success, 401=auth failure, 500=error)
Azure Configuration:
#define AZURE_SERVICE_BUS_NAME_SPACE "cspi2-ns"
#define AZURE_EVENT_HUB_NAME "ehdevices"
#define AZURE_POLICY_NAME "mediateksender"
#define AZURE_TTL "5044894993"
#define AZURE_SIGNATURE "<SAS-token>"
Shared Access Signature Format:
SharedAccessSignature
sr=https%3a%2f%2fcspi2-ns.servicebus.windows.net%2fehdevices%2fpublishers%2fmediateksender%2fmessages
&sig=<signature>
&se=<expiry-timestamp>
&skn=mediateksender
Advantages:
- Reduced hardware cost (no Raspberry Pi required)
- Lower latency (one less hop)
- Simplified deployment
- Better for battery-powered scenarios
Trade-offs:
- More complex firmware (HTTPS handling on MCU)
- Limited to WiFi range
- More difficult debugging (no gateway logs)
- Security considerations (credentials on device)
Sensor Exploration Projects
Before tackling cloud connectivity, the repository shows systematic sensor exploration:
MMA7361 3-Axis Accelerometer (April 2015)
Timeline: April 23, 2015
Hardware: MMA7361 analog accelerometer (±1.5G to ±6G selectable)
Three example sketches demonstrating different data output formats:
1. G_Force Example:
Serial.print("x = ");
Serial.print(x); // Output in G×10⁻² (centipascals)
2. Voltage Example:
Serial.print("x = ");
Serial.print(millivolts); // Output in mV (using 3.3V AREF)
3. RawData Example:
Serial.print("x = ");
Serial.print(analogValue); // Raw ADC values (0-1023)
Pin Configuration:
- Sleep: Pin 13 (power management)
- Self-Test: Pin 12 (built-in test mode)
- Zero-G: Pin 11 (zero-g detection interrupt)
- g-Select: Pin 10 (sensitivity selection: HIGH=±1.5G, LOW=±6G)
- X-axis: A0, Y-axis: A1, Z-axis: A2
Included Documentation: mma7361 schematics.jpg - Wiring diagram (277KB, dated May 4, 2015)
Use Cases: Motion detection, gesture recognition, tilt sensing, vibration monitoring
Library: AcceleroMMA7361.h by Jef Neefs & Jeroen Doggen
This accelerometer work may have been related to the “Mediatek Maracas” project (see below), though that project ultimately used a PIR sensor instead of the accelerometer.
NewPing Ultrasonic Sensor (June 2015)
Timeline: June 10, 2015
Hardware: HC-SR04 ultrasonic distance sensor (200cm max range)
Library: NewPing v1.5 by Tim Eckel (GPL v3)
Four progressively complex examples:
1. NewPingExample - Basic Blocking Operation:
unsigned int distance = sonar.ping_cm();
Serial.println(distance);
delay(50); // 20 pings/second
Simple, synchronous distance measurement. Good for learning but blocks execution.
2. TimerExample - Interrupt-Driven LED Toggle:
// Uses Timer2 interrupt to toggle LED every 500ms
// No main loop code needed!
Demonstrates Timer2 usage. Important: Disables PWM on pins 3 & 11, incompatible with Tone library.
3. NewPingEventTimer - Non-Blocking Async Ping:
void setup() {
pingTimer.every(50, doPing); // Non-blocking ping every 50ms
}
void echoCheck() {
// Called every 24μS during ping
if (sonar.check_timer()) {
// Echo received, distance available
}
}
Key Innovation: Event-driven architecture allows multitasking during ping operation. Perfect for robotics applications where the main loop needs to continue running (motor control, sensor reading, decision making).
4. NewPing15Sensors - Advanced Multi-Sensor Array:
This is the most impressive example - managing 15 ultrasonic sensors simultaneously for 360° obstacle detection:
#define SENSORS_NUM 15
NewPing sonar[SENSORS_NUM] = {
NewPing(41, 41, MAX_DISTANCE), // Sensor 1
NewPing(43, 43, MAX_DISTANCE), // Sensor 2
// ... 13 more sensors
};
Timing Management:
- 33ms per sensor (avoids echo interference)
- 495ms full cycle (15 sensors × 33ms)
- Event-driven sensor rotation
- Distance array for quick access
Hardware Requirements: Arduino Mega (needs sufficient I/O pins)
Use Case: Advanced robotics - autonomous navigation, obstacle avoidance, 360° environment mapping
Pin Strategy: Uses shared trigger/echo pins (single-wire mode) to conserve I/O
This level of multi-sensor coordination demonstrates solid embedded systems knowledge - managing timing, preventing interference, and creating a scalable sensor network.
DHT11 Temperature & Humidity Sensor (August 2015)
Timeline: August 12, 2015
Version: 0.3.2
Authors: George Hadjikyriacou (original), modified by SimKard and Rob Tillaart
License: GPL v3
A self-contained DHT11 library included in the repository:
Key Features:
- Protocol Implementation: Bit-banging the DHT11’s one-wire protocol
- Timeout Handling: Prevents hanging on sensor failures
- Checksum Validation: Verifies data integrity
- Arduino 1.0+ Compatibility: Handles
Arduino.hvs oldWProgram.h
Usage:
dht11 DHT;
DHT.read(pin);
float temp = DHT.temperature; // Celsius
float hum = DHT.humidity; // Percentage
Error Codes:
DHTLIB_OK // Successful read
DHTLIB_ERROR_CHECKSUM // Data corruption
DHTLIB_ERROR_TIMEOUT // Sensor not responding
This library was integrated into all the Connect The Dots variants and the Maracas project.
MediaTek Maracas: Azure IoT Monitoring
Timeline: September 15, 2015
Name Clarification: Despite the creative “Maracas” codename, this is NOT a musical instrument - it’s an environmental monitoring system.
The Misleading Name
The project name “Mediatek Maracas” suggests a motion-based musical instrument (maracas being percussion instruments). However, the actual implementation is a cloud-connected multi-sensor monitoring system that sends data to Azure Event Hub.
Possible reasons for the name:
- Internal Microsoft codename tradition
- Original intention to use accelerometer (which would make sense for maracas)
- Code reuse from an actual maracas project
- Marketing/demo series naming convention
Actual Implementation
Architecture: MediaTek LinkIt ONE → WiFi → HTTPS → Azure Event Hub (Direct)
Sensors:
- DHT11 (Pin 1) - Temperature & humidity
- Photoresistor (A0) - Light level
- PIR (Pin 2) - Motion detection
Custom Library: AWSArduinoMediaTekLibrary/ (16 files)
This is where it gets technically interesting - the project includes a custom AWS Kinesis library adapted for Azure Event Hub:
AWSArduinoMediaTekLibrary/
├── AWSClient.cpp/h - Azure Event Hub client
├── AmazonKinesisClient.cpp/h - Repurposed for Event Hub
├── MtkAWSImplementations.cpp/h - MediaTek HTTP/HTTPS wrappers
├── Utils.cpp/h - Base64, JSON, HMAC-SHA256
├── sha256.cpp/h - SHA-256 hashing
├── jsmn.c/h - Lightweight JSON parser
├── dht11.cpp/h - DHT11 sensor library
└── DeviceIndependentInterfaces.cpp/h - Abstract interfaces
The AWS-to-Azure Adaptation
Original Purpose: AWS Kinesis data streaming
Adapted For: Azure Event Hub (compatible API)
The library cleverly repurposes AWS Kinesis client code for Azure by:
- Modified URL Structure:
// AWS Kinesis would be:
// POST / HTTP/1.1
// Host: kinesis.us-east-1.amazonaws.com
// Adapted for Azure:
// POST /ehmediatek/publishers/mediateksender/messages HTTP/1.1
// Host: cspi2-ns.servicebus.windows.net
- Authentication Change:
// AWS uses HMAC-SHA256 signatures
// Azure uses SharedAccessSignature (SAS) tokens
// Both use similar HMAC-SHA256 under the hood
- MediaTek-Specific HTTP:
class MtkHttpClient : public IHttpClient {
// Uses LinkIt's LWiFiClient
// Wraps vmssl for HTTPS
// Handles asynchronous SSL callbacks
};
SSL/TLS Implementation
Challenge: LinkIt’s SSL API is callback-based and runs in a different thread
Solution: LTask.remoteCall() to bridge threads:
void ssl_send_cb(VMINT hdl, VMINT evt) {
switch (evt) {
case VM_SSL_EVT_CONNECTED:
// Send HTTP request
break;
case VM_SSL_EVT_CAN_WRITE:
// Write data
break;
case VM_SSL_EVT_CAN_READ:
// Read response
break;
}
}
This demonstrates solid understanding of embedded async programming patterns.
Azure Event Hub Configuration
Namespace: cspi2-ns.servicebus.windows.net
Event Hub: ehmediatek
Publisher: mediateksender
SAS Token: (expired - was valid until May 2017)
Data Transmission Pattern:
- Read all sensors
- Generate 4 separate JSON messages (one per sensor type)
- Send each via HTTPS POST
- 500ms delay between transmissions
- ~2 second complete cycle
Why This Project Matters
The Maracas project showcases several advanced IoT concepts:
- Library Portability: Adapting AWS libraries for Azure
- Embedded HTTPS: Implementing TLS on a microcontroller
- Async Programming: Handling callback-based SSL
- Platform Abstraction: Device-independent interfaces
- Security: HMAC-SHA256 authentication
- JSON Parsing: Lightweight jsmn library on embedded device
It represents a more production-ready approach compared to the simpler gateway-based architectures.
Custom ESP32 Libraries (2023)
Fast-forward 8 years to 2023 - custom library development for ESP32 platforms:
ESP32_music_lib_home
Created: September 9, 2023
Language: C++ with Chinese comments
Purpose: Music and tone generation for ESP32
Files:
musicESP32_home.h- Library interfacemusicESP32_home.cpp- Implementationarray.h- Musical note frequency arrays
Use Case: Playing melodies, tones, and sound effects on ESP32-based projects (alarms, notifications, games)
Example Applications:
- Smart doorbell melodies
- Game sound effects
- Musical instruments
- Alarm systems
- Educational projects
xht11
Created: September 9, 2023
Original Author: Dengfei (2021/1/5)
Language: C++ with Chinese comments
Purpose: XHT11 (DHT11 variant) temperature and humidity sensor library
Files:
xht11.h- Library interfacexht11.cpp- Implementationtest_xht11/test_xht11.ino- Example sketch
XHT11 vs DHT11: The XHT11 is a DHT11-compatible sensor, likely a newer revision or alternative manufacturer. This custom library may include optimizations or bug fixes not present in standard DHT11 libraries.
Included Test Sketch: Demonstrates basic usage and provides a template for integration.
Technical Architecture
Data Flow Patterns
The repository demonstrates three distinct IoT architectures:
Pattern 1: Gateway-Mediated (Classic IoT)
Device → Local Protocol → Gateway → Cloud Protocol → Cloud Service
Arduino → Serial/JSON → Raspberry Pi → HTTPS → Azure Event Hub
Advantages:
- Simple device firmware
- Gateway handles authentication
- Easy debugging (gateway logs)
- Protocol translation
- Multiple devices per gateway
Disadvantages:
- Extra hardware cost
- Single point of failure
- Additional latency
- More complex deployment
Pattern 2: Direct Connectivity (Modern IoT)
Device → Cloud Protocol → Cloud Service
LinkIt → WiFi/HTTPS → Azure Event Hub
Advantages:
- Lower cost
- Reduced latency
- Simpler architecture
- Better for distributed deployments
Disadvantages:
- Complex device firmware
- Harder debugging
- Security on device
- Limited by device capabilities
Pattern 3: Hybrid (Best of Both)
Device ←→ Local Gateway ←→ Cloud
(two-way communication for control)
JSON Data Schema
All projects use a consistent JSON schema:
{
"guid": "<unique-device-id>",
"organization": "Microsoft Singapore DX Team",
"timecreated": "2015-11-02T13:49:00.0000000Z",
"displayname": "Arduino + Raspberry Pi 2 on Raspbian",
"location": "SG MIC",
"measurename": "temperature|humidity|light|motion",
"unitofmeasure": "C|%|lumen|binary",
"value": <numeric-value>
}
Design Decisions:
- Separate messages per measurement: Easier Azure Stream Analytics queries
- ISO 8601 timestamps: Universal time format
- Metadata in every message: Self-describing for analytics
- Fixed schema: Enables strong typing in cloud processing
Authentication & Security
Azure Shared Access Signature (SAS) Format:
SharedAccessSignature
sr=<resource-uri>
&sig=<signature-hash>
&se=<expiry-epoch>
&skn=<policy-name>
Components:
sr: Resource URI (URL-encoded Event Hub path)sig: HMAC-SHA256 signature (URL-encoded)se: Expiry timestamp (Unix epoch)skn: Policy name (send, listen, or manage permissions)
Generation Process:
- Create string-to-sign:
<resource-uri>\n<expiry> - Compute HMAC-SHA256 using policy key
- Base64 encode signature
- URL encode all components
- Concatenate into SAS token
Security Note: The repository has WiFi credentials and SAS tokens sanitized. Original tokens expired in 2017.
Hardware Specifications
Microcontrollers Used
| Platform | Year | Features | Projects |
|---|---|---|---|
| Arduino Uno | 2015 | ATmega328P, 16MHz, 2KB RAM | Connect The Dots, Sensors |
| Arduino Mega | 2015 | ATmega2560, 54 I/O pins | 15-sensor ultrasonic |
| MediaTek LinkIt ONE | 2015 | ARM Cortex-M4, WiFi, GPRS, BT | Cloud-connected variants |
| ESP32 | 2023 | Dual-core, WiFi, BT, 520KB RAM | Custom libraries |
Sensor Specifications
DHT11 Temperature & Humidity:
- Temperature: 0-50°C (±2°C accuracy)
- Humidity: 20-90% RH (±5% accuracy)
- Protocol: One-wire (bit-banging)
- Sample rate: 1Hz maximum
- Supply: 3.3-5V
MMA7361 Accelerometer:
- Axes: 3 (X, Y, Z)
- Ranges: ±1.5G or ±6G (selectable via g-Select pin)
- Output: Analog voltage (3 pins)
- Sleep mode: Available
- Self-test: Built-in
- Supply: 3.3V
HC-SR04 Ultrasonic:
- Range: 2-400cm
- Accuracy: ±3mm
- Beam angle: 15°
- Frequency: 40kHz
- Trigger: 10μS pulse
- Echo: Pulse width proportional to distance
- Supply: 5V
Photoresistor:
- Type: Cadmium Sulfide (CdS)
- Resistance: 200Ω (bright) to 10kΩ (dark)
- Response time: ~100ms
- Connection: Voltage divider with 10kΩ resistor
PIR Motion Sensor:
- Detection range: Up to 7 meters
- Angle: 120°
- Output: Digital (HIGH when motion detected)
- Delay: Adjustable (0.5-200s)
- Supply: 5V
Power Considerations
Arduino Uno:
- Operating: ~50mA (no sensors)
- With WiFi shield: +150-200mA
- USB powered or 7-12V external
MediaTek LinkIt ONE:
- Operating: ~50mA (idle)
- WiFi active: +150mA
- Peak: ~300mA (transmission)
- Battery: Li-Po 3.7V (JST connector)
Sensor Power Budget:
- DHT11: ~2.5mA
- MMA7361: ~500μA
- HC-SR04: ~15mA (during ping)
- PIR: ~65μA
Total system: ~250mA (Arduino + WiFi + sensors active)
Lessons Learned
1. Gateway vs. Direct Connectivity Trade-offs
The repository perfectly demonstrates the evolution from gateway-based to direct device connectivity:
2015 Thinking: Gateways are essential
- Devices are simple, gateways are smart
- Raspberry Pi handles authentication, encryption, buffering
- Easy debugging with gateway logs
Modern Approach (demonstrated by direct HTTPS variant):
- Devices are getting smarter (ESP32, LinkIt)
- Direct connectivity reduces cost and latency
- TLS/HTTPS libraries available for embedded
- Cloud SDKs for microcontrollers
Conclusion: Choose based on:
- Device capability (RAM, CPU, networking)
- Power budget (battery vs. mains)
- Scale (1 device vs. 1000)
- Security requirements (credential storage)
2. Sensor Library Ecosystem Matters
Observation: The accelerometer and ultrasonic examples show the importance of good libraries.
NewPing library (Tim Eckel):
- Event-driven, non-blocking operation
- Multi-sensor support
- Excellent documentation
- Saved weeks of development time
Lesson: Don’t reinvent the wheel. Use established libraries but:
- Understand their limitations
- Read the source code
- Contribute improvements back
- Fork if necessary (see custom xht11 library)
3. Security from Day One
Historical Mistake: WiFi credentials and SAS tokens were hardcoded in sketches.
Better Approaches:
- Separate Config Files:
#include "config.h" // Ignored by .gitignore
// config.h contains:
// #define WIFI_SSID "your-network"
// #define WIFI_PASS "your-password"
- Environment Variables: For cloud deployments
- Secure Element: Hardware security modules
- Over-the-Air Updates: For credential rotation
SAS Token Management:
- Use short expiry times (hours, not years)
- Rotate regularly
- Per-device tokens (not shared)
- Monitor for unauthorized usage
4. JSON vs. Binary Protocols
This repository uses JSON exclusively. Good decision for 2015, but consider:
JSON Advantages:
- Human-readable (debugging)
- Self-describing (schema in data)
- Language-agnostic (Python, C++, JavaScript all parse easily)
- Azure Stream Analytics native support
JSON Disadvantages:
- Large payload size (200-300 bytes per message)
- Parsing overhead on MCU
- Unnecessary for machine-to-machine
Modern Alternative: Protocol Buffers or CBOR
- Binary, compact representation
- Schema-defined (type safety)
- 5-10× smaller payloads
- Faster parsing
Recommendation: JSON for prototypes, binary for production IoT.
5. Testing Strategy
The randomizer sketch (Architecture 3) is brilliant:
// Generate fake sensor data for testing
float temperatureC = random(25, 35);
Why This Matters:
- Hardware Independence: Test cloud infrastructure without sensors
- Continuous Integration: Automated testing possible
- Demos: Guaranteed working data for presentations
- Development Speed: No hardware setup time
Expand This Concept:
- Unit tests for sensor libraries
- Mock HTTP clients for offline development
- Sensor simulators with realistic noise
- Fault injection (timeout simulation)
6. Multi-Sensor Timing
The 15-sensor ultrasonic example teaches critical lessons:
Problem: Ultrasonic sensors interfere with each other
Solution: Time-division multiplexing (33ms per sensor)
General Principle: When multiple sensors share a medium (air, light, radio), you need:
- Sequential activation
- Sufficient spacing (avoid crosstalk)
- Event-driven architecture (don’t block)
Applies To:
- Ultrasonic arrays
- Multiple RFID readers
- Concurrent WiFi/BLE operations
- Multi-camera systems
7. Platform Abstraction Pays Off
The Maracas project’s DeviceIndependentInterfaces.cpp/h demonstrates:
class IHttpClient {
virtual bool connect() = 0;
virtual bool send() = 0;
virtual bool receive() = 0;
};
class MtkHttpClient : public IHttpClient {
// MediaTek-specific implementation
};
Benefits:
- Portability: Swap HTTP implementations
- Testing: Mock HTTP client for unit tests
- Future-Proofing: Migrate to different hardware
- Team Development: Multiple developers work in parallel
Lesson: Even small embedded projects benefit from abstraction layers.
8. Documentation Through Code
Good Examples in Repository:
- Pin assignments in comments
- Wiring schematic included (MMA7361)
- Example sketches for each library
- README with setup instructions
Missing:
- Photos of physical setups
- Fritzing diagrams
- Video demonstrations
- Troubleshooting guides
Best Practice: Document as you build, not after.
Technical Impact
Skills Demonstrated
Embedded Programming:
- Bit-banging protocols (DHT11)
- Interrupt-driven programming (Timer2)
- Event-driven architecture (NewPing async)
- Memory management (limited RAM constraints)
- Hardware abstraction layers
Networking:
- HTTP/HTTPS protocol implementation
- SSL/TLS on embedded devices
- WiFi connection management
- JSON serialization/parsing
- Authentication (HMAC-SHA256, SAS tokens)
Cloud Integration:
- Azure Event Hub connectivity
- IoT gateway patterns
- Data pipeline architecture
- Real-time data streaming
- Cloud-to-device messaging
Hardware Integration:
- Multiple sensor types
- Analog vs. digital sensors
- Pull-up/pull-down resistors
- Power management
- Multi-sensor timing coordination
Architecture Patterns
Event-Driven Programming:
// Traditional blocking approach (BAD)
delay(1000);
readSensor();
// Event-driven approach (GOOD)
timer.every(1000, readSensor);
// Main loop continues running
Callback-Based Async:
void ssl_callback(VMINT hdl, VMINT evt) {
// Called when SSL events occur
// Enables non-blocking operations
}
State Machines:
enum State { IDLE, CONNECTING, SENDING, RECEIVING };
// Manage complex async operations
These patterns are fundamental to modern IoT development.
Repository Structure & Usage
Installation
# Clone repository
git clone https://github.com/tanchunsiong/arduino-iot-sensors.git
cd arduino-iot-sensors
# Install custom libraries
cp -r libraries/* ~/Documents/Arduino/libraries/
# Install third-party libraries via Arduino Library Manager:
# - Adafruit GFX Library
# - Adafruit NeoPixel
# - ESP32Tone
# - LiquidCrystal_I2C
# - NewPing
# - OneButton
# (See README for complete list)
Board Setup
Arduino:
- Pre-installed in Arduino IDE
ESP32:
File → Preferences → Additional Board Manager URLs:
https://dl.espressif.com/dl/package_esp32_index.json
Tools → Board → Boards Manager → Install "ESP32"
MediaTek LinkIt ONE:
File → Preferences → Additional Board Manager URLs:
http://download.labs.mediatek.com/package_mtk_linkit_index.json
Tools → Board → Boards Manager → Install "LinkIt ONE"
Azure Setup (for Cloud Projects)
Option 1: Using Gateway:
- Install Connect The Dots gateway software
- Configure
gateway_config.jsonwith Azure credentials - Connect Arduino via USB
- Run
python gateway.py
Option 2: Direct HTTPS:
- Create Azure Event Hub
- Create Shared Access Policy (Send permission)
- Generate SAS token
- Update sketch with credentials
- Upload and run
Conclusion
This repository is more than just code - it’s a historical record of IoT evolution from 2015 to 2023:
2015: The Gateway Era
- Devices were simple
- Gateways handled intelligence
- Cloud connectivity was complex
- Demonstrations required significant setup
2023: The Direct Connectivity Era
- Devices are powerful (ESP32, etc.)
- Direct cloud connectivity standard
- TLS/HTTPS libraries available
- Rapid prototyping possible
Key Takeaways:
- Architecture Matters: Gateway vs. direct connectivity depends on use case
- Security First: Never hardcode credentials (lesson learned the hard way)
- Testing is Essential: Randomizer sketch saved countless hours
- Libraries are Force Multipliers: NewPing prevented weeks of development
- Abstraction Enables Portability: Device-independent interfaces paid off
- Documentation Saves Time: Future you will thank present you
- Event-Driven > Blocking: Essential for responsive embedded systems
- Cloud Integration is Table Stakes: IoT without cloud connectivity is just “T”
Modern Relevance:
Despite being 8-10 years old, these projects demonstrate timeless concepts:
- Multi-sensor coordination
- Authentication and security
- Asynchronous programming
- Platform abstraction
- Cloud connectivity patterns
The ESP32 libraries (2023) show continued learning and adaptation to modern platforms.
Project Stats:
- Duration: 2015-2023 (8 years)
- Platforms: 4 (Arduino, Mega, LinkIt, ESP32)
- Sensors: 6 types
- Architectures: 3 distinct patterns
- Code: 5,958 lines
- Libraries: 2 custom, 11+ third-party
Repository: https://github.com/tanchunsiong/arduino-iot-sensors
License: Mixed - Custom code from Microsoft Singapore DX Team (2015), GPL v3 components, custom libraries (2023)
This archive preserves IoT sensor development work from the Microsoft Singapore Developer Experience Team and subsequent personal projects, demonstrating the evolution of IoT architectures and embedded programming practices over nearly a decade.