Skip to content

Example code

There are many example applications in the Mira SDK, including bare metal use of MiraMesh. Here we will show just a few simple examples using MiraOS.

Blinky

This application will blink the 4 LEDs of the nRF52832-DK board in a sequence, it will wait for one second between each update.

/*----------------------------------------------------------------------------
Copyright (c) 2017-2020 LumenRadio AB
This code is the property of LumenRadio AB and may not be redistributed in any
form without prior written permission from LumenRadio AB.

This example is provided as is, without warranty.
----------------------------------------------------------------------------*/

#include <mira.h>
#include <stdio.h>

#define LED1_PIN MIRA_GPIO_PIN(0, 17)
#define LED2_PIN MIRA_GPIO_PIN(0, 18)
#define LED3_PIN MIRA_GPIO_PIN(0, 19)
#define LED4_PIN MIRA_GPIO_PIN(0, 20)

MIRA_IODEFS(
    MIRA_IODEF_NONE,
    MIRA_IODEF_NONE,
    MIRA_IODEF_NONE,
);

PROCESS(main_proc, "Main process");

void mira_setup(void)
{
    MIRA_MEM_SET_BUFFER(14880);

    mira_gpio_set_dir(LED1_PIN, MIRA_GPIO_DIR_OUT);
    mira_gpio_set_dir(LED2_PIN, MIRA_GPIO_DIR_OUT);
    mira_gpio_set_dir(LED3_PIN, MIRA_GPIO_DIR_OUT);
    mira_gpio_set_dir(LED4_PIN, MIRA_GPIO_DIR_OUT);

    process_start(&main_proc, NULL);
}

PROCESS_THREAD(main_proc, ev, data)
{
    static int i;
    static struct etimer timer;

    PROCESS_BEGIN();
    /* Pause once, so we don't run anything before finish of startup */
    PROCESS_PAUSE();

    while (1) {
        /* Negate, since LEDs are active low */
        mira_gpio_set_value(LED1_PIN, !(i%4 == 0));
        mira_gpio_set_value(LED2_PIN, !(i%4 == 1));
        mira_gpio_set_value(LED3_PIN, !(i%4 == 2));
        mira_gpio_set_value(LED4_PIN, !(i%4 == 3));

        etimer_set(&timer, CLOCK_SECOND);
        PROCESS_YIELD_UNTIL(etimer_expired(&timer));

        i++;
    }

    PROCESS_END();
}

Analog to UART

This examples reads the voltage from an analog input of the nRF52832-DK as well as the supply voltage. The voltages are printed to the UART via stdout.

/*----------------------------------------------------------------------------
Copyright (c) 2017-2020 LumenRadio AB
This code is the property of LumenRadio AB and may not be redistributed in any
form without prior written permission from LumenRadio AB.

This example is provided as is, without warranty.
----------------------------------------------------------------------------*/

#include <mira.h>
#include <stdio.h>
#include <string.h>

/*
 * ADC example.
 */

#define ADC_PIN (MIRA_GPIO_PIN(0, 4))

MIRA_IODEFS(
    MIRA_IODEF_NONE,    /* fd 0: stdin */
    MIRA_IODEF_UART(0), /* fd 1: stdout */
    MIRA_IODEF_NONE     /* fd 2: stderr */
);

PROCESS(main_proc, "Main process");

void mira_setup(void)
{
    MIRA_MEM_SET_BUFFER(12288);

    mira_status_t ret;
    mira_uart_config_t uart_config = {
        .baudrate = 115200,
        .tx_pin = MIRA_GPIO_PIN(0, 6),
        .rx_pin = MIRA_GPIO_PIN(0, 8)
    };

    ret = mira_uart_init(0, &uart_config);
    if (ret != MIRA_SUCCESS) {
        /* Nowhere to send an error message */
    }

    process_start(&main_proc, NULL);
}

PROCESS_THREAD(main_proc, ev, data)
{
    static struct etimer timer;
    static mira_adc_context_t vdd_context;
    static mira_adc_value_t vdd_value;
    static mira_adc_context_t pin_context;
    static mira_adc_value_t pin_value;

    PROCESS_BEGIN();
    /* Pause once, so we don't run anything before finish of startup */
    PROCESS_PAUSE();

    printf("ADC example\n");

    mira_adc_init(&vdd_context);
    mira_adc_set_reference(&vdd_context, MIRA_ADC_REF_INT_3_6V);
    mira_adc_set_source_supply(&vdd_context);

    mira_adc_init(&pin_context);
    mira_adc_set_reference(&pin_context, MIRA_ADC_REF_VDD);
    mira_adc_set_source_single(&pin_context, ADC_PIN);

    while (1) {
        /* Measure VDD */
        mira_adc_measurement_start(&vdd_context);
        PROCESS_WAIT_EVENT_UNTIL(
            !mira_adc_measurement_in_progress(&vdd_context));
        mira_adc_measurement_finish(&vdd_context, &vdd_value);

        /* Measure ADC pin */
        mira_adc_measurement_start(&pin_context);
        PROCESS_WAIT_EVENT_UNTIL(
            !mira_adc_measurement_in_progress(&pin_context));
        mira_adc_measurement_finish(&pin_context, &pin_value);

        int32_t vdd_mv = (int32_t)vdd_value * 3600 / 32768; /* An internal 3.6 V
            reference is used. Hence multiplying with 3600 to get mV */
        int32_t pin_mv = (int32_t)pin_value * vdd_mv / 32768;
        printf("Vdd: %6ld mV Pin: %6ld mV\n",
            vdd_mv,
            pin_mv);

        etimer_set(&timer, 1 * CLOCK_SECOND);
        PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
    }

    PROCESS_END();
}

Network example

This example shows how to set up a node to join a network, and to be able to send UDP packets to a root device as well as being able to receive UDP packets.

/*----------------------------------------------------------------------------
Copyright (c) 2017-2020 LumenRadio AB
This code is the property of Lumenradio AB and may not be redistributed in any
form without prior written permission from LumenRadio AB.

This example is provided as is, without warranty.
----------------------------------------------------------------------------*/

#include <mira.h>
#include <stdio.h>
#include <string.h>

#define UDP_PORT 456
#define SEND_INTERVAL 60


static const mira_net_config_t net_config = {
    .pan_id = 0x13243546,
    .key = {
        0x11, 0x12, 0x13, 0x14,
        0x21, 0x22, 0x23, 0x24,
        0x31, 0x32, 0x33, 0x34,
        0x41, 0x42, 0x43, 0x44
    },
    .mode = MIRA_NET_MODE_MESH,
    .rate = MIRA_NET_RATE_MID,
};

/*
 * Identifies as a node.
 * Sends data to the root.
 */

MIRA_IODEFS(
    MIRA_IODEF_NONE,    /* fd 0: stdin */
    MIRA_IODEF_UART(0), /* fd 1: stdout */
    MIRA_IODEF_NONE     /* fd 2: stderr */
    /* More file descriptors can be added, for use with dprintf(); */
);

static void udp_listen_callback(
    mira_net_udp_connection_t *connection,
    const void *data,
    uint16_t data_len,
    const mira_net_udp_callback_metadata_t *metadata,
    void *storage)
{
    char buffer[MIRA_NET_MAX_ADDRESS_STR_LEN];
    uint16_t i;

    printf("Received message from [%s]:%u: ",
        mira_net_toolkit_format_address(buffer, metadata->source_address),
        metadata->source_port);
    for (i = 0; i < data_len - 1; i++) {
        printf("%c", ((char *) data)[i]);
    }
    printf("\n");
}

PROCESS(main_proc, "Main process");

void mira_setup(
    void)
{
    MIRA_MEM_SET_BUFFER(12288);

    mira_status_t uart_ret;
    mira_uart_config_t uart_config = {
        .baudrate = 115200,
        .tx_pin = MIRA_GPIO_PIN(0, 6),
        .rx_pin = MIRA_GPIO_PIN(0, 8)
    };

    uart_ret = mira_uart_init(0, &uart_config);
    if (uart_ret != MIRA_SUCCESS) {
        /* Nowhere to send an error message */
    }

    process_start(&main_proc, NULL);
}

PROCESS_THREAD(main_proc, ev, data)
{
    static struct etimer timer;

    static mira_net_udp_connection_t *udp_connection;

    static mira_net_address_t net_address;
    static char buffer[MIRA_NET_MAX_ADDRESS_STR_LEN];
    static mira_status_t res;
    static const char *message = "Hello Network";

    PROCESS_BEGIN();
    /* Pause once, so we don't run anything before finish of startup */
    PROCESS_PAUSE();

    printf("Starting Node (Sender).\n");
    printf("Sending one packet every %d seconds\n", SEND_INTERVAL);

    /*
     * Set up the Mira Network with a given PAN ID and encryption key.
     */
    mira_status_t result = mira_net_init(&net_config);
    if(result) {
        printf("FAILURE: mira_net_init returned %d\n", result);
        while(1) ;
    }

    /*
     * Open a connection, but don't specify target address yet, which means
     * only mira_net_udp_send_to() can be used to send packets later
     */
    udp_connection = mira_net_udp_connect(NULL, 0, udp_listen_callback, NULL);

    while (1) {
        etimer_set(&timer, SEND_INTERVAL * CLOCK_SECOND);
        PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));

        /* Try to retrieve the root address. */
        res = mira_net_get_root_address(&net_address);

        /*
        * If root address is successfully retrieved, send a message
        * to the root node on the given UDP Port.
        * Close the connection after the message is sent.
        */
        if (res != MIRA_SUCCESS) {
            printf("Waiting for root address\n");
        } else {
            printf("Sending to address: %s\n",
                mira_net_toolkit_format_address(buffer, &net_address));
            mira_net_udp_send_to(udp_connection, &net_address, UDP_PORT,
                message, strlen(message));
        }
    }

    mira_net_udp_close(udp_connection);

    PROCESS_END();
}