Node Programming Models 01204525 Wireless Sensor Networks and Internet of Things Chaiporn Ja Jaikaeo (c (chaiporn.j@ku.ac.th) Department of f Computer Engineering Kasetsart University Materials taken from lecture slides by Karl and Willig Last updated: 2018-09-08 Cliparts taken from openclipart.org
Outline • Microcontroller programming ◦ Software development cycle • Operating Systems and Execution environments • Concurrent programming ◦ Event-driven programming model ◦ Multithreaded programming model ◦ Coroutines 2
Typical Development Process • Firmware flashing with an external chip programmer Sou ource e cod ode (C/ (C/Assembly) Microcontroller Cross Compiler/Assembler Serial/USB Machine cod ode 010101 port 011101 Uploader (h (hex/binary) 110110 Chip Programmer 3
Typical Development Process • Firmware flashing with on-chip bootstrap loader Sou ource e cod ode (C/Assembly) (C/ Microcontroller Cross Compiler/Assembler flash Serial/USB memory Machine cod ode 010101 port 011101 Uploader (h (hex/binary) Bootstrap 110110 Loader (BSL) 4
Typical Development Process • Script uploading with MicroPython firmware Sou ource e cod ode (Pyth (P ython) Microcontroller flash Serial/USB memory port Uploader MicroPython 5
OS and Execution Environments • Usual operating system goals ◦ Make access to device resources abstract (virtualization) ◦ Protect resources from concurrent access • Usual means ◦ Protected operation modes of the CPU ◦ Process with separate address spaces • These are not available in microcontrollers ◦ No separate protection modes, no MMU ◦ Would make devices more expensive, more power-hungry 6
Levels of Abstraction • Direct hardware access (bare-metal) ◦ Pure C/C++/Assembly • Hardware abstraction layer ◦ E.g., C/C++ using Arduino-provided libraries • Task scheduling ◦ Allows concurrency among multiple tasks in the same app • Resource Virtualization ◦ Makes some limited resources (e.g., timers) virtually available ◦ Memory usually not virtualized 7
Case Study #1: Tmote Sky 8
Case Study #2: IWING-MRF Analog/Digital sensor Radio connectors transceiver UART Connector 8-bit AVR Microcontroller USB Connector (for reprogramming and power) External battery connector 9
Tmote Sky: Schematic 10
IWING-MRF: Schematic 11
Tmote Sky: LED Blinking Code #include <msp430x16x.h> int main () Stop watchdog timer { WDTCTL = WDTPW | WDTHOLD ; P5DIR |= ( 1 << 6 ); Make pin P5.6 output for (;;) { Send logic 1 to pin P5.6 P5OUT |= ( 1 << 6 ); __delay_cycles ( 500000L ); P5OUT &= ~( 1 << 6 ); Send logic 0 to pin P5.6 __delay_cycles ( 500000L ); } return 0 ; } 12
IWING-MRF: LED Blinking Code #include <avr/io.h> #include <util/delay.h> #define F_CPU 12000000L main () { Make pin PD5 output DDRD |= ( 1 << 5 ); while ( 1 ) { PORTD &= ~( 1 << 5 ); Send logic 0 to pin PD5 _delay_ms ( 500 ); PORTD |= ( 1 << 5 ); Send logic 1 to pin PD5 _delay_ms ( 500 ); } } 13
Tmote Sky: Compiling • Tmote Sky uses MSP430 chip by Texas Instruments • It requires MSP430 cross-compiler $ msp430-gcc -mmcu=msp430f1611 -o blink.elf blink.c 14
IWING-MRF: Compiling • IWING-MRF uses AVR chip by Atmel/Microchip • It requires the AVR cross-compiler $ avr-gcc -mmcu=atmega328p – o blink.elf blink.c 15
Hardware Abstraction Layer Tmote Sky API Implementation Tmote Sky Hardware 16
Hardware Abstraction Layer IWING-MRF API Implementation IWING-MRF Hardware 17
LED Blinking: Arduino Code • With appropriate Arduino ports for MSP430 and AVR provided, the following code can be used in both Tmote Sky and IWING-MRF with minimal change #define LED 13 void setup () { pinMode ( LED , OUTPUT ); } void loop () { digitalWrite ( LED , HIGH ); delay ( 500 ); digitalWrite ( LED , LOW ); delay ( 500 ); } 18
LED Blinking: MicroPython Code • MicroPython provides both a hardware abstraction layer and an execution environment • A Python "app" is interpreted by MicroPython firmware from machine import Pin from time import sleep led = Pin ( 2 , Pin . OUT ) while True : led . value ( 1 ) sleep ( 0.5 ) led . value ( 0 ) sleep ( 0.5 ) 19
Concurrent Programming Models • IoT applications tend to get too complex to be implemented as a sequential program • E.g., the app needs to ◦ Monitor various sensor status ◦ Wait for and respond to user switch ◦ Wait for and respond to requests from the network 20
Example: Concurrent Tasks • Create an application that performs the following subtasks concurrently ◦ Subtask#1 repeatedly turns LED on and off every 500 milliseconds ◦ Subtask#2 when the switch (IO0) is pressed, displays the number of total switch presses on the OLED display 21
Setting Up LED and Switch • On-board LED (GPIO2) from machine import Pin led = Pin ( 2 , Pin . OUT ) led . value ( 1 ) # turn LED on led . value ( 0 ) # turn LED off • On-board SW (GPIO0) from machine import Pin sw = Pin ( 0 , Pin . IN ) if sw . value == 0 : print ( "SW is pressed" ) else : print ( "SW is released" ) 22
Wiring the OLED Display • Connect VCC/GND to OLED board • Connect Pins GPIO4 and GPIO5 to OLED's SCL and SDA, respectively 23
Controlling the OLED Display from machine import Pin, I2C import ssd1306 import time i2c = I2C ( scl = Pin ( 4 ), sda = Pin ( 5 )) oled = ssd1306 . SSD1306_I2C ( 128 , 64 , i2c ) while True : oled . text ( "Hello" , 0 , 0 ) # display "Hello" at (0,0) time . sleep ( 1 ) oled . fill ( 0 ) # clear screen oled . text ( "Goodbye" , 0 , 10 ) # display "Goodbye" at (0,10) oled . show () time . sleep ( 1 ) oled . fill ( 0 ) # clear screen oled . show () 24
Subtask #1 Only (No Concurrency) repeatedly turns LED on and off every 500 milliseconds from machine import Pin import time led = Pin ( 2 , Pin . OUT ) while True : led . value ( 1 ) time . sleep ( 0.5 ) led . value ( 0 ) time . sleep ( 0.5 ) 25
Subtask #2 Only (No Concurrency) displays total switch count on OLED from machine import Pin , I2C import ssd1306 import time sw = Pin ( 0 , Pin . IN ) i2c = I2C ( scl = Pin ( 4 ), sda = Pin ( 5 )) oled = ssd1306 . SSD1306_I2C ( 128 , 64 , i2c ) count = 0 while True : while sw . value () != 0 : time . sleep ( 0.01 ) # wait until switch is pressed count += 1 oled . fill ( 0 ) # clear screen oled . text ( str ( count ), 0 , 0 ) oled . show () while sw . value () != 1 : time . sleep ( 0.01 ) # wait until switch is released 26
Attempt to Combine Subtasks • Simply combining the from machine import Pin , I2C import ssd1306 import time two subtasks in a led = Pin ( 2 , Pin . OUT ) sequential manner sw = Pin ( 0 , Pin . IN ) i2c = I2C ( scl = Pin ( 4 ), sda = Pin ( 5 )) will NOT achieve oled = ssd1306 . SSD1306_I2C ( 128 , 64 , i2c ) count = 0 what we expected while True : # Subtask 1 led . value ( 1 ) blocking time . sleep ( 0.5 ) led . value ( 0 ) blocking time . sleep ( 0.5 ) # Subtask 2 blocking while sw . value () != 0 : time . sleep ( 0.01 ) # wait until switch is pressed count += 1 oled . fill ( 0 ) # clear screen oled . text ( str ( count ), 0 , 0 ) oled . show () while sw . value () != 1 : blocking time . sleep ( 0.01 ) # wait until switch is released 27
Concurrent Programming Models • Event driven • Multithreading • Coroutines 28
Event-Driven Model • Perform regular processing or be idle • React to events when they happen immediately • To save power, CPU can be put to sleep during idle Idle/regular Radio event handler processing Sensor event handler 29
Event-Driven Code import time # I/O setup import micropython led = Pin ( 2 , Pin . OUT ) from machine import Pin , I2C , Timer sw = Pin ( 0 , Pin . IN ) import ssd1306 i2c = I2C ( scl = Pin ( 4 ), sda = Pin ( 5 )) oled = ssd1306 . SSD1306_I2C ( 128 , 64 , i2c ) def handle_switch( pin ): count = 0 micropython . schedule ( switch_pressed , None ) # initialize event triggers def handle_timer( timer ): timer = Timer ( 0 ) micropython . schedule ( timer_fired , None ) timer . init ( period = 500 , def switch_pressed( arg ): mode = Timer . PERIODIC , global count callback = handle_timer ) count += 1 sw . irq ( oled . fill ( 0 ) trigger = Pin . IRQ_FALLING , oled . text ( str ( count ), 0 , 0 ) handler = handle_switch ) oled . show () time . sleep ( 0.01 ) # prevent sw bouncing while True : pass def timer_fired( arg ): led . value ( 1 - led . value ()) Ideally, CPU should go to sleep here instead of idle loop 30
Problem with Event-Driven Model • Unstructured code flow Very much like programming with GOTOs! 31
Multithreading Model Handle subtask#1 Handle subtask#2 • Based on interrupts, context switching • Difficulties ◦ Too many context switches ◦ Each process required its own stack • Not much of a problem on modern microcontrollers OS-mediated process switching 32
Recommend
More recommend