Embedded Javascript
How I found running Javascript on microprocessors (can) make sense
Iain Nash
About Me
Software Engineer in NYC
@ Oscar Health
Studied Computer Engineering
Still often tinker with Hardware
My first microcontroller project:
A human-aware missile launcher
My latest microcontroller project:
Live heartrate and motion streaming sensor
First, an overview.
Then, a step by step guide to run JS on an ESP32.
Goal for today:
Show the current temperature on a webpage
Arduino?
C ARM Code
Compiling Custom Interpreters?!
PIC
Arduino
ESP32
void SetupUltrasonic(void) {
T1CKPS1 = 0;
T1CKPS0 = 1;
TMR1CS = 0; // Internal clock (Fosc/4)
TMR1ON = 1; // Turn on Timer 1
TRISE = 0;
TRISC2 = 0;
}
void DelayTime(unsigned int count) {
unsigned int i, j;
for(i=0;i<count;i++){for(j=0;j<count;j++){}}
}
unsigned long int GetUltrasonicDistance(void){
unsigned int range, first_edge, second_edge;
unsigned long int distance, count;
PinDirection = 0; // Output to start sending ultrasonic sound
TRISC2 = 0;
TriggerAndEchoPin = 0;
DelayTime(TenMicroSecond);
TriggerAndEchoPin = 1; // Generate a pulse
DelayTime(TenMicroSecond); // Minimum pulse width
TriggerAndEchoPin = 0; // Turn off the pulse to start sending sound
PinDirection = 1; // Switch to input to receive echo
TRISC2 = 1;
CCP1IF = 0;
CCP1CON = 0b00000101; // Input capture on every rising edge
// Wait for rising edge
while(CCP1IF==0){}
first_edge = CCPR1H;
first_edge = first_edge<<8;
first_edge = first_edge + CCPR1L;
CCP1IF = 0;
CCP1CON = 0b00000100; //Input capture on every falling edge
//DelayTime(TenMicroSecond); /minimum pulse width
while(CCP1IF==0){} //waiting for falling edge
Arduino
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600); // Starts the serial communication
}
void loop() {
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);
}
JS
const trigger = Cfg.getPin('trigger');
const pwmMotor = Cfg.getPin('motor');
const ultrasonic = require('Ultrasonic').init(trigger);
const motor = require('Motor').init(pwmMotor);
ultrasonic.on('range', function(amount) {
motor.setSpeed(amount > 100 ? 10 : 100);
});
ESP8266
Inexpensive network interface board
made by Expressif
Often used in conjuction with an Arduino / PIC
Developing on ESP8266
ESP32
- Low cost
- Many hardware interfaces
- Built-in wifi and bluetooth
- Dual-core processor running at 160/240 MHz
- Open(ish) development toolchain
- Many development boards
Many development boards
Lolin32 by Wemos
https://wiki.wemos.cc/products:lolin32:lolin32
Espruino
Web IDE Demo
Espruino IDE
Espruino is Full-Stack Javascript
How I found Mongoose OS
- Worked on running JS in my free time with Espruino
- Limited environment, somewhat unstable
- Development was more predictable with C
Mongoose OS
IOT Operating System
Mongoose OS
Setting up a simple environment
- Debugging serial ports, voltages
- Assembling the boards
- Choosing the right boards
Build (many)
simple projects
Temperature Sensor
Heart Rate Sensor
Motion Sensor
Be aware of protocols...
RPC
Cesanta
mJS
Install Options
Bash install script
Ubuntu Linux PPA repository
Flashing Firmware
Writing Code
let led = Cfg.get('pins.led');
GPIO.set_mode(led, GPIO.MODE_OUTPUT);
RPC.addHandler('SetLED', function(opts) {
GPIO.write(led, opts.on);
})
// GPIO pin which has a DHT sensor data wire connected
let pin = 16; // or use config
// Initialize DHT library
let dht = DHT.create(Cfg.get('pins.temp'), DHT.DHT22);
RPC.addHandler('GetTemp', function() {
let t = dht.getTemp();
let h = dht.getHumidity();
if (isNaN(h) || isNaN(t)) {
//print('Failed to read data from sensor');
return {temp: null, humidity: null};
}
return {temp: t, humidity: h};
});
// using js
// Publish to MQTT topic on a button press. Button is wired to GPIO pin 0
GPIO.set_button_handler(button, GPIO.PULL_UP, GPIO.INT_EDGE_NEG, 200, function() {
let message = getInfo();
let ok = MQTT.pub(topic, message, 1);
print('Published:', ok, topic, '->', message);
}, null);
// Monitor network connectivity.
Event.addGroupHandler(Net.EVENT_GRP, function(ev, evdata, arg) {
let evs = '???';
if (ev === Net.STATUS_DISCONNECTED) {
evs = 'DISCONNECTED';
} else if (ev === Net.STATUS_CONNECTING) {
evs = 'CONNECTING';
} else if (ev === Net.STATUS_CONNECTED) {
evs = 'CONNECTED';
} else if (ev === Net.STATUS_GOT_IP) {
evs = 'GOT_IP';
}
print('== Net event:', ev, evs);
}, null);
// using js
// Publish to MQTT topic on a button press. Button is wired to GPIO pin 0
GPIO.set_button_handler(button, GPIO.PULL_UP, GPIO.INT_EDGE_NEG, 200, function() {
let message = getInfo();
let ok = MQTT.pub(topic, message, 1);
print('Published:', ok, topic, '->', message);
}, null);
// Monitor network connectivity.
Event.addGroupHandler(Net.EVENT_GRP, function(ev, evdata, arg) {
let evs = '???';
if (ev === Net.STATUS_DISCONNECTED) {
evs = 'DISCONNECTED';
} else if (ev === Net.STATUS_CONNECTING) {
evs = 'CONNECTING';
} else if (ev === Net.STATUS_CONNECTED) {
evs = 'CONNECTED';
} else if (ev === Net.STATUS_GOT_IP) {
evs = 'GOT_IP';
}
print('== Net event:', ev, evs);
}, null);
Making a project
Building Firmware
Mongoose OS Libraries
Hardware Config
Protocols...
http://coecsl.ece.illinois.edu/ge423/sensorprojects/1-wire_full.doc
Hardware Config
Go forth and create!
get in touch ~
github
@iainnash
iain@iain.in
Javascript on the ESP32
By Iain Nash
Javascript on the ESP32
- 2,137