1537 Software Prototyping: Programming Languages
1537.1 Learning Objectives
By the end of this chapter, you will be able to:
- Compare IoT Programming Languages: Evaluate C/C++, Python, JavaScript, and Rust for embedded development
- Select Languages by Constraint: Choose appropriate languages based on memory, real-time, and team factors
- Write Cross-Platform Code: Understand language portability considerations
- Evaluate Trade-offs: Balance development speed against runtime performance
1537.2 Prerequisites
Before diving into this chapter, you should be familiar with:
- Development Environments: Understanding of IDE options and setup
- Basic programming concepts in at least one language
1537.3 C/C++ for Microcontrollers
Why C/C++: - Direct hardware control - Minimal overhead and high efficiency - Real-time determinism - Industry standard for embedded systems
Characteristics: - Manual memory management - Low-level hardware access - Compiled to machine code - Small binary sizes
Arduino C++ Example:
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Adafruit_BME280 bme;
void setup() {
Serial.begin(115200);
if (!bme.begin(0x76)) {
Serial.println("BME280 not found!");
while (1);
}
}
void loop() {
float temp = bme.readTemperature();
float pressure = bme.readPressure() / 100.0F;
float humidity = bme.readHumidity();
Serial.print("Temp: ");
Serial.print(temp);
Serial.print(" C, Pressure: ");
Serial.print(pressure);
Serial.print("hPa, Humidity: ");
Serial.print(humidity);
Serial.println("%");
delay(2000);
}Best For: - Resource-constrained microcontrollers - Real-time applications - Power-critical battery devices - Performance-sensitive applications
1537.4 Python for IoT
Why Python: - Rapid development - Extensive libraries - Readable, maintainable code - Strong ecosystem for data analysis and ML
MicroPython: Subset of Python 3 running on microcontrollers (ESP32, ESP8266, Raspberry Pi Pico).
Example:
from machine import Pin, I2C
import bme280
import time
i2c = I2C(scl=Pin(22), sda=Pin(21))
bme = bme280.BME280(i2c=i2c)
while True:
temp, pressure, humidity = bme.read_compensated_data()
print(f"Temp: {temp/100:.2f} C, Pressure: {pressure/25600:.2f}hPa, Humidity: {humidity/1024:.2f}%")
time.sleep(2)CPython (Raspberry Pi): Full Python implementation on Linux-based systems.
Example:
import board
import adafruit_bme280
i2c = board.I2C()
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c)
while True:
print(f"Temp: {bme280.temperature:.2f} C")
print(f"Humidity: {bme280.humidity:.2f}%")
print(f"Pressure: {bme280.pressure:.2f}hPa")
time.sleep(2)Best For: - Raspberry Pi and capable microprocessors - Rapid prototyping and experimentation - Data processing and analysis - Integration with ML frameworks
1537.5 JavaScript/Node.js
Why JavaScript: - Familiar to web developers - Asynchronous I/O model - Rich ecosystem (npm packages) - Full-stack IoT (device to cloud to web app)
Johnny-Five Framework: JavaScript robotics and IoT platform.
Example:
const five = require("johnny-five");
const board = new five.Board();
board.on("ready", function() {
const temperature = new five.Thermometer({
controller: "BME280"
});
temperature.on("change", function() {
console.log(`${this.celsius} C`);
});
});Best For: - Web developer-friendly IoT - Real-time applications (WebSockets) - Prototyping with rapid iteration - Projects integrating with web services
1537.6 Rust for Embedded
Why Rust: - Memory safety without garbage collection - Zero-cost abstractions - Fearless concurrency - Growing embedded ecosystem
Example:
#![no_std]
#![no_main]
use cortex_m_rt::entry;
use panic_halt as _;
use stm32f4xx_hal::{prelude::*, pac};
#[entry]
fn main() -> ! {
let dp = pac::Peripherals::take().unwrap();
let gpioa = dp.GPIOA.split();
let mut led = gpioa.pa5.into_push_pull_output();
loop {
led.toggle();
cortex_m::asm::delay(8_000_000);
}
}Best For: - Safety-critical applications - Long-lived deployed systems - Projects requiring both performance and safety - Advanced embedded developers
1537.7 Language Selection Criteria
1537.7.1 By Resource Constraints
| RAM Available | Recommended Language |
|---|---|
| Severe (<16KB) | C only |
| Limited (16-64KB) | C/C++ |
| Moderate (64KB-1MB) | C/C++, MicroPython |
| Abundant (>1MB) | Python, JavaScript, any |
1537.7.2 By Development Speed
| Priority | Best Choice |
|---|---|
| Rapid prototyping | Python, JavaScript |
| Production optimization | C/C++, Rust |
| Team familiarity | Match to existing skills |
1537.7.3 By Team Skills
| Team Background | Recommended Path |
|---|---|
| Embedded engineers | C/C++ |
| Web developers | JavaScript, then C |
| Data scientists | Python |
| Systems programmers | Rust |
1537.7.4 By Real-Time Requirements
| Requirement | Language Choice |
|---|---|
| Hard real-time (<1ms) | C/C++, Rust |
| Soft real-time (1-100ms) | Any with proper design |
| No real-time | Python, JavaScript |
1537.8 Language Comparison Table
| Factor | C/C++ | Python | JavaScript | Rust |
|---|---|---|---|---|
| Memory Footprint | Tiny (2-20KB) | Large (100-500KB) | Medium (50-200KB) | Small (10-50KB) |
| Development Speed | Slow | Fast | Fast | Medium |
| Safety | Manual | Automatic GC | Automatic GC | Compile-time |
| Learning Curve | Medium | Easy | Easy | Hard |
| Library Ecosystem | Excellent | Excellent | Good | Growing |
| Real-time Support | Excellent | Poor | Poor | Excellent |
Python (MicroPython): - 10x faster development - 10x larger memory footprint - 10x slower execution - Interactive REPL for debugging
C/C++: - Slower development - Minimal memory overhead - Maximum performance - Compile-test-debug cycle
Recommendation: Start with MicroPython for proof-of-concept, migrate to C when performance or memory becomes critical.
1537.9 Knowledge Check
1537.10 What’s Next
The next section covers Software Architecture Patterns, where you’ll learn about bare-metal, state machine, event-driven, and RTOS-based architectures for organizing your IoT firmware effectively.