1538 Software Prototyping: Libraries and Version Control
1538.1 Learning Objectives
By the end of this chapter, you will be able to:
- Use Sensor Libraries: Integrate Adafruit Unified Sensor and similar libraries for standardized sensor access
- Implement Communication Protocols: Add Wi-Fi, MQTT, and HTTP connectivity using established libraries
- Manage Dependencies: Track library versions and handle dependency conflicts
- Apply Version Control: Use Git effectively for IoT firmware projects
1538.2 Prerequisites
Before diving into this chapter, you should be familiar with:
- Software Architecture Patterns: Understanding of firmware organization
- Development Environments: Ability to install and manage libraries
1538.3 Sensor Libraries
Adafruit Unified Sensor Library: Standardized interface for various sensors.
Example:
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
DHT_Unified dht(DHTPIN, DHT22);
void setup() {
dht.begin();
sensor_t sensor;
dht.temperature().getSensor(&sensor);
}
void loop() {
sensors_event_t event;
dht.temperature().getEvent(&event);
Serial.print("Temp: ");
Serial.println(event.temperature);
}Benefits: - Consistent API across sensors - Easy to swap sensors - Well-documented and tested
Popular Sensor Libraries:
| Sensor Type | Library | Sensors Supported |
|---|---|---|
| Environmental | Adafruit BME280 | Temperature, humidity, pressure |
| Motion | Adafruit MPU6050 | Accelerometer, gyroscope |
| Light | Adafruit TSL2591 | Lux measurement |
| Distance | NewPing | Ultrasonic sensors |
| GPS | TinyGPS++ | NMEA parsing |
1538.4 Communication Libraries
1538.4.1 Wi-Fi
#include <WiFi.h>
void setup() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.println(WiFi.localIP());
}1538.4.2 MQTT
#include <PubSubClient.h>
WiFiClient espClient;
PubSubClient client(espClient);
void callback(char* topic, byte* payload, unsigned int length) {
// Handle incoming messages
}
void setup() {
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// Publish data
client.publish("sensors/temperature", "25.5");
}1538.4.3 HTTP/REST
#include <HTTPClient.h>
void sendData() {
HTTPClient http;
http.begin("http://api.example.com/data");
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST("{\"sensor\":\"temp\",\"value\":25.5}");
if (httpCode > 0) {
String response = http.getString();
Serial.println(response);
}
http.end();
}1538.4.4 WebSocket
#include <WebSocketsClient.h>
WebSocketsClient webSocket;
void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) {
switch(type) {
case WStype_CONNECTED:
webSocket.sendTXT("Hello Server");
break;
case WStype_TEXT:
Serial.printf("Received: %s\n", payload);
break;
}
}
void setup() {
webSocket.begin("server.com", 80, "/ws");
webSocket.onEvent(webSocketEvent);
}
void loop() {
webSocket.loop();
}1538.5 Display Libraries
OLED Displays:
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("Hello IoT!");
display.display();
}TFT Displays:
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE);
tft.drawString("Sensor Data", 10, 10);
}1538.6 Cloud Integration Libraries
AWS IoT:
#include <AWS_IOT.h>
AWS_IOT aws;
void setup() {
aws.connect(HOST, CLIENT_ID);
}
void loop() {
if (aws.publish(TOPIC, "{\"temp\":25.5}")) {
Serial.println("Published");
}
}Azure IoT Hub:
#include <AzureIoTHub.h>
#include <AzureIoTProtocol_MQTT.h>
void sendMessage() {
IOTHUB_MESSAGE_HANDLE messageHandle =
IoTHubMessage_CreateFromString(message);
IoTHubClient_SendEventAsync(iotHubClientHandle,
messageHandle, sendCallback, NULL);
}Firebase:
#include <Firebase_ESP_Client.h>
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
void setup() {
config.api_key = API_KEY;
config.database_url = DATABASE_URL;
Firebase.begin(&config, &auth);
}
void loop() {
Firebase.RTDB.setFloat(&fbdo, "/sensors/temp", 25.5);
}1538.7 Git for IoT Projects
Repository Structure:
iot-project/
βββ firmware/
β βββ src/
β βββ lib/
β βββ test/
β βββ platformio.ini
βββ hardware/
β βββ schematics/
β βββ pcb/
βββ docs/
βββ .gitignore
βββ README.md
.gitignore for IoT:
# Build artifacts
.pio/
build/
*.hex
*.bin
*.elf
# IDE files
.vscode/
.idea/
*.swp
# Environment-specific
secrets.h
credentials.json
# OS files
.DS_Store
Thumbs.db
Branching Strategy: - main: Production-ready code - develop: Integration branch - feature/*: New features - bugfix/*: Bug fixes - release/*: Release preparation
Commit Best Practices:
# Good commit messages
git commit -m "Add BME280 sensor support with I2C interface"
git commit -m "Fix deep sleep wake-up issue on ESP32"
git commit -m "Optimize Wi-Fi reconnection logic to reduce power"
# Poor commit messages
git commit -m "Update"
git commit -m "Fix bug"
git commit -m "Changes"1538.8 Collaborative Development
Pull Request Workflow: 1. Create feature branch 2. Implement and test changes 3. Push to remote repository 4. Create pull request 5. Code review 6. Merge to develop
Code Review Checklist: - [ ] Code compiles without warnings - [ ] Follows project coding style - [ ] Adequate comments and documentation - [ ] No hardcoded credentials or secrets - [ ] Memory leaks checked - [ ] Power consumption considered - [ ] Tested on target hardware
1538.9 Dependency Management
PlatformIO lib_deps:
[env:esp32dev]
lib_deps =
# Exact version
knolleary/PubSubClient@2.8
# Version range (semver)
adafruit/Adafruit BME280 Library@^2.2.2
# Git repository
https://github.com/me/mylib.git
# Local library
lib/custom_sensorVersion Pinning Best Practices:
| Approach | Syntax | Use Case |
|---|---|---|
| Exact version | @2.8.0 |
Production builds |
| Compatible updates | @^2.8.0 |
Accept patches |
| Any version | (no version) | Only for prototyping |
Symptom: Code compiles fine, then fails after pio lib update
Cause: Library update introduced breaking change
Prevention: 1. Pin exact versions in production: lib@2.8.0 2. Test updates in separate branch 3. Read library changelogs before updating 4. Use CI/CD to catch breakages early
Recovery:
# Revert to known working versions
pio lib uninstall PubSubClient
pio lib install "PubSubClient@2.8.0"1538.10 Knowledge Check
1538.11 Whatβs Next
The next section covers Over-the-Air Updates, where youβll learn to implement secure OTA firmware updates, rollback mechanisms, and update orchestration for deployed IoT devices.