Presentation is loading. Please wait.

Presentation is loading. Please wait.

Node Programming Models

Similar presentations


Presentation on theme: "Node Programming Models"— Presentation transcript:

1 Node Programming Models
Wireless Sensor Networks and Internet of Things Chaiporn Jaikaeo Department of Computer Engineering Kasetsart University Materials taken from lecture slides by Karl and Willig Cliparts taken from openclipart.org Last updated:

2 Outline Microcontroller programming
Software development cycle Operating Systems and Execution environments Concurrent programming Event-driven programming model Multithreaded programming model Coroutines

3 Typical Development Process
Firmware flashing with an external chip programmer Source code (C/Assembly) Microcontroller Cross Compiler/Assembler Chip Programmer Serial/USB port Machine code (hex/binary) 010101 011101 110110 Uploader

4 Typical Development Process
Firmware flashing with on-chip bootstrap loader Source code (C/Assembly) Microcontroller Cross Compiler/Assembler flash memory Bootstrap Loader (BSL) Serial/USB port Machine code (hex/binary) 010101 011101 110110 Uploader

5 Typical Development Process
Script uploading with MicroPython firmware Source code (Python) Microcontroller flash memory MicroPython Serial/USB port Uploader

6 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

7 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

8 Case Study #1: Tmote Sky

9 Case Study #2: IWING-MRF
Analog/Digital sensor connectors Radio transceiver UART Connector 8-bit AVR Microcontroller USB Connector (for reprogramming and power) External battery connector

10 Tmote Sky: Schematic

11 IWING-MRF: Schematic

12 Tmote Sky: LED Blinking Code
#include <msp430x16x.h> int main() { WDTCTL = WDTPW | WDTHOLD; P5DIR |= (1 << 6); for (;;) P5OUT |= (1 << 6); __delay_cycles(500000L); P5OUT &= ~(1 << 6); } return 0; Stop watchdog timer Make pin P5.6 output Send logic 1 to pin P5.6 Send logic 0 to pin P5.6

13 IWING-MRF: LED Blinking Code
#include <avr/io.h> #include <util/delay.h> #define F_CPU L main() { DDRD |= (1 << 5); while (1) PORTD &= ~(1 << 5); _delay_ms(500); PORTD |= (1 << 5); } Make pin PD5 output Send logic 0 to pin PD5 Send logic 1 to pin PD5

14 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

15 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

16 Hardware Abstraction Layer
Tmote Sky API Implementation Tmote Sky Hardware

17 Hardware Abstraction Layer
IWING-MRF API Implementation IWING-MRF Hardware

18 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);

19 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)

20 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

21 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

22 Setting Up LED and Switch
On-board LED (GPIO2) On-board SW (GPIO0) from machine import Pin led = Pin(2, Pin.OUT) led.value(1) # turn LED on led.value(0) # turn LED off from machine import Pin sw = Pin(0, Pin.IN) if sw.value == 0: print("SW is pressed") else: print("SW is released")

23 Wiring the OLED Display
Connect VCC/GND to OLED board Connect Pins GPIO4 and GPIO5 to OLED's SCL and SDA, respectively

24 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() oled.fill(0) # clear screen

25 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)

26 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

27 Attempt to Combine Subtasks
Simply combining the two subtasks in a sequential manner will NOT achieve what we expected from machine import Pin, I2C import ssd1306 import time led = Pin(2, Pin.OUT) sw = Pin(0, Pin.IN) i2c = I2C(scl=Pin(4), sda=Pin(5)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) count = 0 while True: # Subtask 1 led.value(1) time.sleep(0.5) led.value(0) # Subtask 2 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 blocking blocking blocking blocking

28 Concurrent Programming Models
Event driven Multithreading Coroutines

29 Idle/regular processing
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 processing Radio event handler Sensor event handler

30 Ideally, CPU should go to sleep here instead of idle loop
Event-Driven Code import time import micropython from machine import Pin, I2C, Timer import ssd1306 def handle_switch(pin): micropython.schedule(switch_pressed,None) def handle_timer(timer): micropython.schedule(timer_fired,None) def switch_pressed(arg): global count count += 1 oled.fill(0) oled.text(str(count),0,0) oled.show() time.sleep(0.01) # prevent sw bouncing def timer_fired(arg): led.value(1-led.value()) # I/O setup led = Pin(2, Pin.OUT) sw = Pin(0, Pin.IN) i2c = I2C(scl=Pin(4), sda=Pin(5)) oled = ssd1306.SSD1306_I2C(128,64,i2c) count = 0 # initialize event triggers timer = Timer(0) timer.init( period=500, mode=Timer.PERIODIC, callback=handle_timer) sw.irq( trigger=Pin.IRQ_FALLING, handler=handle_switch) while True: pass Ideally, CPU should go to sleep here instead of idle loop

31 Problem with Event-Driven Model
Unstructured code flow Very much like programming with GOTOs!

32 Multithreading Model Based on interrupts, context switching
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

33 Multithreading Code Thread #1 Thread #2 import _thread
from machine import Pin, I2C import ssd1306 import time def blink_led(): while True: led.value(1) time.sleep(.5) led.value(0) def count_switch(): count = 0 while sw.value() != 0: time.sleep(0.01) # wait until sw 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 sw is released # I/O setup led = Pin(2, Pin.OUT) sw = Pin(0, Pin.IN) i2c = I2C(scl=Pin(4), sda=Pin(5)) oled = ssd1306.SSD1306_I2C(128, 64, i2c) # create and run threads _thread.start_new_thread(blink_led, ()) _thread.start_new_thread(count_switch, ()) while True: pass Thread #1 Thread #2

34 Problems with Multithreads
Each thread requires its own stack to hold local variables Not much of a problem for modern microcontrollers Thread 1 Thread 2 Thread 3 Thread 4

35 Problems with Multithreads
Code employing preemptive threading library must ensure thread-safe operations

36 Coroutines Generalized subroutines Can be used to implement:
Allow multiple entry points for suspending and resuming execution at certain locations Can be used to implement: Cooperative multitasking Actor model of concurrency No worry about thread-safe operations

37 Subroutines vs. Coroutines
“Subroutines are a special case of coroutines.” --Donald Knuth Fundamental Algorithms. The Art of Computer Programming Routine 1 Routine 2 Routine 1 Routine 2 yield yield call return yield return yield call Subroutines Coroutines

38 Coroutines in MicroPython
Can be achieved using The uasyncio module with async/await pattern Generators

39 Coroutines: Code Require uasyncio module from machine import Pin, I2C
import uasyncio as asyncio import ssd1306 async def blink_led(): while True: await asyncio.sleep_ms(500) led.value(1-led.value()) async def count_switch(): count = 0 while sw.value() != 0: await asyncio.sleep_ms(1) count += 1 oled.fill(0) # clear screen oled.text(str(count),0,0) oled.show() while sw.value() == 0: # I/O setup led = Pin(2,Pin.OUT) sw = Pin(0,Pin.IN) i2c = I2C(scl=Pin(4), sda=Pin(5)) oled = ssd1306.SSD1306_I2C(128,64,i2c) # create and run async tasks loop = asyncio.get_event_loop() loop.create_task(blink_led()) loop.create_task(count_switch()) loop.run_forever()

40 Conclusion Microcontroller programming requires cross-compiler to build a firmware, which must be uploaded to the chip IoT devices usually do not require full-featured operating systems; only hardware abstraction and task scheduling Hardware abstraction allows code reuse across different platforms Complex applications often require concurrency Event-driven programming model Multithreaded programming model Coroutines


Download ppt "Node Programming Models"

Similar presentations


Ads by Google