Node Programming Models 01204525 Wireless Sensor Networks and - - PowerPoint PPT Presentation

node programming models
SMART_READER_LITE
LIVE PREVIEW

Node Programming Models 01204525 Wireless Sensor Networks and - - PowerPoint PPT Presentation

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


slide-1
SLIDE 1

Node Programming Models

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 Cliparts taken from openclipart.org

01204525 Wireless Sensor Networks and Internet of Things

Last updated: 2018-09-08

slide-2
SLIDE 2

2

Outline

  • Microcontroller programming
  • Software development cycle
  • Operating Systems and Execution environments
  • Concurrent programming
  • Event-driven programming model
  • Multithreaded programming model
  • Coroutines
slide-3
SLIDE 3

3

  • Firmware flashing with an external chip programmer

Typical Development Process

Sou

  • urce

e cod

  • de

(C/ (C/Assembly) Cross Compiler/Assembler Machine cod

  • de

(h (hex/binary)

010101 011101 110110

Microcontroller

Serial/USB port

Chip Programmer Uploader

slide-4
SLIDE 4

4

  • Firmware flashing with on-chip bootstrap loader

Typical Development Process

flash memory

Bootstrap Loader (BSL)

Microcontroller

Serial/USB port

Sou

  • urce

e cod

  • de

(C/ (C/Assembly) Cross Compiler/Assembler Machine cod

  • de

(h (hex/binary)

010101 011101 110110

Uploader

slide-5
SLIDE 5

5

  • Script uploading with MicroPython firmware

Typical Development Process

flash memory

MicroPython

Microcontroller

Serial/USB port

Sou

  • urce

e cod

  • de

(P (Pyth ython) Uploader

slide-6
SLIDE 6

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
slide-7
SLIDE 7

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
slide-8
SLIDE 8

8

Case Study #1: Tmote Sky

slide-9
SLIDE 9

9

Case Study #2: IWING-MRF

Radio transceiver 8-bit AVR Microcontroller USB Connector (for reprogramming and power) Analog/Digital sensor connectors External battery connector UART Connector

slide-10
SLIDE 10

10

Tmote Sky: Schematic

slide-11
SLIDE 11

11

IWING-MRF: Schematic

slide-12
SLIDE 12

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); __delay_cycles(500000L); } return 0; } Make pin P5.6 output Send logic 1 to pin P5.6 Send logic 0 to pin P5.6 Stop watchdog timer

slide-13
SLIDE 13

13

IWING-MRF: LED Blinking Code

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

slide-14
SLIDE 14

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

slide-15
SLIDE 15

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

slide-16
SLIDE 16

16

Hardware Abstraction Layer

Tmote Sky Hardware Tmote Sky API Implementation

slide-17
SLIDE 17

17

Hardware Abstraction Layer

IWING-MRF Hardware IWING-MRF API Implementation

slide-18
SLIDE 18

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); delay(500); }

slide-19
SLIDE 19

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) sleep(0.5)

slide-20
SLIDE 20

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
slide-21
SLIDE 21

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

slide-22
SLIDE 22

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

slide-23
SLIDE 23

23

Wiring the OLED Display

  • Connect VCC/GND to OLED board
  • Connect Pins GPIO4 and GPIO5 to OLED's SCL and SDA, respectively
slide-24
SLIDE 24

24

Controlling the OLED Display

from machine import Pin, I2C import ssd1306 import time i2c = I2C(scl=Pin(4), sda=Pin(5))

  • led = ssd1306.SSD1306_I2C(128, 64, i2c)

while True:

  • led.text("Hello",0,0)

# display "Hello" at (0,0) time.sleep(1)

  • led.fill(0) # clear screen
  • led.text("Goodbye",0,10)

# display "Goodbye" at (0,10)

  • led.show()

time.sleep(1)

  • led.fill(0)

# clear screen

  • led.show()
slide-25
SLIDE 25

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) time.sleep(0.5)

slide-26
SLIDE 26

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

  • led = 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

  • led.fill(0)

# clear screen

  • led.text(str(count),0,0)
  • led.show()

while sw.value() != 1: time.sleep(0.01) # wait until switch is released

slide-27
SLIDE 27

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

  • led = ssd1306.SSD1306_I2C(128, 64, i2c)

count = 0 while True: # Subtask 1 led.value(1) time.sleep(0.5) led.value(0) time.sleep(0.5) # Subtask 2 while sw.value() != 0: time.sleep(0.01) # wait until switch is pressed count += 1

  • led.fill(0)

# clear screen

  • led.text(str(count),0,0)
  • led.show()

while sw.value() != 1: time.sleep(0.01) # wait until switch is released

blocking blocking blocking blocking

slide-28
SLIDE 28

28

Concurrent Programming Models

  • Event driven
  • Multithreading
  • Coroutines
slide-29
SLIDE 29

29

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

slide-30
SLIDE 30

30

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

  • led.fill(0)
  • led.text(str(count),0,0)
  • led.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))

  • led = 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

slide-31
SLIDE 31

31

Problem with Event-Driven Model

  • Unstructured code flow

Very much like programming with GOTOs!

slide-32
SLIDE 32

32

Multithreading Model

  • Based on interrupts, context

switching

  • Difficulties
  • Too many context switches
  • Each process required its own stack
  • Not much of a problem on

modern microcontrollers

Handle subtask#1 Handle subtask#2

OS-mediated process switching

slide-33
SLIDE 33

33

Multithreading Code

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) time.sleep(.5) def count_switch(): count = 0 while True: while sw.value() != 0: time.sleep(0.01) # wait until sw is pressed count += 1

  • led.fill(0)

# clear screen

  • led.text(str(count),0,0)
  • led.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))

  • led = 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

slide-34
SLIDE 34

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

slide-35
SLIDE 35

35

Problems with Multithreads

  • Code employing preemptive threading library must ensure

thread-safe operations

slide-36
SLIDE 36

36

Coroutines

  • Generalized subroutines
  • 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

36

slide-37
SLIDE 37

37

Routine 2

Subroutines vs. Coroutines

Routine 1

Subroutines

Routine 2 Routine 1

Coroutines

call call return return yield yield yield yield “Subroutines are a special case of coroutines.”

  • -Donald Knuth

Fundamental Algorithms. The Art of Computer Programming

slide-38
SLIDE 38

38

Coroutines in MicroPython

  • Can be achieved using
  • The uasyncio module with async/await pattern
  • Generators
slide-39
SLIDE 39

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 True: while sw.value() != 0: await asyncio.sleep_ms(1) count += 1

  • led.fill(0)

# clear screen

  • led.text(str(count),0,0)
  • led.show()

while sw.value() == 0: await asyncio.sleep_ms(1) # I/O setup led = Pin(2,Pin.OUT) sw = Pin(0,Pin.IN) i2c = I2C(scl=Pin(4), sda=Pin(5))

  • led = 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()

slide-40
SLIDE 40

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