Node.js implementation of the Arduino Firmata protocol for controlling Arduino boards from JavaScript applications
Analog input reading and PWM output control for interfacing with sensors, controlling motor speeds, LED brightness, and other analog devices.
Generate PWM (Pulse Width Modulation) signals for controlling analog devices like LEDs, motors, and servo positions.
/**
* Write analog value to a PWM-capable pin
* Automatically configures pin for PWM output
* @param pin - PWM-capable pin number (typically 3, 5, 6, 9, 10, 11 on Arduino UNO)
* @param value - PWM value from 0 (0% duty cycle) to 255 (100% duty cycle)
* @param callback - Optional callback function called when value is written
*/
analogWrite(pin: number, value: number, callback?: Function): void;PWM Value Range:
0 - 0% duty cycle (always LOW, equivalent to digitalWrite(pin, false))127-128 - ~50% duty cycle (half power)255 - 100% duty cycle (always HIGH, equivalent to digitalWrite(pin, true))Usage Examples:
// Set LED to half brightness
arduino.analogWrite(9, 127);
// Fade LED in and out
let brightness = 0;
let direction = 1;
setInterval(function() {
arduino.analogWrite(9, brightness);
brightness += direction * 5;
if (brightness >= 255 || brightness <= 0) {
direction = -direction;
}
}, 50);
// Control motor speed (0 = stopped, 255 = full speed)
arduino.analogWrite(6, 200); // ~78% speed
// With callback
arduino.analogWrite(9, 100, function() {
console.log('PWM value set to 100');
});Read analog voltage values from Arduino analog input pins for sensor data collection.
/**
* Read current analog value from an analog input pin
* @param pin - Analog pin number (0-5 on Arduino UNO, corresponds to A0-A5)
* @returns Current analog reading as integer from 0 to 1023
*/
analogRead(pin: number): number;Value Range:
0 - 0V input voltage512 - ~2.5V input voltage (half of 5V reference)1023 - 5V input voltage (or reference voltage)Usage Examples:
// Read potentiometer on analog pin 0
const potValue = arduino.analogRead(0);
console.log(`Potentiometer reading: ${potValue} (${(potValue/1023*100).toFixed(1)}%)`);
// Read multiple analog sensors
for (let pin = 0; pin < 6; pin++) {
const reading = arduino.analogRead(pin);
const voltage = (reading / 1023) * 5.0; // Convert to voltage
console.log(`A${pin}: ${reading} (${voltage.toFixed(2)}V)`);
}
// Convert reading to percentage
const lightLevel = arduino.analogRead(1);
const lightPercentage = Math.round((lightLevel / 1023) * 100);
console.log(`Light sensor: ${lightPercentage}%`);Monitor analog pin value changes in real-time using events.
// Event: analogChange
// Fired when an analog pin value changes
// Event object properties:
interface AnalogChangeEvent {
pin: number; // Analog pin number that changed (0-5)
value: number; // New analog reading (0-1023)
old_value: number; // Previous analog reading
}Usage Example:
arduino.on('analogChange', function(event) {
console.log(`Analog pin A${event.pin} changed from ${event.old_value} to ${event.value}`);
// Example: Light sensor trigger
if (event.pin === 1 && event.value > 800 && event.old_value <= 800) {
console.log('Bright light detected!');
arduino.analogWrite(9, 255); // Turn on LED at full brightness
}
// Example: Potentiometer controlling LED brightness
if (event.pin === 0) {
const brightness = Math.round((event.value / 1023) * 255);
arduino.analogWrite(9, brightness);
console.log(`LED brightness set to ${brightness}/255`);
}
});const ArduinoFirmata = require('arduino-firmata');
const arduino = new ArduinoFirmata();
arduino.connect();
arduino.on('connect', function() {
console.log('Arduino connected - Analog I/O ready');
// Read analog sensors periodically
setInterval(function() {
const pot = arduino.analogRead(0); // Potentiometer
const light = arduino.analogRead(1); // Light sensor
const temp = arduino.analogRead(2); // Temperature sensor
console.log(`Sensors - Pot: ${pot}, Light: ${light}, Temp: ${temp}`);
// Use potentiometer to control LED brightness
const brightness = Math.round((pot / 1023) * 255);
arduino.analogWrite(9, brightness);
}, 1000);
// Real-time analog monitoring for immediate responses
arduino.on('analogChange', function(event) {
// Quick response to light sensor changes
if (event.pin === 1) {
if (event.value < 300) { // Dark environment
arduino.analogWrite(10, 200); // Turn on status LED
} else { // Bright environment
arduino.analogWrite(10, 50); // Dim status LED
}
}
});
});Arduino PWM operates at approximately 490 Hz (pins 5 and 6) or 980 Hz (other pins) with 8-bit resolution:
Arduino analog readings are relative to the reference voltage:
// Pin modes for analog operations
ArduinoFirmata.ANALOG = 2; // Analog input mode
ArduinoFirmata.PWM = 3; // PWM output modeNote: Analog pins can also be used as digital pins by referencing their digital pin numbers (14-19).
// Temperature sensor (LM35) - converts reading to Celsius
const tempReading = arduino.analogRead(0);
const voltage = (tempReading * 5.0) / 1024;
const temperature = voltage * 100; // LM35 outputs 10mV per degree C
console.log(`Temperature: ${temperature.toFixed(1)}°C`);// Control DC motor speed with potentiometer
const speedControl = arduino.analogRead(0);
const motorSpeed = Math.round((speedControl / 1023) * 255);
arduino.analogWrite(9, motorSpeed); // Motor connected to pin 9// Smooth LED fade effect
let brightness = 0;
let fadeDirection = 1;
setInterval(function() {
arduino.analogWrite(9, brightness);
brightness += fadeDirection * 2;
if (brightness >= 255) {
fadeDirection = -1;
} else if (brightness <= 0) {
fadeDirection = 1;
}
}, 10);Analog I/O operations integrate with the event system for real-time monitoring. See Event System for complete event documentation including analog change events.
Install with Tessl CLI
npx tessl i tessl/npm-arduino-firmata