Skip to content

Examples

The following are a list of examples for core.zerynth.stdlib

Hello World

The simplest example to be tried for starting with embedded development

tags: [First Steps, Serial] groups:[First Steps]

main.py

###############################################################################
# Hello Zerynth
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

# import the streams module, it is needed to send data around
import streams

# open the default serial port, the output will be visible in the serial console
streams.serial()  

# loop forever
while True:
    print("Hello Zerynth!")   # print automatically knows where to print!
    sleep(1000)

The "Hello World" of embedded devices

Just configure a digital pin as output driving it ON and OFF every sec to blink the attached LED.

tags: [Digital I/O, First Steps] groups:[First Steps]

main.py

###############################################################################
# Led Blink
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

# D0 to D127 represent the names of digital pins
# On most Arduino-like boards Pin D13 has an on-board LED connected.
# However Zerynth abstracts the board layout allowing to use LED0, LED1, etc as led names.
# In this example LED0 is used.

pinMode(LED0,OUTPUT)

# loop forever
while True:
    digitalWrite(LED0, HIGH)  # turn the LED ON by setting the voltage HIGH
    sleep(1000)               # wait for a second
    digitalWrite(LED0, LOW)   # turn the LED OFF by setting the voltage LOW
    sleep(1000)               # wait for a second

Digital Read Basics

The basic definition of digitalRead() in ZERYNTH has the same behaviour of Arduino digitalRead().

In this example simple digitalRead use is reported

tags: [First Steps,Digital Read ADC] groups:[First Steps]

main.py

################################################################################
# Digital Read Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

# create a serial port stream with default parameters  
streams.serial()

# configure pin D5 in input mode
pinMode(D5, INPUT_PULLUP)

# loop forever, printing the value of D5
while True:
    print(digitalRead(D5))
    sleep(500)  

ADC Analog to Digital Acquisition Basics

The function for Analog to Digital convertion in ZERYNTH is adc.read()

The complete definition is adc.read(pin, samples=1)

In this example simple ADC single pin acquisition and advanced multi sample ADC acquisition are reported.

In ZERYNTH ADC is also available as builtin analogRead() with the same signature of adc.read(). analogRead() is available only for compatibility with the Arduino world and will be deprecated in future versions of ZERYNTH.

tags: [First Steps,Analog Read ADC] groups:[First Steps]

main.py

################################################################################
# Analog Read
# 
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams  # import the streams module
import adc      # import the adc driver 

# create a stream linked to the default serial port
streams.serial() 

while True:

# Basic usage of ADC for acquiring the analog signal from a pin   
    value = adc.read(A0)
    print("One sample:",value)

# The complete definition of adc.read() is adc.read(pin, samples=1) 
# For an advanced usage of adc.read refer to the official Zerynth documentation

#acquire 10 samples with default sampling period    
    value2 = adc.read(A0,10)
    print("10 samples:\n",value2)

#acquire 3 samples from the first 4 analog pins of the board with default sampling period    
    value3= adc.read([A0,A1,A2,A3],3)
    print("3 samples from A0, A1, A2 and A3:\n",value3)

    print()
    sleep(300)

ADC Analog to Digital Acquisition with Voltage Conversion

This basic examples shows how to read an analog voltage from pin 0, converts it to the corresponding voltage, and prints the result to the serial monitor. To test it user can attach the center pin of a potentiometer to pin A0, and the other pins respectively to to +3.3V and GND.

tags: [Analog Read ADC, Sensors, First Steps]
groups:[First Steps]

main.py

################################################################################
# Analog Read to Voltage
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import adc      # import the adc module  

#create a serial port stream with default parameters
streams.serial()

while True:

    #read the input on analog pin 0
    sensor_value = adc.read(A0)

    #convert the analog reading (which goes from 0 - 4095.0) to a voltage (0 - 3.3V):
    voltage = sensor_value * (3.3 / 4095.0)

    #print out the raw and converted values:
    print("sensor raw value:", sensor_value,"Voltage:",voltage)

    sleep(300)

ZERYNTH Oscilloscope

Simple usage of the analog acquisition and of the Python smart print functions. The example shows how to print to the serial console the values read on an analog pin in a "scope" like graphicspretty way.

tags: [First Steps, Analog Read ADC, Serial] groups:[First Steps]

main.py

###############################################################################
# Zerynth oscilloscope
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

import streams
import adc

streams.serial()

while True:
    value = adc.read(A4)
    conv = value*80//4095
    print("|","#"*conv," "*(80-conv),"|")
    sleep(200)

Serial Port Read/Write Basics

Basic examples of read and write data through a serial port. In this example a serial port instance is created allowing use of various methods.

tags:[Serial, First Steps] groups:[First Steps]

main.py

################################################################################
# Serial Port Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
# creates a serial port and name it "s"
s=streams.serial()

while True:
    print("Write some chars on the serial port and terminate with \\n (new line)")
    line=s.readline() # read and return any single character available on the serial port until a \n is found
    print("You wrote:", line)
    print()
    sleep (300)

This examples shows how to drive various behaviours taking as input an analog signal acquired through ADC fro driving three loop implemented as separated threads. In particular, the implemented scripts drives three LEDs at three different frequencies calculated on the basis of the acquired analog signal.

The example is implemented using 4 threads that run in parallel. One thread is used for acquiring the analog signal and convert the acquired raw value in blinking frequencies usable by the LED driving threads. The other three threads are used to instantiate a generic blinking function that drive a PIN where a LED is connected.

tags:[Multi-Thread, First Steps, Analog Read ADC] groups:[First Steps]

main.py

################################################################################
# Sensor Driven Multi-Blink
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# This example requires an analog sensor and three LEDs
import streams
import adc

# create a serial port stream with default parameters
streams.serial()

# set the A1 pin as analog input and D8, D9, D10 as outputs to drive the LEDs. 
pinMode(A1,INPUT_ANALOG)
pinMode(D10,OUTPUT)
pinMode(D9,OUTPUT)
pinMode(D8,OUTPUT)

# creates two arrays for storing global variables to be used in the blinking threads
freq=[1,1,1]        
pin=[D8,D9,D10]    

# define the generic blinking function to be used for driving the LEDs
# this function takes as input the index identifying the LED, then uses the global freq and pin arrays to dynamically drive the LEDs
def blink(Npin):
    while True:
        digitalWrite(pin[Npin],HIGH)
        sleep(freq[Npin])
        digitalWrite(pin[Npin],LOW)
        sleep(freq[Npin])

# define an analog sensor sampling function that acquires the raw data and converts it to the three LED frequencies
def sampling():
    global freq
    while True:
        value = adc.read(A1)
        freq[0] = value//10
        freq[1] = freq[0] * 2
        freq[2] = freq[0] * 4
        sleep(50)

# launch the four threads        
thread(sampling)
thread(blink,0)
thread(blink,1)
thread(blink,2)

# The main loop is used only for printing out at reasonable speed the calculated frequencies in term of waiting times 
while True:
    print("Wait times are", freq)
    sleep(500)

Multi-Thread Basics

This examples shows the basics of ZERYNTH multi-threading In ZERYNTH a thread require a function to be executed as input for the definition the same function can be instanced by various thread giving you the possibility to write very concise and readable code. In this example 4 threads are created as instances of the same function where different parameters are passed to the function when the thread is initialized

Note that the while True main loop typical of imperative programming is not present in this code. ZERYNTH allows pure thread driven implementation!

tags: [First Steps, Multi-Thread]
groups:[First Steps]

main.py

################################################################################
# Multi-Thread Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

# create a serial port with default parameters
streams.serial()

# Define a function to be used in the various threads.
# Parameters are passed to the function when the thread is created and then used in the thread loop.
# To be continuously executed by a thread a function requires an infinite loop,
# otherwise when the function terminates the thread is closed

def threadfn(number,delay):    

    while True:                    
        print("I am the thread",number)
        print("I run every:",delay,"msec")
        print()                # just add an empty line for console output readability 
        sleep(delay)

# create the various threads using the same function but passing different parameters        
thread(threadfn,1,500)
thread(threadfn,2,1000)
thread(threadfn,3,1300)
thread(threadfn,4,800)

This examples shows how to use ZERYNTH threads for driving three LEDs with asymmetric and different blinking rates.

Each Thread in ZERYNTH is a sort of separated and parallel process that runs autonomously on your board. With threads you can design your algorithm architecture assuming parallelism that is typical of high level programming languages. In this code a function is defined and then instanced by three threads creating a pool of parallel processes where three LEDs are driven at different frequencies.

Moreover, thanks to Python argument passing, default values can be defined for function inputs. This way you can launch threads without specifying all the inputs required by the function, default values will fill the holes. In this case all the parameters following 'blink' are passed to the functions as arguments. thread(blink,pin,delayON,delayOFF) is equivalent to thread(blink(pin,delayON,delayOFF)).

tags: [Multi-Thread, First Steps, Digital I/O] groups:[First Steps]

main.py

################################################################################
# Multi-Blink
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# Initialize the digital pins where the LEDs are connected as output
pinMode(D2,OUTPUT)
pinMode(D8,OUTPUT)
pinMode(D5,OUTPUT)

# Define the 'blink' function to be used by the threads
def blink(pin,timeON=100,timeOFF=100): # delayON and delayOFF are optional parameters, used as default 
                                         # if not specified when you call the function
    while True:
        digitalWrite(pin,HIGH)   # turn the LED ON by making the voltage HIGH
        sleep(timeON)            # wait for timeON 
        digitalWrite(pin,LOW)    # turn the LED OFF by making the voltage LOW
        sleep(timeOFF)           # wait for timeOFF 

# Create three threads that execute instances of the 'blink' function.     
thread(blink,D2)             # D2 is ON for 100 ms and OFF for 100 ms, the default values of delayON an delayOFF
thread(blink,D8,200)         # D8 is ON for 200 ms and OFF for 100 ms, the default value of delayOFF
thread(blink,D5,500,200)     # D5 is ON for 500 ms and OFF for 200 ms

Serial Port Advanced

Advanced example of using a serial port for writing and sending data The examples shows how to read the entire serial port buffer or how to read a defined number of chars from the buffer. Moreover is also shown how to read a buffer until a \n newline terminator is found.

tags:[Serial, First Steps] groups:[First Steps]

main.py

################################################################################
# Serial Advanced
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

s = streams.serial()

# Testing various serial port reading methods

while True:
    print("write some chars and send it to the board")
    char=s.read() # read and return any single character available on the serial port one by one
    print("This is the first char you wrote:",char)
    print() # add a line space for improving the serial console ouput readability

    sleep(500) # waiting for the serial buffer to fill
    length=s.available() # check if data are available on the port and count them
    chars=s.read(length) # read all the bytes available in the buffer an return the bytearray 
    print("This are the other", length, "chars you wrote:",chars)
    print() # add a line space for improving the serial console view

    print("write a line ending it with return or enter")
    line=s.readline() # read until a line terminator \n is found, then return a bytearray
    print("This is the line you wrote:",line)

Input Capture Unit as PWM Analyzer

This examples shows how to use the Input Capture Unit of the board MCU for analysing a PWM signal The PWM is generated on PIN13 in order to have a feedbakc on the board embedded LED PIN13 is also connected through a wire with PIN2 on which the ICU capture is activated An interrupt is also attached on a PIN where a button is connected for changing the PWM duty.

Very Important: ICU and PWM are both timer powered embedded feature, it is impossible to run an ICU and a PWM on two pin controlled by the same timer channel. Please refer to the board pinout in order to select the proper pins for your board e.i: on a ST Nucleo this example use PWM2/1 for PIN13 and PWM⅓ for PIN2 so we are using two diferent embedded timers (first number on the PEM pin descrition)

Board setup:
PIN13-----PIN2 (shortcut the pins) BTNPin----GND (connect a button between a pin and GND)

tags: [First Steps, Input Capture Unit ICU, Interrupts, Analog Write PWM]
groups:[First Steps]

main.py

################################################################################
# Input Capture Unit as PWM Analyzer
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import pwm 
import icu
import streams

# create the serial port using default parameters  
streams.serial()

# define a pin where a button is connected, you can use the Nucleo button pin as input or change it with any other digital pin available

# this is the pin the button is connected to; for the various supported boards, Zerynth automatically translates it 
# to the board button. On Arduino DUE the user button isn't installed, so this line rises a compilation error.
# On Arduino DUE, change it to the pin your button is connected to or comment this line (see below)
buttonPin=BTN0


# define the ICU pin. D5 works with Arduino footprint boards while with Particle boards D0 can be used 
captPin=D5.ICU  # On Arduino like boards
#captPin=D0.ICU  # On Particle boards

# define the PWM pin. D13 works with Arduino footprint boards (and is also connected to a LED) while with Particle boards A4 can be used
pwmPin=D13.PWM # On Arduino like boards 
#pwmPin=A4.PWM # On Particle boards

# set the pin as input with PullUp, the button will be connected to ground
pinMode(buttonPin, INPUT_PULLUP)

# define a function for printing capture results on the serial port
def print_results(y):
    print("Time ON is:", y[0],"micros")
    print("Time OFF is:",y[1],"micros")
    print("Period is:", y[0]+y[1], "micros")
    print()

# define a global variable for PWM duty cycle and turn on the PWM

duty=10
pwm.write(pwmPin,100, duty,MICROS) #pwm.write needs (pn, period, duty, time_unit)

# define the function to be called for changing the PWM duty when the button is pressed
def pwm_control():
    global duty
    duty= duty+10
    if duty>=100:
        duty=0
    pwm.write(pwmPin, 100, duty,MICROS)
    print("Duty:", duty, "millis")

# Attach an interrupt on the button pin waiting for signal going from high to low when the button is pressed.
# pwm_control will be called when the interrupt is fired.
# If you are on Arduino DUE and you haven't connected any button comment the following line 
# you will not change the PWM duty but you can still test the ICU capture
onPinFall(buttonPin, pwm_control)

while True:
    # start an icu capture to be triggered when the pin rise.
    # this routine acquires 10 steps (HIGH or LOW states) or terminates after 50000 micros
    # this is a blocking function
    x = icu.capture(captPin,LOW_TO_HIGH,10,50000,MICROS)
    print("captured")
    # x is a list of step durations in microseconds, pass it to the printing function and check the serial console
    print_results(x)

    sleep(1000)

Timers Basics

Basic example of use of the timer module for monitoring the time during the program execution. Timers can be used as alternative to the Arduino Millis().

tags=[First Steps, Timers] groups:[First Steps]

main.py

################################################################################
# Timers Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import timers
import streams

# create a serial port with default parameters
streams.serial()

# create a new timer
t=timers.timer()
# start the timer
t.start()

minutes=0

while True:

    if t.get()>= 60000:        #check if 60 seconds are passed
        t.reset()              #timer can be reset
        minutes +=1
    seconds=t.get()//1000
    print("time is:", minutes,":",seconds) #just print the current value since timer start or last reset
    print("System time is:", timers.now(), "(millis)") #timers.now() gives the system time in milliseconds since program start
    print()

    sleep(500)                 #run every 500 millisec

String Formatting

Some example of Python string formatting with the modulo operator.

main.py

################################################################################
# strformat
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

streams.serial()

print("Starting!")
sleep(1000)

# a data tuple
tt = ("string",-21,15.23,32)
# a data dictionary
dd = {
      "thing":"string",
      "number":1,
      "float":1.0,
      "hex":32  
}

# let's format :)
while True:
    try:
        # basic formatting
        print("%% this is a %s, this is a %d, this is a %f, this is a %x, this is a %%"%tt)
        # named keys formatting
        print("%% this is a %(thing)s, this is a %(number)d, this is a %(float)f, this is a %(hex)x, this is a %%"%dd)
        # width & precision
        print("%s %8d %f %d"%tt)
        print("%s %08.7d %f %d"%tt)
        # width & precision & left alignment & sign
        print("%s %-010.9d %f %d"%tt)
        print("%s %-010.9d %2.0f %d"%tt)
        print("%s %-010.9d %2.5f %d"%tt)
        print("%s %-010.9d %12.5f %d"%tt)
        print("%s %-010.9d %-12.5f %d"%tt)
        print("%s %-010.9d %012.15f %d"%tt)
        print("%s %+010.9d %012.15f %d"%tt)
        print("%s % 010.9d %012.15f %d"%tt)
        # width & precision for strings
        print("%15.3s % 010.9d %012.15f %d"%tt)
        # variable width & precision
        print("%x %3.*d"%(123456,5,6))
    except Exception as e:
        print(e)
    sleep(5000)

Serial Port Read/Write Basics

Basic examples of read and write data through a serial port. In this example a serial port instance is created allowing use of various methods.

tags:[Serial, First Steps] groups:[First Steps]

main.py

################################################################################
# Serial Port Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
# creates a serial port and name it "s"
s=streams.serial()

while True:
    print("Write some chars on the serial port and terminate with \\n (new line)")
    line=s.readline() # read and return any single character available on the serial port until a \n is found
    print("You wrote:", line)
    print()
    sleep (300)

Serial Port Advanced

Advanced example of using a serial port for writing and sending data The examples shows how to read the entire serial port buffer or how to read a defined number of chars from the buffer. Moreover is also shown how to read a buffer until a \n newline terminator is found.

tags:[Serial, First Steps] groups:[First Steps]

main.py

################################################################################
# Serial Advanced
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

s = streams.serial()

# Testing various serial port reading methods

while True:
    print("write some chars and send it to the board")
    char=s.read() # read and return any single character available on the serial port one by one
    print("This is the first char you wrote:",char)
    print() # add a line space for improving the serial console ouput readability

    sleep(500) # waiting for the serial buffer to fill
    length=s.available() # check if data are available on the port and count them
    chars=s.read(length) # read all the bytes available in the buffer an return the bytearray 
    print("This are the other", length, "chars you wrote:",chars)
    print() # add a line space for improving the serial console view

    print("write a line ending it with return or enter")
    line=s.readline() # read until a line terminator \n is found, then return a bytearray
    print("This is the line you wrote:",line)

Digital Read Basics

The basic definition of digitalRead() in ZERYNTH has the same behaviour of Arduino digitalRead().

In this example simple digitalRead use is reported

tags: [First Steps,Digital Read ADC] groups:[First Steps]

main.py

################################################################################
# Digital Read Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

# create a serial port stream with default parameters  
streams.serial()

# configure pin D5 in input mode
pinMode(D5, INPUT_PULLUP)

# loop forever, printing the value of D5
while True:
    print(digitalRead(D5))
    sleep(500)  

The "Hello World" of embedded devices

Just configure a digital pin as output driving it ON and OFF every sec to blink the attached LED.

tags: [Digital I/O, First Steps] groups:[First Steps]

main.py

###############################################################################
# Led Blink
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

# D0 to D127 represent the names of digital pins
# On most Arduino-like boards Pin D13 has an on-board LED connected.
# However Zerynth abstracts the board layout allowing to use LED0, LED1, etc as led names.
# In this example LED0 is used.

pinMode(LED0,OUTPUT)

# loop forever
while True:
    digitalWrite(LED0, HIGH)  # turn the LED ON by setting the voltage HIGH
    sleep(1000)               # wait for a second
    digitalWrite(LED0, LOW)   # turn the LED OFF by setting the voltage LOW
    sleep(1000)               # wait for a second

ADC Analog to Digital Acquisition Basics

The function for Analog to Digital convertion in ZERYNTH is adc.read()

The complete definition is adc.read(pin, samples=1)

In this example simple ADC single pin acquisition and advanced multi sample ADC acquisition are reported.

In ZERYNTH ADC is also available as builtin analogRead() with the same signature of adc.read(). analogRead() is available only for compatibility with the Arduino world and will be deprecated in future versions of ZERYNTH.

tags: [First Steps,Analog Read ADC] groups:[First Steps]

main.py

################################################################################
# Analog Read
# 
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams  # import the streams module
import adc      # import the adc driver 

# create a stream linked to the default serial port
streams.serial() 

while True:

# Basic usage of ADC for acquiring the analog signal from a pin   
    value = adc.read(A0)
    print("One sample:",value)

# The complete definition of adc.read() is adc.read(pin, samples=1) 
# For an advanced usage of adc.read refer to the official Zerynth documentation

#acquire 10 samples with default sampling period    
    value2 = adc.read(A0,10)
    print("10 samples:\n",value2)

#acquire 3 samples from the first 4 analog pins of the board with default sampling period    
    value3= adc.read([A0,A1,A2,A3],3)
    print("3 samples from A0, A1, A2 and A3:\n",value3)

    print()
    sleep(300)

ADC Analog to Digital Acquisition with Voltage Conversion

This basic examples shows how to read an analog voltage from pin 0, converts it to the corresponding voltage, and prints the result to the serial monitor. To test it user can attach the center pin of a potentiometer to pin A0, and the other pins respectively to to +3.3V and GND.

tags: [Analog Read ADC, Sensors, First Steps]
groups:[First Steps]

main.py

################################################################################
# Analog Read to Voltage
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import adc      # import the adc module  

#create a serial port stream with default parameters
streams.serial()

while True:

    #read the input on analog pin 0
    sensor_value = adc.read(A0)

    #convert the analog reading (which goes from 0 - 4095.0) to a voltage (0 - 3.3V):
    voltage = sensor_value * (3.3 / 4095.0)

    #print out the raw and converted values:
    print("sensor raw value:", sensor_value,"Voltage:",voltage)

    sleep(300)

ZERYNTH Oscilloscope

Simple usage of the analog acquisition and of the Python smart print functions. The example shows how to print to the serial console the values read on an analog pin in a "scope" like graphicspretty way.

tags: [First Steps, Analog Read ADC, Serial] groups:[First Steps]

main.py

###############################################################################
# Zerynth oscilloscope
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

import streams
import adc

streams.serial()

while True:
    value = adc.read(A4)
    conv = value*80//4095
    print("|","#"*conv," "*(80-conv),"|")
    sleep(200)

This examples shows how to drive various behaviours taking as input an analog signal acquired through ADC fro driving three loop implemented as separated threads. In particular, the implemented scripts drives three LEDs at three different frequencies calculated on the basis of the acquired analog signal.

The example is implemented using 4 threads that run in parallel. One thread is used for acquiring the analog signal and convert the acquired raw value in blinking frequencies usable by the LED driving threads. The other three threads are used to instantiate a generic blinking function that drive a PIN where a LED is connected.

tags:[Multi-Thread, First Steps, Analog Read ADC] groups:[First Steps]

main.py

################################################################################
# Sensor Driven Multi-Blink
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# This example requires an analog sensor and three LEDs
import streams
import adc

# create a serial port stream with default parameters
streams.serial()

# set the A1 pin as analog input and D8, D9, D10 as outputs to drive the LEDs. 
pinMode(A1,INPUT_ANALOG)
pinMode(D10,OUTPUT)
pinMode(D9,OUTPUT)
pinMode(D8,OUTPUT)

# creates two arrays for storing global variables to be used in the blinking threads
freq=[1,1,1]        
pin=[D8,D9,D10]    

# define the generic blinking function to be used for driving the LEDs
# this function takes as input the index identifying the LED, then uses the global freq and pin arrays to dynamically drive the LEDs
def blink(Npin):
    while True:
        digitalWrite(pin[Npin],HIGH)
        sleep(freq[Npin])
        digitalWrite(pin[Npin],LOW)
        sleep(freq[Npin])

# define an analog sensor sampling function that acquires the raw data and converts it to the three LED frequencies
def sampling():
    global freq
    while True:
        value = adc.read(A1)
        freq[0] = value//10
        freq[1] = freq[0] * 2
        freq[2] = freq[0] * 4
        sleep(50)

# launch the four threads        
thread(sampling)
thread(blink,0)
thread(blink,1)
thread(blink,2)

# The main loop is used only for printing out at reasonable speed the calculated frequencies in term of waiting times 
while True:
    print("Wait times are", freq)
    sleep(500)

CAN Auto-baudrate

This example shows how to use the CAN interface library and how to detect baudrate.

main.py

# CAN Auto-baudrate
# Created at 2020-02-10 16:39:24.048614

from fortebit.polaris import polaris
import can

polaris.init()

print("CAN Bus Auto-Baudrate Example")

# Initialize CAN transceiver
pinMode(polaris.internal.PIN_CAN_STANDBY, OUTPUT)
digitalWrite(polaris.internal.PIN_CAN_STANDBY, LOW)
sleep(100)

def can_auto_baudrate():
    print("Start auto baudrate...")
    for bps in (1000000,800000,500000,250000,125000,100000,50000,10000):
        print("Try",bps,"bps")
        try:
            canbus = can.Can(CAN0, bps, options=can.OPTION_LISTEN_ONLY)
        except Exception as e:
            print(e)
            continue
        try:
            canbus.add_filter(0,0)
            canbus.receive(timeout=500)
            print("Found baudrate:",bps)
            canbus.done()
            return bps
        except TimeoutError:
            pass
        except Exception as e:
            print(e)
        print("Errors",canbus.get_errors())
        canbus.done()
    print("Auto baudrate failed!")
    return None

bps = None
while bps is None:
    bps = can_auto_baudrate()
    sleep(1000)

print("Start active listening at",bps,"bps")
canbus = can.Can(CAN0, bps)
canbus.add_filter(0,0)
while True:
    try:
        msg = canbus.receive()
        print("ID",hex(msg[0] & can.FRAME_EXT_MASK),"IDE",(msg[0] & can.FRAME_EXT_FLAG) != 0,"RTR",(msg[0] & can.FRAME_RTR_FLAG) != 0,"DLC",msg[1],"DATA",[hex(b) for b in msg[2]])
    except Exception as e:
        print(e)

Can Bus Example

This example shows how to use the CAN interface library.

main.py

# Can Bus Example
# Created at 2019-12-17 16:21:55.938660

from fortebit.polaris import polaris
import can

polaris.init()

print("CAN Bus Auto-Baudrate Example")

# Initialize CAN transceiver
pinMode(polaris.internal.PIN_CAN_STANDBY, OUTPUT)
digitalWrite(polaris.internal.PIN_CAN_STANDBY, LOW)
sleep(100)

canbus = can.Can(CAN0, 500000)

def can_rx(timeout=-1):
    print("rx, listening...")
    msg = canbus.receive(timeout=timeout)
    print("ID",hex(msg[0] & can.FRAME_EXT_MASK),"IDE",(msg[0] & can.FRAME_EXT_FLAG) != 0,"RTR",(msg[0] & can.FRAME_RTR_FLAG) != 0,"DLC",msg[1],"DATA",[hex(b) for b in msg[2]])

def abort_rx():
    sleep(1000)
    print("abort rx")
    canbus.abort_receive()
    sleep(500)
    print("resume rx")
    canbus.resume_receive()

def abort_tx():
    sleep(1000)
    print("abort tx")
    canbus.abort_transmit()
    sleep(500)
    print("resume tx")
    canbus.resume_transmit()

f0 = canbus.add_filter(0,0)
f1 = canbus.add_filter(0x123|can.FRAME_EXT_FLAG,can.FRAME_EXT_MASK|can.FRAME_EXT_FLAG)
print("Filters",f0,f1)
canbus.del_filter(f0)
f2 = canbus.add_filter(0x456,can.FRAME_STD_MASK)
f3 = canbus.add_filter(0x88|can.FRAME_RTR_FLAG,can.FRAME_STD_MASK|can.FRAME_RTR_FLAG)
print("Filters",f1,f2,f3)

print("tx std data")
canbus.transmit(0x456,8,b'abcdefgh')

print("tx ext remote")
canbus.transmit(0x123|can.FRAME_EXT_FLAG|can.FRAME_RTR_FLAG,8)

print("Errors",canbus.get_errors())

thread(abort_rx)
try:
    can_rx()
except Exception as e:
    print(e)
sleep(1000)
can_rx()
canbus.done()


# test standby/wakeup
digitalWrite(polaris.internal.PIN_CAN_STANDBY, HIGH)
sleep(100)

sleeping = True
def wakeup():
    global sleeping
    if sleeping:
        sleeping = False
        onPinFall(CANRX0, None)
        print("CAN wakeup")

pinMode(CANRX0,INPUT_PULLUP)
onPinFall(CANRX0, wakeup)

print("Going to sleep...")
while sleeping:
    sleep(10)

digitalWrite(polaris.internal.PIN_CAN_STANDBY, LOW)


canbus = can.Can(CAN0, 500000)
f0 = canbus.add_filter(0,0)
print("Timeout rx 3s...")
try:
    can_rx(timeout=3000)
except Exception as e:
    print(e)

thread(abort_tx)
id=0
while id <= can.FRAME_STD_MASK:
    try:
        canbus.transmit((id<<18)|can.FRAME_EXT_FLAG|can.FRAME_RTR_FLAG,id&7)
        canbus.transmit(id+6,(id&7)+1,b'abcdefgh')
    except Exception as e:
        print(e)
        sleep(100)
    #sleep(50)
    id += 15

print("Errors",canbus.get_errors())

while True:
    can_rx()
    print("Errors",canbus.get_errors())

canbus.done()

DAC Basic

A simple example to introduce Dac features.

main.py

################################################################################
# Dac Basic
#
# Created by Zerynth Team 2015 CC
# Authors: L. Rizzello
################################################################################

import streams
import adc # for analogRead

import dac


def readInput():
    while True:
        print("reading A1: ",analogRead(A1))
        sleep(500)

streams.serial()
pinMode(A1,INPUT)

# read input in a separate thread
thread(readInput)

my_dac = dac.DAC(D8.DAC)
my_dac.start()

# circular mode: continuously repeat the input buffer
my_dac.write([100,200,900,800],1000,MILLIS,circular=True)

Buzzer Driven through PWM

This example shows how to drive a buzzer using PWM. In the example a frequency ramp going from 100 Hz to 5 KHz is generated as drive. The frequency is converted in period to be used as input of the pwm.rite function that require period and pulse to be expressed in milli or micro seconds (measure unit can be selected as extra parameter of the pwm.write function). The PWM duty cycle is set to 50% driving the buzzer with a symmetric square wave.

tags:[First Steps, Input Capture Unit ICU, Sound]
groups:[First Steps]

main.py

################################################################################
# Buzzer with PWM
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import pwm

#create a serial port stream with default parameters  
streams.serial()

# the pin where the buzzer is attached to
buzzerpin = D8.PWM 

pinMode(buzzerpin,OUTPUT) #set buzzerpin to output mode
frequency=100             #define a variable to hold the played tone frequency

while True:
    period=1000000//frequency #we are using MICROS so every sec is 1000000 of micros. // is the int division, pwm.write period doesn't accept floats
    print("frequency is", frequency,"Hz")

    #set the period of the buzzer and the duty to 50% of the period
    pwm.write(buzzerpin,period,period//2,MICROS)

    # increment the frequency every loop
    frequency = frequency + 20 

    # reset period
    if frequency >= 5000:
        frequency=100

    sleep(100) 

LED Fade

This example shows hot to use PWM for fading a LED by changing the duty cycle in a for loop.

main.py

################################################################################
# LED Fade
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi,  D. Mazzei
###############################################################################

import pwm

duty=0

pinMode(LED0,OUTPUT) # set the LED pin as output:

while True:
    for i in range(-100,100,1):   # create a loop for ranging the duty cycle from 0 to 100 MICROS
        duty=100-abs(i)
        pwm.write(LED0.PWM,100,duty,MICROS)     # set the pwm at the calculated duty with a fixed period of 100 MICROS
        sleep(10) # update the PWM every 10 millis  

Input Capture Unit as PWM Analyzer

This examples shows how to use the Input Capture Unit of the board MCU for analysing a PWM signal The PWM is generated on PIN13 in order to have a feedbakc on the board embedded LED PIN13 is also connected through a wire with PIN2 on which the ICU capture is activated An interrupt is also attached on a PIN where a button is connected for changing the PWM duty.

Very Important: ICU and PWM are both timer powered embedded feature, it is impossible to run an ICU and a PWM on two pin controlled by the same timer channel. Please refer to the board pinout in order to select the proper pins for your board e.i: on a ST Nucleo this example use PWM2/1 for PIN13 and PWM⅓ for PIN2 so we are using two diferent embedded timers (first number on the PEM pin descrition)

Board setup:
PIN13-----PIN2 (shortcut the pins) BTNPin----GND (connect a button between a pin and GND)

tags: [First Steps, Input Capture Unit ICU, Interrupts, Analog Write PWM]
groups:[First Steps]

main.py

################################################################################
# Input Capture Unit as PWM Analyzer
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import pwm 
import icu
import streams

# create the serial port using default parameters  
streams.serial()

# define a pin where a button is connected, you can use the Nucleo button pin as input or change it with any other digital pin available

# this is the pin the button is connected to; for the various supported boards, Zerynth automatically translates it 
# to the board button. On Arduino DUE the user button isn't installed, so this line rises a compilation error.
# On Arduino DUE, change it to the pin your button is connected to or comment this line (see below)
buttonPin=BTN0


# define the ICU pin. D5 works with Arduino footprint boards while with Particle boards D0 can be used 
captPin=D5.ICU  # On Arduino like boards
#captPin=D0.ICU  # On Particle boards

# define the PWM pin. D13 works with Arduino footprint boards (and is also connected to a LED) while with Particle boards A4 can be used
pwmPin=D13.PWM # On Arduino like boards 
#pwmPin=A4.PWM # On Particle boards

# set the pin as input with PullUp, the button will be connected to ground
pinMode(buttonPin, INPUT_PULLUP)

# define a function for printing capture results on the serial port
def print_results(y):
    print("Time ON is:", y[0],"micros")
    print("Time OFF is:",y[1],"micros")
    print("Period is:", y[0]+y[1], "micros")
    print()

# define a global variable for PWM duty cycle and turn on the PWM

duty=10
pwm.write(pwmPin,100, duty,MICROS) #pwm.write needs (pn, period, duty, time_unit)

# define the function to be called for changing the PWM duty when the button is pressed
def pwm_control():
    global duty
    duty= duty+10
    if duty>=100:
        duty=0
    pwm.write(pwmPin, 100, duty,MICROS)
    print("Duty:", duty, "millis")

# Attach an interrupt on the button pin waiting for signal going from high to low when the button is pressed.
# pwm_control will be called when the interrupt is fired.
# If you are on Arduino DUE and you haven't connected any button comment the following line 
# you will not change the PWM duty but you can still test the ICU capture
onPinFall(buttonPin, pwm_control)

while True:
    # start an icu capture to be triggered when the pin rise.
    # this routine acquires 10 steps (HIGH or LOW states) or terminates after 50000 micros
    # this is a blocking function
    x = icu.capture(captPin,LOW_TO_HIGH,10,50000,MICROS)
    print("captured")
    # x is a list of step durations in microseconds, pass it to the printing function and check the serial console
    print_results(x)

    sleep(1000)

ICU Capture IR Packets

Basic example of use of the ICU feature for capturing IR signals acquired through an IR demodulator.

main.py

################################################################################
# ICU Capture IR Packets
#
# Created by Zerynth Team 2015 CC
# Authors: L. Rizzello, G. Baldi, D. Mazzei  
################################################################################

import icu
import streams
import pwm

streams.serial()

# Set the pin the IR receiver is connected to.
# In this example D2 is used: if you happen to have a TOI Shield on an Arduino compatible board
# you are good to go.
ir_pin = D2.ICU # when you want to use a particular pin function, just use the dot notation


def IR_capture():
    while True:
        print("Capturing...")
        # Starts capturing from the icu configured pin.
        # The capture starts from a selected trigger (in this case capture will start when the pin first goes from
        # HIGH to LOW).
        # The max number of samples to be collected and a maximum time window are specified.

        # Play with max number and time window to fit your remote protocol.
        # The following values are for the NEC IR (used by LG) protocol
        x = icu.capture(ir_pin,LOW,67,68,pull=HIGH)
        print(x,"\n captured n samples:",len(x))


# captures in a different thread
thread(IR_capture)

while True:
    print("alive!")
    sleep(1000)

Timers Basics

Basic example of use of the timer module for monitoring the time during the program execution. Timers can be used as alternative to the Arduino Millis().

tags=[First Steps, Timers] groups:[First Steps]

main.py

################################################################################
# Timers Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import timers
import streams

# create a serial port with default parameters
streams.serial()

# create a new timer
t=timers.timer()
# start the timer
t.start()

minutes=0

while True:

    if t.get()>= 60000:        #check if 60 seconds are passed
        t.reset()              #timer can be reset
        minutes +=1
    seconds=t.get()//1000
    print("time is:", minutes,":",seconds) #just print the current value since timer start or last reset
    print("System time is:", timers.now(), "(millis)") #timers.now() gives the system time in milliseconds since program start
    print()

    sleep(500)                 #run every 500 millisec

Timers Advanced Use

This example shows how ZERYNTH soft timers can be used to schedule functions execution. ZERYNTH timers can be used as program time counter through the timer.start attribute or as recursive callers through the timer.interval method that takes as input the elapsing interval and the function to be called. Moreover, it is also possible to activate a timer in one shot mode. In this case the function si called after the requested interval and then the timer stops

tags: [Timers, First Steps]
groups:[First Steps]

main.py

################################################################################
# Timers Advanced Use

# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import timers
import streams

# create a serial port with default parameters
streams.serial()

# create new timers
tsec=timers.timer()
tminute=timers.timer()     
tshoot=timers.timer()

seconds=0
minutes=0

# define a function to call when the timer for seconds elapses
def secondpassed():
    global seconds
    seconds +=1
    print(seconds,"  seconds")
    if seconds==60:
        seconds=0

# define a function to call when the timer for minutes elapses
def minutepassed():
    global minutes
    minutes +=1
    print(minutes,"  minutes")

# define a function to call when the one shot timer elapses
def shootpassed():
    print("1 second ago was 1:30")

# start the timers for minutes and seconds
tsec.interval(1000,secondpassed)
tminute.interval(60000,minutepassed)
tsec.start()
tminute.start()

while True:

    if seconds==30 and minutes==1:                               # do a check on passed time to trigger a oneshot timer 
        tshoot.one_shot(1000, shootpassed)                       # this is a oneshot timer, it executes only one time

    print("timer minutes runs since:", tminute.get(),"timer seconds runs since:",tsec.get(), "millisec")         #just print the current value since start or last reset
    sleep(2500)                 #run every 2500 millisec

Multi-Thread Basics

This examples shows the basics of ZERYNTH multi-threading In ZERYNTH a thread require a function to be executed as input for the definition the same function can be instanced by various thread giving you the possibility to write very concise and readable code. In this example 4 threads are created as instances of the same function where different parameters are passed to the function when the thread is initialized

Note that the while True main loop typical of imperative programming is not present in this code. ZERYNTH allows pure thread driven implementation!

tags: [First Steps, Multi-Thread]
groups:[First Steps]

main.py

################################################################################
# Multi-Thread Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

# create a serial port with default parameters
streams.serial()

# Define a function to be used in the various threads.
# Parameters are passed to the function when the thread is created and then used in the thread loop.
# To be continuously executed by a thread a function requires an infinite loop,
# otherwise when the function terminates the thread is closed

def threadfn(number,delay):    

    while True:                    
        print("I am the thread",number)
        print("I run every:",delay,"msec")
        print()                # just add an empty line for console output readability 
        sleep(delay)

# create the various threads using the same function but passing different parameters        
thread(threadfn,1,500)
thread(threadfn,2,1000)
thread(threadfn,3,1300)
thread(threadfn,4,800)

This examples shows how to use ZERYNTH threads for driving three LEDs with asymmetric and different blinking rates.

Each Thread in ZERYNTH is a sort of separated and parallel process that runs autonomously on your board. With threads you can design your algorithm architecture assuming parallelism that is typical of high level programming languages. In this code a function is defined and then instanced by three threads creating a pool of parallel processes where three LEDs are driven at different frequencies.

Moreover, thanks to Python argument passing, default values can be defined for function inputs. This way you can launch threads without specifying all the inputs required by the function, default values will fill the holes. In this case all the parameters following 'blink' are passed to the functions as arguments. thread(blink,pin,delayON,delayOFF) is equivalent to thread(blink(pin,delayON,delayOFF)).

tags: [Multi-Thread, First Steps, Digital I/O] groups:[First Steps]

main.py

################################################################################
# Multi-Blink
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# Initialize the digital pins where the LEDs are connected as output
pinMode(D2,OUTPUT)
pinMode(D8,OUTPUT)
pinMode(D5,OUTPUT)

# Define the 'blink' function to be used by the threads
def blink(pin,timeON=100,timeOFF=100): # delayON and delayOFF are optional parameters, used as default 
                                         # if not specified when you call the function
    while True:
        digitalWrite(pin,HIGH)   # turn the LED ON by making the voltage HIGH
        sleep(timeON)            # wait for timeON 
        digitalWrite(pin,LOW)    # turn the LED OFF by making the voltage LOW
        sleep(timeOFF)           # wait for timeOFF 

# Create three threads that execute instances of the 'blink' function.     
thread(blink,D2)             # D2 is ON for 100 ms and OFF for 100 ms, the default values of delayON an delayOFF
thread(blink,D8,200)         # D8 is ON for 200 ms and OFF for 100 ms, the default value of delayOFF
thread(blink,D5,500,200)     # D5 is ON for 500 ms and OFF for 200 ms

This examples shows how to drive various behaviours taking as input an analog signal acquired through ADC fro driving three loop implemented as separated threads. In particular, the implemented scripts drives three LEDs at three different frequencies calculated on the basis of the acquired analog signal.

The example is implemented using 4 threads that run in parallel. One thread is used for acquiring the analog signal and convert the acquired raw value in blinking frequencies usable by the LED driving threads. The other three threads are used to instantiate a generic blinking function that drive a PIN where a LED is connected.

tags:[Multi-Thread, First Steps, Analog Read ADC] groups:[First Steps]

main.py

################################################################################
# Sensor Driven Multi-Blink
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# This example requires an analog sensor and three LEDs
import streams
import adc

# create a serial port stream with default parameters
streams.serial()

# set the A1 pin as analog input and D8, D9, D10 as outputs to drive the LEDs. 
pinMode(A1,INPUT_ANALOG)
pinMode(D10,OUTPUT)
pinMode(D9,OUTPUT)
pinMode(D8,OUTPUT)

# creates two arrays for storing global variables to be used in the blinking threads
freq=[1,1,1]        
pin=[D8,D9,D10]    

# define the generic blinking function to be used for driving the LEDs
# this function takes as input the index identifying the LED, then uses the global freq and pin arrays to dynamically drive the LEDs
def blink(Npin):
    while True:
        digitalWrite(pin[Npin],HIGH)
        sleep(freq[Npin])
        digitalWrite(pin[Npin],LOW)
        sleep(freq[Npin])

# define an analog sensor sampling function that acquires the raw data and converts it to the three LED frequencies
def sampling():
    global freq
    while True:
        value = adc.read(A1)
        freq[0] = value//10
        freq[1] = freq[0] * 2
        freq[2] = freq[0] * 4
        sleep(50)

# launch the four threads        
thread(sampling)
thread(blink,0)
thread(blink,1)
thread(blink,2)

# The main loop is used only for printing out at reasonable speed the calculated frequencies in term of waiting times 
while True:
    print("Wait times are", freq)
    sleep(500)

Queues

Simple producer/consumer example based on thread safe queues.

main.py

################################################################################
# Queues
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import threading
import streams
import queue


streams.serial()

# create a bounded queue
q = queue.Queue(maxsize=20)

# keep producing an element every 100 millis
def producer(id):
    while True:
        try:
            x = random(0,100)
            print("producer",id,"->",x)
            q.put(x)
        except Exception as e:
            print(e)
        sleep(100)

# keep consuming an element every 1 second
def consumer(id):
    while True:
        try:
            print("consumer",id,"<-",q.get())
        except Exception as e:
            print(e)
        sleep(1000)

# start everyone
thread(producer,0)
thread(consumer,1)
thread(consumer,2)

while True:
    isfull = q.full()
    print("Queue is full?",isfull)
    if isfull:
        # clear queue if full
        print("Clearing queue")
        q.clear()
    sleep(5000)

Interrupt Basics

This example shows how to use interrupts for monitoring pin state changes. A button is used to connect a pin to ground when pressed. The pin is set as INPUT_PULLUP putting HIGH voltage on it while activated as digital input. It is possible to use onboard embedded button like in the case of ST Nucleo. Otherwise an external button can be connected to any digital pin available on the board and then to GND. In this case the pin number have to be changed with the pin used for connecting the button

Note that the main loop (while True) is not present in this example. With ZERYNTH it is possible to write pure event driven code!

tags: [First Steps, Interrupts, Digital I/O] groups:[First Steps]

main.py

################################################################################
# Interrupt Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

# create a serial port stream with default parameters
streams.serial()

# define where the button and the LED are connected
# in this case BTN0 will be automatically configured according to the selected board button
# change this definition to connect external buttons on any other digital pin
buttonPin=BTN0 
ledPin=LED0  # LED0 will be configured to the selected board led

# configure the pin behaviour to drive the LED and to read from the button  
pinMode(buttonPin,INPUT_PULLUP)
pinMode(ledPin,OUTPUT)

# define the function to be called when the button is pressed
def pressed():
        print("touched!")
        digitalWrite(ledPin,HIGH) # just blink the LED for 100 millisec when the button is pressed
        sleep(100)
        digitalWrite(ledPin,LOW)

# attach an interrupt on the button pin and call the pressed function when it falls
# being BTN0 configured as pullup, when the button is pressed the signal goes to from HIGH to LOW.
# opposite behaviour can be obtained with the equivalent "rise" interrupt function: onPinRise(pin,fun)
# hint: onPinFall and onPinRise can be used together on the same pin, even with different functions
onPinFall(buttonPin,pressed)

Interrupt Advanced

This example uses pwm to show the advanced feature of interrupt debouncing. PWM triggers fall and rise events at different speeds, but interrupts are triggered only if the debounce time (i.e. the stable time after and event) is in the correct range.

main.py

################################################################################
# Interrupt Debounce
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# import streams
import streams
# import pwm for testing
import pwm


# CONNECT pin D3 to PIN D2 for this example to work!

streams.serial()

def on_touch_up():
    print("touched UP")

def on_touch_dn():
    print("touched DN")



try:    
    # D2 will call touch_up on rise and touch_dn on fall with different debounce times
    onPinRise(D2,on_touch_up,debounce=500)
    onPinFall(D2,on_touch_dn,debounce=300)
except Exception as e:
    print(e)




while True:
    for x in [100,200,300,400,500,600,700,800,900]:
        print("--->",x, 1000-x)
        # start pwm on D3 with the current period
        pwm.write(D3.PWM,1000,x)
        # now wait and check if debounce is working
        sleep(5000)

Exceptions-Debugger Basic

Basic example of how to use the ZERYNTH Exceptions class to monitor and analyze programs behavior without crashing the execution. The examples shows how a "division by zero" is identified in the code without causing any crash. In ZERYNTH exceptions reported on the IDE serial console can be opened and analyzed through the integrated debugger window.

tags:[First Steps, Exceptions] groups:[First Steps]

main.py

################################################################################
# Exception-Debugger Basics
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi,  D. Mazzei
###############################################################################

import streams

streams.serial()

while True:
    for x in range(-10,10,1):   # create a loop ranging on the integers between -10 and 10

        try:                    # open the Exception monitoring scope
            value=100//x        # when x=0 this will results in a DivisionByZero!
            print(value)
        except Exception as e:  # capture any raised exception as e
            print(e)            # print the content of e to monitor where the program is faulting
                                # click on the console X icon to open the Zerynth debugger window 
        sleep(1000)    

Math Module

Some fun with math functions

main.py

###############################################################################
# Math module
#
# Created by Zerynth Team 2017 CC
# Authors: G. Baldi
###############################################################################
import streams
import math 

streams.serial()


while True:
    # loop over angles in degrees
    print("---> TRIGONOMETRY!")
    for angle in range(0,360*3,10):
        # convert to radians
        r = math.radians(angle)
        # take the sin
        s = math.sin(r)
        # calculate offset...
        sl = int(40*s)
        # ...and print!
        if sl>=0:
            print(" "*40,"#"*sl)
        else:
            print(" "*(40+sl),"#"*(-sl))
        sleep(50)
    sleep(1000)

    # loop from -5 to 0 in 0.05 increments
    print("---> EXPONENTIALS")
    x = -5
    incr = 0.05
    while x<0:
        # take the exp...
        y = math.exp(x)
        # ...and print!
        print("#"*int(y*80))
        # do not forget to increment x
        x = x + incr
        sleep(50)
    sleep(1000)

    print("---> ROOTS and POWERS")
    # loop from 1 to 100
    print(" a   |  b   |  c   | math.sqrt(a*a*+b*b)")
    print("----------------------------------------")
    for i in range(0,100):
        # let's generate and test Pythagorean Triples!
        # select n and m
        m = 1
        n = 0
        while m>=n:
            n = random(1,30)
            m = random(1,30)

        a = math.pow(n,2)-math.pow(m,2)
        b = 2*m*n 
        c = math.pow(n,2)+math.pow(m,2)
        a2 = math.pow(a,2)
        b2 = math.pow(b,2)
        p = math.sqrt(a2+b2)

        print("%4.0f | %4.0f | %4.0f | %4.0f"%(a,b,c,p))
        sleep(100)
    sleep(1000)

Mini Web Server

This example implements a very minimal web server by opening a TCP socket in listening mode, reading HTTP headers and sending out some HTML.

It prints the IP to connect to in the serial console. Type it in your browser and test your mini web server!

It uses the CC3000 wireless driver, however any network driver can be used changing only a few lines of code.

main.py

###############################################################################
# Mini Web Server
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################

# import streams & socket
import streams
import socket

# import the wifi interface
from wireless import wifi

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# FOR THIS EXAMPLE TO WORK, A NETWORK DRIVER MUST BE SELECTED BELOW

# uncomment the following line to use the CC3000 driver (Particle Core or CC3000 Wifi shields)
# from texas.cc3000 import cc3000 as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()
# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

# Yes! we are connected
print("Linked!")

# Let's print our ip, it will be needed soon
info = wifi.link_info()
print("My IP is:",info[0])

# Now let's create a socket and listen for incoming connections on port 80
sock = socket.socket()
sock.bind(80)
sock.listen()


while True:
    try:
        # Type in your browser the board ip!
        print("Waiting for connection...")
        # here we wait for a connection
        clientsock,addr = sock.accept()
        print("Incoming connection from",addr)

        # yes! a connection is ready to use
        # first let's create a SocketStream
        # it's like a serial stream, but with a socket underneath.
        # This way we can read and print to the socket
        client = streams.SocketStream(clientsock)

        # let's read all the HTTP headers from the browser
        # stop when a blank line is received
        line = client.readline()
        while line!="\n" and line!="\r\n":
            line = client.readline()
        print("HTTP request received!")

        # let's now send our headers (very minimal)
        # hint: \n is added by print
        print("HTTP/1.1 200 OK\r",stream=client)
        print("Content-Type: text/html\r",stream=client)
        print("Connection: close\r\n\r",stream=client)
        # see? as easy as print!
        print("<html><body>Hello Zerynth!",random(0,100),"</body></html>",stream=client)
        # close connection and go waiting for another one
        client.close()
    except Exception as e:
        print("ooops, something wrong:",e)

ZERYNTH UDP pinger

This example demonstrates the use of UDP sockets. A writer thread sends UDP broadcast packets while a reader threads catches them. Uplink this script on more than one board for some pinger fun!

main.py

################################################################################
# Zerynth UDP pinger
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# import streams & socket
import streams
import socket

# import the wifi interface
from wireless import wifi

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# FOR THIS EXAMPLE TO WORK, A NETWORK DRIVER MUST BE SELECTED BELOW

# uncomment the following line to use the CC3000 driver (Particle Core or CC3000 Wifi shields)
# from texas.cc3000 import cc3000 as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()

# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
    # get our ip
    myip = wifi.link_info()[0]
    # convert myip to a tuple with the socket.ip_to_tuple function
    # "x.y.z.w" becomes (x,y,z,w)
    ip_tuple = socket.ip_to_tuple(myip)
    # generate a broadcast address to port 9999
    # (it's ok and easier to generate it as a 5 number tuple)
    broadcast = (ip_tuple[0],ip_tuple[1],ip_tuple[2],255,9999)
    print(myip,ip_tuple,broadcast)
    # create an UDP socket and bind it to port 9999
    sock = socket.socket(type=socket.SOCK_DGRAM)
    sock.bind(9999)
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)


# this function will be used as a thread
# sending every 2 seconds a message to all
# the udp sockets listening on port 9999 
def ping():
    while True:
        print("Sending")
        sock.sendto("Hello Zerynth!",broadcast)
        sleep(2000)

# launch it!
thread(ping)

# in the main thread we listen for incoming udp packets
while True:
    print("Receiving pings")
    try:
        # recvfrom returns both the packet data and the address of the sender
        data,address = sock.recvfrom(32)
        # since we bind to 9999 we also receive the packets we sent
        # check for it by comparing just the ip address (without the port)
        if address[0]!=myip:
            print("Received ping from",address,"=>",str(data))
        else:
            print("Received ping from myself!")
    except Exception as e:
        print(e)
# uplink this script to more than one board and check

UDP NTP Time

This example uses UDP socket to make client requests to an NTP server.

The received timestamp is printed on the serial console in a human-readable form.

main.py

# UDP NTP Time
# Created at 2019-02-19 08:07:55.144570

import streams
import socket

# import the wifi interface
from wireless import wifi

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# This example can be used as is with ESP32 based devices
from espressif.esp32net import esp32wifi as wifi_driver


def ntc_ts_to_datetime(t):
    # convert NTP timestamp (seconds since January 1st 1900) to datetime formatted string
    # YYYY-mm-dd HH:MM:SS
    ts = t - 2208988800

    s = ts % 60
    ts //= 60
    m = ts % 60
    ts //= 60
    h = ts % 24
    ts //= 24

    a = (4 * ts + 102032) // 146097 + 15
    b = (ts + 2442113 + a - (a//4))
    c = (20 * b - 2442) // 7305
    d =  b - 365* c - (c // 4)
    e = d * 1000 //30601
    f = d - e*30 - e*601//1000

    if e <= 13:
        c-=4716
        e -= 1
    else:
        c -= 4715
        e -= 13

    Y = c
    M = e
    D = f

    return "%d-%02d-%02d %02d:%02d:%02d"%(Y, M, D, h, m, s)


try:
    streams.serial()

    # init the wifi driver!
    # The driver automatically registers itself to the wifi interface
    # with the correct configuration for the selected board
    wifi_driver.auto_init()

    # use the wifi interface to link to the Access Point
    # change network name, security and password as needed
    print("Establishing WiFi Link...")
    for retry in range(5):
        try:
            # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
            # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
            wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
            print("...done!")
            break
        except Exception as e:
            pass
    else:
        print(":( can't connect to wifi")
        raise IOError

    # create an UDP socket and set a timeout of 1 second
    sock = socket.socket(type=socket.SOCK_DGRAM)
    sock.settimeout(1000)

    # create an NTP request packet
    pkt = bytearray([0]*48)
    pkt[0] = 0x1B

    while True:
        try:
            # resolve the NTP server hostname to get its IP address
            ip_string = wifi.gethostbyname("0.pool.ntp.org")
            ip = socket.ip_to_tuple(ip_string)

            # create a tuple containing NTP server ip address and port
            addr = (ip[0], ip[1], ip[2], ip[3], 123)

            print("Sending NTP request to %s:%d" %(ip_string, 123))
            # send the NTP request packet to the NTP server
            sock.sendto(pkt, addr)

            # read the response from the server
            res = sock.recv(48)

            # extract the "transmit timestamp" field from the received packet
            ts =  (res[40]<<24) | (res[41]<<16) | (res[42]<<8) | res[43]

            # convert NTP timestamp to human readable datetime
            print(" >", ntc_ts_to_datetime(ts))
            print(" ")
        except Exception as e:
            print(" >", e)
        sleep(10000)

except Exception as e:
    print(e)

ZERYNTH wifi scan

This example explains how to scan for wifi networks.

main.py

################################################################################
# Zerynth wifi scan
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

# import streams & socket
import streams
import socket

# import the wifi interface
from wireless import wifi

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# FOR THIS EXAMPLE TO WORK, A NETWORK DRIVER MUST BE SELECTED BELOW

# uncomment the following line to use the CC3000 driver (Particle Core or CC3000 Wifi shields)
# from texas.cc3000 import cc3000 as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()

# a list of security strings
wifi_sec=["Open","WEP","WPA","WPA2"]
try:
    print("Scanning for 15 seconds...")
    # start scanning for 15000 milliseconds
    res = wifi.scan(15000)

    # if everything goes well, res is a sequence of tuples
    # each tuple contains:
    # -ssid: the name of the network
    # -sec: the security type of the network, from 0 to 3
    # -rssi: the strength of the signal, from 0 to 127
    # -bssid: the mac address of the access point
    for ssid,sec,rssi,bssid in res:
        print(ssid,"::",wifi_sec[sec],":: strength ",rssi*100/127)
except Exception as e:
    print(e)

ZERYNTH Time API

This example connects via HTTP to timeapi.org to get the current UTC time

main.py

################################################################################
# Zerynth Time API
#
# Created: 2015-08-17 16:44:58.640097
#
################################################################################

# import streams
import streams
import json

# import the wifi interface
from wireless import wifi

# import the http module
import requests

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# THIS EXAMPLE IS SET TO WORK WITH BCM43362 WIFI DRIVER

# uncomment the following line to use the espressif esp8266 wifi driver (NodeMcu v2, Adafruit Feather Huzzah, Wemos d1 Mini, ...)
# from espressif.esp8266wifi import esp8266wifi as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
from broadcom.bcm43362 import bcm43362 as wifi_driver

# uncomment the following line to use the ESP32 driver (Sparkfun Esp32 Thing, Olimex Esp32, ...)
# from espressif.esp32net import esp32wifi as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()

# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

## let's try to connect to timeapi.org to get the current UTC time
for i in range(3):
    try:
        print("Trying to connect...")
        # go get that time!
        # url resolution and http protocol handling are hidden inside the requests module
        response = requests.get("http://now.zerynth.com/")
        # let's check the http response status: if different than 200, something went wrong
        print("Http Status:",response.status)
        # if we get here, there has been no exception, exit the loop
        break
    except Exception as e:
        print(e)


try:
    # check status and print the result
    #if response.status==200:
    print("Success!!")
    print("-------------")
    print("And the result is:",response.content)
    print("-------------")
    js = json.loads(response.content)
    print("Date:",js["now"]["rfc2822"][:16])
    print("Time:",js["now"]["rfc2822"][17:])
except Exception as e:
    print("ooops, something very wrong! :(",e)

ZERYNTH Weather

This example connects to openweathermap.org, queries for weather conditions and prints the result.

main.py

################################################################################
# Zerynth Weather
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################



# import streams & socket
import streams
import socket

# import json parser, will be needed later
import json

# import the wifi interface
from wireless import wifi

# import the http module
import requests

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# THIS EXAMPLE IS SET TO WORK WITH ESP8266 WIFI DRIVER

# uncomment the following line to use the espressif esp8266 wifi driver (NodeMcu v2, Adafruit Feather Huzzah, Wemos d1 Mini, ...)
from espressif.esp8266wifi import esp8266wifi as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

# uncomment the following line to use the ESP32 driver (Sparkfun Esp32 Thing, Olimex Esp32, ...)
# from espressif.esp32net import esp32wifi as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()


# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

# let's try to connect to openweathermap.org to get some weather info
# for this example to work you need a openweathermap API key
# if you don't have one, you can get one for free here: http://openweathermap.org/price

# type here your API key!
# or you can use ours...however, if our calls quota is exceded 
# the example won't work :(
api_key = "bd4ba90e2b397e24a925e436a9d8fed9"

for i in range(3):
    try:
        print("Trying to connect...")
        # to get weather info you need to specify a correct api url
        # there are a lot of different urls with different functions
        # they are all documented here http://openweathermap.org/api

        # let's put the http query parameters in a dict
        params = {
            "APPID":api_key,
            "q":"Pisa"   # <----- here it goes your city
        }

        # the following url gets weather information in json based on the name of the city
        url="http://api.openweathermap.org/data/2.5/weather"
        # url resolution and http protocol handling are hidden inside the requests module
        response = requests.get(url,params=params)
        # if we get here, there has been no exception, exit the loop
        break
    except Exception as e:
        print(e)


try:
    # check status and print the result
    if response.status==200:
        print("Success!!")
        print("-------------")
        # it's time to parse the json response
        js = json.loads(response.content)
        # super easy!
        print("Weather:",js["weather"][0]["description"],js["main"]["temp"]-273,"degrees")
        print("-------------")
except Exception as e:
    print("ooops, something very wrong! :(",e)

HTTP Methods

This example connects via HTTP to httpbin.org and tests each Zerynth supported HTTP method

main.py

################################################################################
# Zerynth HTTP Methods
#
# Created: 2017-09-19 12:35:25.155721
# Authors: M. Cipriani
################################################################################

# import streams
import streams
import json

# import the wifi interface
from wireless import wifi

# import the http module
import requests

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# THIS EXAMPLE IS SET TO WORK WITH ESP32 WIFI DRIVER

# uncomment the following line to use the espressif esp8266 wifi driver (NodeMcu v2, Adafruit Feather Huzzah, Wemos d1 Mini, ...)
# from espressif.esp8266wifi import esp8266wifi as wifi_driver

# uncomment the following line to use the BCM43362 driver (Particle Photon)
# from broadcom.bcm43362 import bcm43362 as wifi_driver

# uncomment the following line to use the ESP32 driver (Sparkfun Esp32 Thing, Olimex Esp32, ...)
from espressif.esp32net import esp32wifi as wifi_driver

streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()

# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Zerynth",wifi.WIFI_WPA2,"zerynthwifi")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

url = "http://httpbin.org/"

tests = [
    {
        "title": "Testing GET Method...",
        "method": requests.get,
        "url": url+"get",
        "params": {"test": "query_string"}
    },
    {
        "title": "Testing POST Method...",
        "method": requests.post,
        "url": url+"post",
        "json": {"test": "json_data"}
    },
    {
        "title": "Testing PUT Method...",
        "method": requests.put,
        "url": url+"put",
        "data": {"test": "urlencoded_data"}
    },
    {
        "title": "Testing PATCH Method...",
        "method": requests.patch,
        "url": url+"patch",
        "data": {"test": "urlencoded_data"}
    },
    {
        "title": "Testing DELETE Method...",
        "method": requests.delete,
        "url": url+"delete",
    },
    {
        "title": "Testing HEAD Method...",
        "method": requests.head,
        "url": url+"get",
    },
    {
        "title": "Testing OPTIONS Method...",
        "method": requests.options,
        "url": url+"get",
    }
]

print("---------------------------------")
for test in tests:
    try:
        print(test["title"])
        if "params" in test:
            response = test["method"](test["url"], params=test["params"])
        elif "json" in test:
            response = test["method"](test["url"], json=test["json"])
        elif "data" in test:
            response = test["method"](test["url"], data=test["data"])
        else:
            response = test["method"](test["url"])
        print("Http Status:",response.status)
        print("Http Headers:",response.headers)
        print("Http Content:",response.content)
        print("---------------------------------")
        response = None
    except Exception as e:
        print(e)
    sleep(2000)

Secure HTTP

This example connects to https://howsmyssl.com/a/check and displays info about the SSL/TLS connection

main.py

################################################################################
# Zerynth Secure Sockets
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import json
# import the wifi interface
from wireless import wifi
# import the http module
import requests
import ssl

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# This example can be used as is with ESP32 based devices
from espressif.esp32net import esp32wifi as wifi_driver


streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()


# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

# let's try to connect to https://www.howsmyssl.com/a/check to get some info
# on the SSL/TLS connection

# retrieve the CA certificate used to sign the howsmyssl.com certificate
cacert = __lookup(SSL_CACERT_DST_ROOT_CA_X3)

# create a SSL context to require server certificate verification
ctx = ssl.create_ssl_context(cacert=cacert,options=ssl.CERT_REQUIRED|ssl.SERVER_AUTH)
# NOTE: if the underlying SSL driver does not support certificate validation
#       uncomment the following line!
# ctx = None


for i in range(3):
    try:
        print("Trying to connect...")
        url="https://www.howsmyssl.com/a/check"
        # url resolution and http protocol handling are hidden inside the requests module
        user_agent = {"User-Agent": "curl/7.53.1", "Accept": "*/*" }
        # pass the ssl context together with the request
        response = requests.get(url,headers=user_agent,ctx=ctx)
        # if we get here, there has been no exception, exit the loop
        break
    except Exception as e:
        print(e)


try:
    # check status and print the result
    if response.status==200:
        print("Success!!")
        print("-------------")
        # it's time to parse the json response
        js = json.loads(response.content)
        # super easy!
        for k,v in js.items():
            if k=="given_cipher_suites":
                print("Supported Ciphers")
                for cipher in v:
                    print(cipher)
                print("-----")
            else:
                print(k,"::",v)
        print("-------------")
except Exception as e:
    print("ooops, something very wrong! :(",e)

NTPClient

A simple example showing how to obtain a timestamp from an NTP server and how to convert it to UTC datetime.

main.py

################################################################################
# NTPClient using UDP
#
# Created: 2019-06-16
# Author: L. Marsicano
################################################################################

import streams
import ntpclient 

streams.serial()

# import the wifi interface
from wireless import wifi

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# This example can be used as is with ESP32 based devices
from espressif.esp32net import esp32wifi as wifi_driver
def ntc_ts_to_datetime(t):
   ts = t - 2208988800

   s = ts % 60
   ts //= 60
   m = ts % 60
   ts //= 60
   h = ts % 24
   ts //= 24

   a = (4 * ts + 102032) // 146097 + 15
   b = (ts + 2442113 + a - (a//4))
   c = (20 * b - 2442) // 7305
   d =  b - 365* c - (c // 4)
   e = d * 1000 //30601
   f = d - e*30 - e*601//1000

   if e <= 13:
       c-=4716
       e -= 1
   else:
       c -= 4715
       e -= 13

   Y = c
   M = e
   D = f

   return "%d-%02d-%02d %02d:%02d:%02d"%(Y, M, D, h, m, s)

try:
    wifi_driver.auto_init()
    for i in range(0, 5):
        try:
            # Change this line to match your network configuration
            wifi.link("SSID",wifi.WIFI_WPA2,"PASSWORD")
            break
        except Exception as e:
            print(e)
            sleep(500)
    else:
        print("Could not link :(")
        raise IOError

    client = ntpclient.NTPClient(wifi_driver)
    t = client.get_time()
    print("Time is", t)
    print("Converted time is:", ntc_ts_to_datetime(t))
except Exception as e:
    print(e)

Secure HTTP

This example connects to https://howsmyssl.com/a/check and displays info about the SSL/TLS connection

main.py

################################################################################
# Zerynth Secure Sockets
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import json
# import the wifi interface
from wireless import wifi
# import the http module
import requests
import ssl

# the wifi module needs a networking driver to be loaded
# in order to control the board hardware.
# This example can be used as is with ESP32 based devices
from espressif.esp32net import esp32wifi as wifi_driver


streams.serial()

# init the wifi driver!
# The driver automatically registers itself to the wifi interface
# with the correct configuration for the selected board
wifi_driver.auto_init()


# use the wifi interface to link to the Access Point
# change network name, security and password as needed
print("Establishing Link...")
try:
    # FOR THIS EXAMPLE TO WORK, "Network-Name" AND "Wifi-Password" MUST BE SET
    # TO MATCH YOUR ACTUAL NETWORK CONFIGURATION
    wifi.link("Network-Name",wifi.WIFI_WPA2,"Wifi-Password")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

# let's try to connect to https://www.howsmyssl.com/a/check to get some info
# on the SSL/TLS connection

# retrieve the CA certificate used to sign the howsmyssl.com certificate
cacert = __lookup(SSL_CACERT_DST_ROOT_CA_X3)

# create a SSL context to require server certificate verification
ctx = ssl.create_ssl_context(cacert=cacert,options=ssl.CERT_REQUIRED|ssl.SERVER_AUTH)
# NOTE: if the underlying SSL driver does not support certificate validation
#       uncomment the following line!
# ctx = None


for i in range(3):
    try:
        print("Trying to connect...")
        url="https://www.howsmyssl.com/a/check"
        # url resolution and http protocol handling are hidden inside the requests module
        user_agent = {"User-Agent": "curl/7.53.1", "Accept": "*/*" }
        # pass the ssl context together with the request
        response = requests.get(url,headers=user_agent,ctx=ctx)
        # if we get here, there has been no exception, exit the loop
        break
    except Exception as e:
        print(e)


try:
    # check status and print the result
    if response.status==200:
        print("Success!!")
        print("-------------")
        # it's time to parse the json response
        js = json.loads(response.content)
        # super easy!
        for k,v in js.items():
            if k=="given_cipher_suites":
                print("Supported Ciphers")
                for cipher in v:
                    print(cipher)
                print("-----")
            else:
                print(k,"::",v)
        print("-------------")
except Exception as e:
    print("ooops, something very wrong! :(",e)

RTC Keep Time

This example downloads a time reference for the Real-Time Clock from the Internet and retrieves updated time from the RTC itself for subsequent use.

main.py

################################################################################
# RTC Keep Time
#
# Created by Zerynth Team 2018 CC
# Authors: G. Baldi, L. Rizzello
################################################################################

import streams
import json
import requests

from wireless import wifi
# import a wifi driver to connect and retrieve base timestamp
from espressif.esp32net import esp32wifi as wifi_driver

# import Real-Time Clock module
import rtc

def get_epoch():
    user_agent = {"user-agent": "curl/7.56.0"}
    return int(json.loads(requests.get("http://now.zerynth.com/", headers=user_agent).content)['now']['epoch'])

streams.serial()
wifi_driver.auto_init()

print('connecting to wifi...')
try:
    wifi.link("SSID",wifi.WIFI_WPA2,"PSW")
except Exception as e:
    print("ooops, something wrong while linking :(", e)
    while True:
        sleep(1000)

timestamp = get_epoch()
rtc.set_utc(timestamp)
while True:
    tm = rtc.get_utc()
    print(tm.tv_seconds)
    print(tm.tm_year,'/',tm.tm_month,'/',tm.tm_mday,sep='')
    print(tm.tm_hour,':',tm.tm_min,':',tm.tm_sec,sep='')
    sleep(1000)

ZERYNTH Resources

This example explains the use of flash resources.

main.py

################################################################################
# Zerynth Resources
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams

streams.serial()

# new_resource is a builtin that includes the file specified
# in the generated bytecode
# remember: the file used as a resource must be added to the project!
new_resource("mytxt.txt")

# to open resources saved by new_resource
# a specific url must be passed to open
# once opened, methods like read, readline and seek can be used!
ff = open("resource://mytxt.txt")

print("Opening resource...")
while True:

    # let's read line by line and print
    line = ff.readline()

    # if line is empty, we are at the end of file
    if not line:
        break

    print("Line:",line)

# easy!
print("Done!")

Struct Example

Test pack and unpack methods with different formats

main.py

################################################################################
# struct
#
# Created by Zerynth Team 2017 CC
# Authors: G. Baldi, M. Cipriani
################################################################################

import streams
import struct

streams.serial()

def print_res(b):
    print("Pack -->\n ",end="")
    for x in b:
        print(hex(x,prefix=""),end="")
    print("")

try:
    print("Create pack for 0x01020304 in >xl format")
    b = struct.pack(">xl",0x01020304)
    u = struct.unpack(">xl",b)
    print_res(b)
    print("Unpack -->\n", hex(u[0]))
    print("-------------------------------------------------")
    print("Create pack for a in 10s format")
    b = struct.pack("10s","a")
    u = struct.unpack("10s",b)
    print_res(b)
    print("Unpack -->\n", u[0])
    print("-------------------------------------------------")
    print("Create pack for a in 10p format")
    b = struct.pack("10p","a")
    u = struct.unpack("10p",b)
    print_res(b)
    print("Unpack -->\n", u[0])
    print("-------------------------------------------------")
    print("Create pack for (1,2,3.0) in blf format")
    b = struct.pack("blf",1,2,3.0)
    u = struct.unpack("blf",b)
    print_res(b)
    print("Unpack -->\n", u)
    print("-------------------------------------------------")
    print("Create pack for (-1,9,1.2) in =hlf format")
    b = struct.pack("=hlf",-1,9,1.2)
    u = struct.unpack("=hlf",b)
    print_res(b)
    print("Unpack -->\n", u)
    print("-------------------------------------------------")
    print("Create pack for (127,10,5.5) in =blf format")
    b = struct.pack("=blf",127,10,5.5)
    u = struct.unpack("=blf",b)
    print_res(b)
    print("Unpack -->\n", u)
except Exception as e:
    print(e)

while True:
    print(".")
    sleep(1000)

Flash Internal

Writing and reading internal flash files.

main.py

################################################################################
# iflash
#
# Created: 2016-03-22 15:54:21.232663
#
################################################################################

import streams
import json
import flash

## Warning! This example works on the Particle Photon only!
# You need to change the flash address to use another board
#  --> For Sam3X based boards you can safely use 0xe0000

streams.serial()


print("create flash file")

# open a 512 bytes FlashFileStream at address 0x80E0000
ff = flash.FlashFileStream(0x80E0000,512)

print("reading flash file")

for i in range(30):
    print(i,"->",str(ff[i]))

print("writing flash file")

sleep(1000)

hh = {
    "type":"thing",
    "data":23.5
}

ds = json.dumps(hh)

# save length and json to flash
ff.write(len(ds))
ff.write(ds)

ff.flush()

ff.seek(0,streams.SEEK_SET)

print("reading flash file")

n = ff.read_int()

for i in range(n+4):
    print(i,"->",str(ff[i]))

Spi Flash

An example of how to use the spiflash library to read Spi Flash chips.

main.py

################################################################################
# SpiFlash Example
#
# Created: 2016-04-21 19:16:44.440555
#
################################################################################

import spiflash
import streams

streams.serial()


my_flash = spiflash.SpiFlash(SPI0, D25)

my_flash.erase_sector(0x30122)

to_w = [235,166,128,124,65,66]
# write data through bracket notation
my_flash[0x30122] = to_w

print("---")

# read 8 bytes starting from 0x30122 address
for x in my_flash.read_data(0x30122,8):
    print(x)

print("---")

# read the same 8 bytes through bracket notation
for x in my_flash[0x30123:0x30123+8]:
    print(x)

print("---")

QSpi Flash

An example of how to use the qspiflash library to read QSpi Flash chips.

main.py

################################################################################
# QSpiFlash Example
#
################################################################################

import qspiflash
import streams

streams.serial()

my_flash = qspiflash.QSpiFlash()

my_flash.erase_block(0)

to_w = b'\x77\x76\x75\x74\x73\x72'
# write data through bracket notation
my_flash[0] = to_w

print("---")

# read 8 bytes starting from 0 address
for x in my_flash.read_data(0, 8):
    print('%02x' % x)

print("---")

# read the same 8 bytes through bracket notation
for x in my_flash[1:1+8]:
    print('%02x' % x)

print("---")

Spi SD

An example of how to use spisd libray to read SD cards block by block.

main.py

################################################################################
# SpiSD Example
#
# Created: 2016-04-29 12:37:53.316436
#
################################################################################

import spisd
import streams

streams.serial()


my_sd = spisd.SpiSD(SPI0, D25)
data = bytearray(512*2)
for i in range(512*2):
    data[i] = 166

# write 512 bytes of data starting from 3rd block
my_sd.write_data(3,data)

# read 512*3 bytes of data starting from 3rd block
for i, x in enumerate(my_sd.read_data(3,3)):
    print(hex(0x200*3+i),": ",x)

Filesystem

A simple example to show the filesystem support in Zerynth (FATFS on SD with SPI)

main.py

import streams

import fatfs # import driver module
import os    # import file/directory management module

streams.serial()


# mount my SD card as volume 0 through SPI protocol
fatfs.mount('0:', {"drv": SPI0, "cs": D25, "clock": 1000000} )

# mount my SD card as volume 0 trough SD mode
# (be careful in choosing frequency (kHz) and bits supported by your board)
# fatfs.mount('0:', {"drv": SD1, "freq_khz": 20000, "bits": 1})

# create "zerynth.txt" file and open it for read/write operations
ww = os.open('0:zerynth.txt', 'w+')

# write a string on it, flushing data immediately (not waiting for file to be closed)
ww.write("Zerynth allows me to easily manage files, cool.", sync = True)


# ops, I forgot what I wrote...
# not a real problem problem using Zerynth

# back to the start
ww.seek(0)
print("I wrote: ", ww.read())

ww.close()

# files and directories in root folder?
print(os.listdir('.'))


# a folder for zerynth stuff is needed
if not os.exists("0:zerynth_stuff"):
    os.mkdir("0:zerynth_stuff")

# copy my cool file    
os.copyfile("zerynth.txt","zerynth_stuff/zerynth_cool.txt")
os.chdir("0:zerynth_stuff")

# check if anything went wrong
print("in ", os.getcwd())
print(os.listdir('.'))

print("SUCCESS!")

MCU Reset

A simple example showing how to soft reset the microcontroller from Python.

main.py

###############################################################################
# MCU Reset
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
###############################################################################


# import the mcu module
import mcu
import streams

# open the default serial port, the output will be visible in the serial console
streams.serial()  

resetting = False
# define a simple function to be called on interrupt
def reset():
    global resetting
    resetting=True

# on button pressed, call reset
# >>>> if the board hasn't a button, change BTN0 to a digital pin
#      and use a jumper wire to simulate a falling edge <<<<
onPinFall(BTN0,reset)

# loop forever
while True:
    print("Hello Zerynth!")
    sleep(1000)
    # check for the need to reset
    if resetting:
        print("Resetting in 3 seconds!!")
        sleep(3000)
        mcu.reset()
        # bye!

C Interface

This advanced example shows how to call C functions from Python.

main.py

################################################################################
# C Interface
#
# Created: 2016-01-17 10:06:10.333915
#
################################################################################

import streams

streams.serial()

# define a Python function decorated with c_native.
# This function has no body and will instead call
# the C function specified in the decorator.
# The source file(s) where to find the C function must be given (cdiv.c)
@c_native("_my_c_function",["cdiv.c"],[])
def c_division(a,b):
    pass


while True:
    a = random(0,100)
    b = random(0,10)
    try:
        # call the c_division function with random values
        c = c_division(a,b)
        print(a,"/",b,"=",c)
    except Exception as e:
        print(e)
    sleep(1000)

Secure Hash Functions

A simple example to introduce Secure Hashes of the crypto module

main.py

################################################################################
# Secure Hash
#
# Created by Zerynth Team 2017 CC
# Authors: G.Baldi
################################################################################

import streams

# import all supported hash functions
from crypto.hash import md5 as md5
from crypto.hash import sha1 as sha1
from crypto.hash import sha2 as sha2
from crypto.hash import sha3 as sha3
from crypto.hash import keccak as keccak
# also import HMAC
from crypto.hash import hmac as hmac

# open stdout
streams.serial()

message = "Zerynth"

while True:
    try:
        ss = md5.MD5()
        ss.update(message)
        print("MD5: ",ss.hexdigest())

        ss = sha1.SHA1()
        ss.update(message)
        print("SHA1:",ss.hexdigest())

        ss = sha2.SHA2(sha2.SHA512)
        ss.update(message)
        print("SHA2:",ss.hexdigest())

        ss = sha3.SHA3()
        ss.update(message)
        print("SHA3:",ss.hexdigest())

        ss = keccak.Keccak()
        ss.update(message)
        print("KECCAK:",ss.hexdigest())

        # generate a hmac with key="Python" and sha1 hash
        hh = hmac.HMAC("Python",sha1.SHA1())
        hh.update(message)
        print("HMAC:",hh.hexdigest())
    except Exception as e:
        print(e)
    sleep(2000)

Elliptic Curve Cryptography

A simple example to introduce ECDSA primitives.

main.py

################################################################################
# Elliptic Curve Cryptography
#
# Created by Zerynth Team 2017 CC
# Authors: G. Baldi
################################################################################

import streams

# import ecc and sha1 modules
from crypto.ecc import ecc as ec
from crypto.hash import sha1 as sha1

streams.serial()

message = "Zerynth"

# import a Public Key for SECP256R1
pb = ec.hex_to_bin("7A181C7D3AD54EC3817CBAF86EA4E003AD492D8569102392A6EFE0C27E471A65553918EA1BAC86A68C78A30E9FE725EA499E14BEA96C3FE85E2267B74385E56B")
# import a Private Key for SECP256R1
pv = ec.hex_to_bin("6D5BE10E67D479FF99421A8DE030E2B4C5323EE477DA4C17420936CAC49C261E")

while True:
    # calculate hash of message
    ss = sha1.SHA1()
    ss.update(message)
    digest = ss.digest()

    # Calculate non deterministic signature of digest
    # for SECP256R1 and pv
    signature = ec.sign(ec.SECP256R1,digest,pv)

    # Calculate the deterministic signature of digest using SHA1
    deterministic_signature = ec.sign(ec.SECP256R1,digest,pv,deterministic=sha1.SHA1())

    print("PVKEY:",ec.bin_to_hex(pv))
    print("PBKEY:",ec.bin_to_hex(pb))
    # this changes each loop because of random number generator
    print("SIGNED:",ec.bin_to_hex(signature))
    # this is always the same
    print("SIGNED (det)",ec.bin_to_hex(deterministic_signature))

    print("VERIFY SIGNATURE:", ec.verify(ec.SECP256R1,digest,signature,pb))
    print("VERIFY SIGNATURE (det):", ec.verify(ec.SECP256R1,digest,deterministic_signature,pb))
    # tampered digests are detected
    print("VERIFY TAMPERED:", ec.verify(ec.SECP256R1,digest+b'\x00',signature,pb))
    print("-"*20)
    sleep(2000)

Powersaving

This example shows the most important features of Powersaving enabled VMs:

  • The ability to choose which low power mode to enter and how to exit
  • The ability to save status on a special purpose memory guaranteed to be preserved after exiting the low power mode

main.py

################################################################################
# Powersaving
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

##
## This example only works on a Powersaving enabled Virtual Machine!
##

import streams
# import the Power Management module
# Check documentation here: https://docs.zerynth.com/latest/official/core.zerynth.stdlib/docs/official_core.zerynth.stdlib_pwr.html
import pwr

streams.serial()

# wake up reasons dictionary
reasons = {
    pwr.PWR_RESET:"System Reset",
    pwr.PWR_INTERRUPT: "Event on WAKEUP pin",
    pwr.PWR_TIMEOUT: "Timeout"
}

# modes and descriptions
modes = [
    (pwr.PWR_SLEEP, "Sleep mode"),
    (pwr.PWR_STOP, "Stop mode"),
    (pwr.PWR_STANDBY, "Standby mode")
]

# some status variables
slept = 0
wokeup = 0
sleep_counter = 0

# callback for Wake Up events on pins
def wakeup():
    print("Hello!")

# function to prepare for and enter low power mode
def sleepfn(delay,mode):
    global slept,wokeup
    print("Going to sleep for",delay,"milliseconds in",modes[mode][1])
    sleep(100)
    # call go_to_sleep and get the amount of time spent sleeping
    # !! the VM is suspended here !!
    slept = pwr.go_to_sleep(delay,modes[mode][0])
    # if we reach this point, something caused a Wake Up from a low power mode
    # if we don't reach here, the device exited from a standby mode with a system reset

    # retrieve the Wake Up reason
    wokeup = pwr.wakeup_reason()
    print("SLEPT FOR",slept)
    print("My wake up reason:",reasons.get(wokeup,"Unknown"))


try:

    # retrieve the Wake Up reason
    wokeup = pwr.wakeup_reason()

    # retrieve sleep_counter from special purpose memory if supported
    try:
        sleep_counter = pwr.get_status_byte(0)
        print("Special purpose memory supported!")
    except Exception as e:
        print("Special purpose memory not supported :(")

    # print status at VM startup
    print("Wake up reason at startup:",reasons.get(wokeup,"Unknown"))
    print("Tried to sleep",sleep_counter,"times")


    # configure button to do something
    # depending on the platform this is enough to configure a Wake Up event
    # on some platforms only specific pins have the Wake Up property
    # (If the device has no button, configure another pin! [Try D6 on MKR1000 and D8 on Hexiwear])
    pinMode(BTN0,INPUT_PULLUP)
    onPinFall(BTN0, wakeup, debounce=1000)

    cnt = 5
    mode = 0
    print("Countdown!")
    while True:
        # print the countdown
        print(cnt)
        sleep(1000)

        cnt-=1
        if cnt==0:
            cnt=5
            try:
                # save number of sleeps in special purpose memory
                sleep_counter=(sleep_counter+1)%256
                try:
                    pwr.set_status_byte(0,sleep_counter)
                except:
                    # ignore if special purpose memory not supported
                    pass
                # enter a low power mode for 5 seconds or less
                # (press the button while sleeping to check if Wake Up is available in this mode)
                sleepfn(5000,mode)
            except Exception as e:
                print(modes[mode][1],"not supported!")
                print(e)
            mode=(mode+1)%len(modes)
            print("Countdown!")
except Exception as e:
    print(e)


# Expected results by architecture and mode for Wake Up on pin event
#
#      MODE  |      SLEEP        STOP                 STANDBY
# MCU        |
# -------------------------------------------------------------------
#            |
# STM32F     |       OK           OK                Only on pin PA0
#            |
# -------------------------------------------------------------------
#            |
# SAMD21     |       OK           No               Mode not supported
#            |
# --------------------------------------------------------------------
#            |
# NXP K64    |       OK           OK               Only on WakeUp pins 
#            |
# --------------------------------------------------------------------
#            |
# ESP8266    |    Unsupported   Unsupported    Only works for Gpio 16
#            |
# --------------------------------------------------------------------

Watchdogs

A basic example showing the watchdog functionalities in a Secure Fimrware enabled VM.

main.py

################################################################################
# Watchdogs
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

##
## This example only works on a Secure Firmware enabled Virtual Machine!
##

import streams
# import the Secure Firmware module
# Check documentation here: https://docs.zerynth.com/latest/official/core.zerynth.stdlib/docs/official_core.zerynth.stdlib_sfw.html
import sfw

streams.serial()

sleep(2000)

# Check for reset reason
try:
    print("Watchdog triggered:",sfw.watchdog_triggered())
except Exception as e:
    print("Watchdog not suppported by this Virtual Machine!")
    while True:
        sleep(1000)

# Do something without fearing a reset
for x in range(10):
    sleep(1000)
    print("Printing something for a while, no watchdog can reset me! 8‑D")



# Configure watchdog in normal mode with a 5 seconds timeout
print("Configuring watchdog to a 5 seconds timeout...")
sfw.watchdog(0,5000)
sleep(100)

# Kick the watchdog every second
for x in range(10):
    sleep(1000)
    sfw.kick()
    print("Kick!")

# Stop kicking and wait for reset
while True:
    print("Printing something for a while waiting for the watchdog! D-8")
    sleep(1000)

VM Exceptions

This example explains how to set VM Options to handle uncaught exceptions

main.py

################################################################################
# Zerynth VM Options
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################

import streams
import vm

streams.serial()

#let's set some VM options: uncomment the test you want to try, comment the others

#test 1: reset on uncaught exception and print trace (Default)
vm.set_option(vm.VM_OPT_RESET_ON_EXCEPTION,1)
vm.set_option(vm.VM_OPT_TRACE_ON_EXCEPTION,1)

#test 2: don't reset on uncaught exception but print trace (Default)
# vm.set_option(vm.VM_OPT_RESET_ON_EXCEPTION,0)
# vm.set_option(vm.VM_OPT_TRACE_ON_EXCEPTION,1)

#test 3: don't reset on uncaught exception and don't print trace (Default)
# vm.set_option(vm.VM_OPT_RESET_ON_EXCEPTION,0)
# vm.set_option(vm.VM_OPT_TRACE_ON_EXCEPTION,0)

#test 3: reset on uncaught exception but don't print trace (Default)
# vm.set_option(vm.VM_OPT_RESET_ON_EXCEPTION,1)
# vm.set_option(vm.VM_OPT_TRACE_ON_EXCEPTION,0)


def thread_fn_exc():
    for i in range(5):
        print("TH working",i)
        sleep(1000)
    x=1/0

# launch thread
thread(thread_fn_exc)

while True:
    sleep(2000)
    #let's print some VM info
    nfo = vm.info()
    print("--------------")
    print("VM uid ",nfo[0])
    print("Target ",nfo[1])
    print("Version",nfo[2])
    print("--------------")

VM Hard Fault

This example explains how to set VM Options to manage Hard Faults

main.py

################################################################################
# Zerynth VM Options
#
# Created by Zerynth Team 2015 CC
# Authors: G. Baldi, D. Mazzei
################################################################################
import streams
import vm

streams.serial()

#let's set some VM options: uncomment the test you want to try, comment the others

#test 1: reset on hard fault and print trace (Default)
vm.set_option(vm.VM_OPT_RESET_ON_HARDFAULT,1)
vm.set_option(vm.VM_OPT_TRACE_ON_HARDFAULT,1)

#test 2: don't reset on hard fault but print trace (Default)
# vm.set_option(vm.VM_OPT_RESET_ON_HARDFAULT,0)
# vm.set_option(vm.VM_OPT_TRACE_ON_HARDFAULT,1)

#test 3: don't reset on hard fault and don't print trace (Default)
# vm.set_option(vm.VM_OPT_RESET_ON_HARDFAULT,0)
# vm.set_option(vm.VM_OPT_TRACE_ON_HARDFAULT,0)

#test 3: reset on hard faultbut don't print trace (Default)
# vm.set_option(vm.VM_OPT_RESET_ON_HARDFAULT,1)
# vm.set_option(vm.VM_OPT_TRACE_ON_HARDFAULT,0)


# here is a function that causes a hard fault by writing to NULL (in c)
@c_native("_hf_function",["hf.c"],[])
def armageddon():
    pass


while True:
    print("Releasing the Armageddon in 2 sec...:-@")
    sleep(2000)
    armageddon()