Host a wasm module on Raspberry Pi easily Part 1

Knoldus Blog Audio
Reading Time: 5 minutes

In this series of WebAssembly, I tell you about wasm and some useful CLI to have fun with wasm. WebAssembly is an open standard that defines a portable binary code format for executable programs, and a corresponding textual representation for interactions between such programs and their hosts. More than 20 companies reportedly use WebAssembly in their tech stacks, including Backend, Foretag, and Cubbit. C++CRust, Blazor, and Yew Framework are some of the popular tools that can integrate with WebAssembly. WebAssembly is a widely used compile target for Rust. Rust also helps us to host wasm modules easily. This enables us to use an IoT device like Raspberry Pi as a host.

In this blog of the series, I will tell you how to host a wasm module generated by a Rust program in your IoT devices like Raspberry Pi. So let’s see how can we do this.

Overview

Host Raspberry Pi
Raspberry Pi 2

In my previous blog, I showed you how to host a wasm module in a Rust program using wasmi. You can check that blog for reference. In this blog, I will be using wasmi to make a rust program to act as a wasm host on Raspberry Pi. We will compile the rust program to armv7 as Raspberry Pi 2+ devices are arm v7 devices. Then we will host a WebAssembly module on the Raspberry Pi.

First of all, we will be writing the program in Rust that is to be hosted and then compile it to wasm. We’re going to build a battery indicator. Its operation is quite simple. One of the sensor inputs represents the amount of
battery remaining as a percentage. In response to that percentage, we’re going to control the colour of a group of eight LEDs. Let’s begin.

Battery Indicator

The LEDs can light up colours as a combination of RGB components ranging in between 0 to 255. The actual hardware that is used is Blinkt! Pimoroni. You can buy this online if you want to implement this.

Blinkt!
Blinkt! Pimoroni

There are 8 LEDs on a Blinkt!. So the core logic is to divide the maximum battery percentage by 8, i.e., 100 by 8 (100/8 = 12.5 ) to get the percentage per LED. We can call this value percent_per_pixel. Then we can use this value to light up the LEDs based on the number we get after dividing the current battery percentage by percent_per_pixel. If the value after dividing is a floating-point number then we take the ceiling value.

For example – if the battery percentage is 80 then the number of LEDs lighting up will be 7 as 80 / 12.5 = 6.4, so we take the ceiling value.

So let’s see the code and then discuss it further.

#[derive(PartialEq, Debug, Clone)]
struct LedColor(i32, i32, i32); 

const SENSOR_BATTERY: i32 = 20;

const OFF:LedColor =  LedColor(0, 0, 0);
const YELLOW: LedColor = LedColor(255, 255, 0);
const GREEN: LedColor = LedColor(0, 255, 0);
const RED: LedColor = LedColor(255, 0, 0);
const PCT_PER_PIXEL: f64 = 12.5_f64;


extern "C" {
    fn set_led(led_index: i32, r: i32, g: i32, b: i32); 
}


#[no_mangle]
pub extern "C" fn sensor_update(sensor_id: i32, sensor_value: f64) -> f64 { 
    if sensor_id == SENSOR_BATTERY {
        set_leds(get_led_values(sensor_value));
    }
    sensor_value
}

#[no_mangle]
pub extern "C" fn apply(_frame: u32) {
    // NO OP, not an animated indicator
}


fn get_led_values(battery_remaining: f64) -> [LedColor; 8] {
    let mut arr: [LedColor; 8] = [OFF,OFF,OFF,OFF,OFF,OFF,OFF,OFF,];
    let lit = (battery_remaining / PCT_PER_PIXEL).ceil();

    // 0 - 20 : Red
    // 21 - 50 : Yellow
    // 51 - 100 : Green

    let color = if 0.0 <= battery_remaining &&
        battery_remaining <= 20.0 {
        RED
    } else if battery_remaining > 20.0 && battery_remaining < 50.0 {
        YELLOW
    } else {
        GREEN
    };

    for index in 0..lit as usize {
        arr[index] = color.clone();
    }
    arr
}

fn set_leds(values: [LedColor; 8]) { // (5)
    for index in 0..8 {
        let LedColor(r, g, b) = values[index];
        unsafe {
            set_led(index as i32, r,g,b);
        }
    }
}

The program defines a tuple struct LedColor for the RGB value of each LED. SENSOR_BATTERY is the sensor_id for the sensor giving the battery percentage. Then we define the RGB value for each of the colours we are going to use to represent battery percentage.

This Program exports two functions, sensor_update and apply and imports the set_led function from the host. Let’s see what these functions do.

sensor_update function

The sensor_update function takes two values sensor_id and sensor_value. The sensor_id is the id of the sensor sending the battery percentage and the sensor_value is the actual battery percentage of the battery.

The function checks if the input is from the battery sensor or not. Then it calls the set_leds function that sets the LEDs on the Blinkt! as ON or OFF and also sets the colour of the LEDs. apply() function is not defined as it is used to create animations.

set_leds function

set_leds function takes an array of LedColor objects as arguments. LedColor is a tuple struct that defines the RGB values for the colours of LEDs. It sets the desired LEDs with respective colours on the host. It makes an unsafe call to the imported function set_let to set the LEDs. The unsafe denote that Rust does not guarantee the type safety of this function as it is an imported function.

get_led_values function

This function takes the battery percentage as an argument that is passed to the sensor_update function. This function then calculates the number of LEDs to light up by the same method we discussed above, i.e., dividing the battery percentage by 12.5 and then taking the ceiling value. It then uses this value to fill an array of type LedColor with colour according to the current battery percentage. We use Red colour for battery percentages lying in range 0 to 20, Yellow colour for battery percentages lying in range 21 to 50 and Green colour for battery percentages lying in range 51 to 100.

After that, it calls the set_leds function and pass the LedColor array to light up the LEDs.

Now we are all set to host this program on our Raspberry Pi but before that, we need to create a host program that will run on our Raspberry Pi and continuously watch for the wasm module. We will see how to build a host on Raspberry pi in our next blog. So stay tuned.

Before that make sure you compile this program to wasm so that we can use this and run the battery indicator on Raspberry pi.


If you want to read more content like this?  Subscribe to Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe to Rust Times Newsletter: https://bit.ly/2Vdlld7.


Knoldus-blog-footer-image

1 thought on “Host a wasm module on Raspberry Pi easily Part 16 min read

Leave a Reply