Skip to main content

Part 2: Send a message from a button service

1. Introduction

There are two ways to receive a message, but what about sending one?

gif_how_it_workgif_how_it_work

Don't worry, we will see how to do it step by step.

2. Set up your hardware

Begin by setting up the MCU pins for your button in the file button.c:

#include <Arduino.h>
#include "button.h"

/*******************************************************************************
* Definitions
******************************************************************************/
// the new line to copy and paste
#define BTN_PIN 8

Set the pin as an input:


void Button_Init(void)
{
revision_t revision = {1, 0, 0};
button_service = Luos_CreateService(0, STATE_TYPE, "button", revision);
// the new line to copy and paste
pinMode(BTN_PIN, INPUT);
}

Now everything is ready to send back the button's value in a message.

3. Send back the button's value

By learning how to catch messages from the previous page of this tutorial, we already know that they contain some interesting information allowing you to understand the meaning of the transmitted data.

Any message contains two main parts:

luos_imgluos_img

The Data is the actual transmitted data.

The Header contains some contextual information allowing the receiver to get the purpose of the Data.

info

For more information about the messages, you can refer to the related documentation page.

To send a message, you will need to fill in some header information regarding the target and the data of you message:

Message target

In this button service, we want to reply to a request coming from another service. So we will target this specific service and be sure that it gets the answer.

To do that, we will need to configure the following information:

  • target_mode as IDACK ⇒ because we target only one service and want to be sure it gets the message

  • target as the requested source message ⇒ because we want to target the service sending the request.

Message data meaning

To send the message, we also need to explain the meaning of the data.

In this button service, we want to send an IO_STATE, so data size will be a byte because it just needs to send 1 or 0. To do that, we will need to configure the following information:

  • cmd as IO_STATE ⇒ to define the type of transmited data

  • size as 1 ⇒ because only 1 byte is sent

  • data as the button's state ⇒ this will be the actual data.

info

On the message request filtering you previously made, we did not look at the message size. This is because a request does not need any data. most of the time, a message where size = 0 is equivalent to a “get” command. If size != 0, it means that you want to set something by sending a value.

4. Send back the button's value

After filling in all this information, we are now able to send it using the Luos_SendMsg function.

This function needs to know which service wants to send this message, so you will need to provide it with your service and the message you want to send in arguments.

info

Luos_SendMsg function returns an error_return_t information allowing you to know if the message transmission FAILED or SUCCEED.

error_return_t Luos_SendMsg(service_t *service, msg_t *msg)

The only reason why this function sends back a FAILED status is because there is not enough RAM in your device.

Write it in the code

Let's fill in the information of the structure:

void Button_Loop(void)
{
msg_t* msg;
while (Luos_ReadMsg(button_service, &msg) == SUCCEED)
{
if ((msg->header.cmd == IO_STATE)||(msg->header.cmd == UNKNOW)
{
// the new block to copy and paste
// fill the message infos
msg_t pub_msg;
pub_msg.header.cmd = IO_STATE;
pub_msg.header.target_mode = IDACK;
pub_msg.header.target = msg->header.source;
pub_msg.header.size = sizeof(char); // 1 byte
pub_msg.data[0] = digitalRead(BTN_PIN);
Luos_SendMsg(service, &pub_msg);
}
}
}

The STATE button service now returns an IO_STATE value when a service asks for it! Let's see if our service reacts as expected.

gif_testgif_test

5. Test the response

  1. Compile and upload the project to the board.
  2. Using the command pyluos-shell in a terminal, you should see the following routing table:
  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ╭node 1 /!\ Not certified ┃
┃ │ Type Alias ID ┃
┃ ├> Pipe Pipe 2
┃ ├> Gate gate 1
┃ ╰> State button 3
>┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Typing device.button.state, you should see the pin's value:

In [1]: device.button.state
Out[1]: False
To simulate a press button, connect a wire between the BTN_PIN (pin 8) and GND.
luos_imgluos_img

Typing device.button.state, you should see the new pin's value:

In [2]: device.button.state
Out[2]: True

6. Exercise: control a LED depending on your button's state

Let's try a small exercise:

Make a LED turn on when the button's state is TRUE and off when it's FALSE.

  1. Add the led package created on the previous tutorial on your board.

  2. Compile and flash your board again.

  3. Type pyluos-shell in the terminal again, you should see:

      ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
    ┃ ╭node 1 /!\ Not certified ┃
    ┃ │ Type Alias ID ┃
    ┃ ├> Pipe Pipe 2
    ┃ ├> Gate gate 1
    ┃ ├> State button 3
    ┃ ╰> State led 4
    >┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
  4. Then still in Pyluos-shell type:

    while True :
    device.led.state = device.button.state
  5. Run this while-loop and try to push on the button to see the LED turning on and off.

gif_ligthgif_ligth

7. Test your skills

The author: Nicolas C.

Embedded Engineer
Nicolas C.

Experienced engineer in embedded software and hardware engineering with strong skills in embedded Linux, digital and analog hardware, and radiocommunication.