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

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:

  1. Reads JSON from serial port
  2. Adds accurate timestamps
  3. Authenticates with Azure using Shared Access Signatures
  4. Sends HTTPS POST to Event Hub
  5. 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:

  1. Azure Testing: Validate Event Hub connectivity without hardware setup
  2. Gateway Development: Test gateway software independently
  3. Dashboard Testing: Generate continuous data for visualization development
  4. 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.h vs old WProgram.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:

  1. Internal Microsoft codename tradition
  2. Original intention to use accelerometer (which would make sense for maracas)
  3. Code reuse from an actual maracas project
  4. 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:

  1. 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
  1. Authentication Change:
// AWS uses HMAC-SHA256 signatures
// Azure uses SharedAccessSignature (SAS) tokens
// Both use similar HMAC-SHA256 under the hood
  1. 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:

  1. Read all sensors
  2. Generate 4 separate JSON messages (one per sensor type)
  3. Send each via HTTPS POST
  4. 500ms delay between transmissions
  5. ~2 second complete cycle

Why This Project Matters

The Maracas project showcases several advanced IoT concepts:

  1. Library Portability: Adapting AWS libraries for Azure
  2. Embedded HTTPS: Implementing TLS on a microcontroller
  3. Async Programming: Handling callback-based SSL
  4. Platform Abstraction: Device-independent interfaces
  5. Security: HMAC-SHA256 authentication
  6. 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 interface
  • musicESP32_home.cpp - Implementation
  • array.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 interface
  • xht11.cpp - Implementation
  • test_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:

  1. Create string-to-sign: <resource-uri>\n<expiry>
  2. Compute HMAC-SHA256 using policy key
  3. Base64 encode signature
  4. URL encode all components
  5. 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:

  1. Separate Config Files:
#include "config.h"  // Ignored by .gitignore
// config.h contains:
// #define WIFI_SSID "your-network"
// #define WIFI_PASS "your-password"
  1. Environment Variables: For cloud deployments
  2. Secure Element: Hardware security modules
  3. 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:

  1. Install Connect The Dots gateway software
  2. Configure gateway_config.json with Azure credentials
  3. Connect Arduino via USB
  4. Run python gateway.py

Option 2: Direct HTTPS:

  1. Create Azure Event Hub
  2. Create Shared Access Policy (Send permission)
  3. Generate SAS token
  4. Update sketch with credentials
  5. 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:

  1. Architecture Matters: Gateway vs. direct connectivity depends on use case
  2. Security First: Never hardcode credentials (lesson learned the hard way)
  3. Testing is Essential: Randomizer sketch saved countless hours
  4. Libraries are Force Multipliers: NewPing prevented weeks of development
  5. Abstraction Enables Portability: Device-independent interfaces paid off
  6. Documentation Saves Time: Future you will thank present you
  7. Event-Driven > Blocking: Essential for responsive embedded systems
  8. 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.