Skip to main content

Part 3: Full embedded application

1. Introductionโ€‹

The purpose of this training is to create a full embedded application that detects all the services in the system and create a switcher that turns on or off a LED, depending on a button.

Let's code that and see how cool it is to do it with Luos engine!

2. Add the package buttonโ€‹

For now, there are tow packages in the project. In the next step, we will add the button package into main.c or Arduino.ino.

#include <luos_engine.h>
#include "led.h"
// the new line to copy and paste
#include "button.h"
#include "switcher.h"

#ifdef __cplusplus
}
#endif

/******************************************************************************
* @brief Setup ardiuno
* @param None
* @return None
******************************************************************************/
void setup()
{
Luos_Init();
Led_Init();
// the new line to copy and paste
Button_Init();
Switcher_Init();
}
/******************************************************************************
* @brief Loop Arduino
* @param None
* @return None
******************************************************************************/
void loop()
{
Luos_Loop();
Led_Loop();
// the new line to copy and paste
Button_Loop();
Switcher_Loop();
}
caution

You must call the Luos_Init() API before any service initialization to make the library work properly.

tip

The actual detection will be performed at Luos_Loop() execution. So it is better to call the Luos_Loop() function first, allowing the services to start working as soon as possible.

3. Find the button service's IDโ€‹

The button package is now added to your project. we must find its ID to send a message to it.

  1. Create a variable where the ID of button service will be saved:
/*******************************************************************************
* Variables
******************************************************************************/
service_t *switcher_app; // This will be our switcher service
uint16_t ID_Led;
// the new line to copy and paste
uint16_t ID_Button;
  1. Filter the button service alias in the routing table and ask it about it:
void Switcher_MsgHandler(service_t *service, msg_t *msg)
{
if (msg->header.cmd == END_DETECTION)
{
search_result_t filter_result;
RTFilter_Reset(&filter_result); // Init your filter.
// Now your filter_result have the entire routing table. #nofilter ;)
RTFilter_Alias(&filter_result, "led"); // Filter your filter_result only keep the services with the alias "led"
ID_Led = filter_result.result_table[0]->id;//recover the first service ID with alias "led"

// the three new lines to copy and paste
RTFilter_Reset(&filter_result); // Reset your filter.
RTFilter_Alias(&filter_result, "button");
ID_Button = filter_result.result_table[0]->id;

if (ID_Led > 0)
{
msg_t pub_msg;
pub_msg.header.cmd = IO_STATE;
pub_msg.header.target_mode = ID;
pub_msg.header.target = ID_Led; // configure the target to be our led service ID
pub_msg.header.size = 1;
pub_msg.data[0] = 1;
Luos_SendMsg(switcher_app, &pub_msg);
}
}
}

4. Ask for the button valueโ€‹

Now that we have the button service's ID, we can easily get the button's value (or state) by sending a message to the button service in Switcher_Loop. The button service will reply with a message containing the button's value

If we send this request at every loop, this will create too many messages and overload the network, consuming a lot of RAM and creating network congestion.

Let's space them to 10ms between each one!

1. Execute request every 10msโ€‹

We will have to bring improvement to the Switcher_loop to be able to send a message every 10ms.

You can use the sysTick to get a 1ms precision date using Luos_GetSystick();. This tick gives you the opportunity to count the milliseconds.

Let's create a variable to track the LastAsk:

/*******************************************************************************
* Variables
******************************************************************************/
service_t *switcher_app; // This will be our switcher service
uint16_t ID_Led;
uint16_t ID_Button;
// the new line to copy and paste
uint32_t LastAsk;

Initialize this variable at the service start:

void Switcher_Init(void)
{
revision_t revision = {1, 0, 0};
switcher_app = Luos_CreateService(Switcher_MsgHandler, SWITCHER_APP, "Switcher", revision);
Luos_Detect(switcher_app);
// the new line to copy and paste
LastAsk = Luos_GetSystick();
}

Check if 10ms have passed:

void Switcher_Loop(void)
{
// the new block to copy and paste
// ask button value every 10ms
if ((Luos_GetSystick() - LastAsk) > 10)
{
// Ask the button
LastAsk = Luos_GetSystick();
}
}

2. Be sure a that detection has been made before sending a message on a networkโ€‹

before sending a request value to the button service, we have to be sure that a detection has been made. Luos engine provides a specific API allowing you to know if your system has been detected or not: bool Luos_IsNodeDetected(void)

This function returns TRUE when your system has been entirely detected:

void Switcher_Loop(void)
{
// the new block to copy and paste
if (Luos_IsNodeDetected() == true) // Topology detection completed
{
// ask button value every 10ms
if ((Luos_GetSystick() - LastAsk) > 10)
{
LastAsk = Luos_GetSystick();
}
}
}

3. Finally, ask for the button's valueโ€‹

Now taht everything is ready, we can ask the button to send us its value:

void Switcher_Loop(void)
{
if (Luos_IsNodeDetected() == true) // Topology detection completed
{
// ask button value every 10ms
if ((Luos_GetSystick() - LastAsk) > 10)
{
// the new block to copy and paste
if (ID_Button > 0)
{
// Ask the button
msg_t pub_msg;
pub_msg.header.cmd = IO_STATE;
pub_msg.header.target_mode = ID;
pub_msg.header.target = ID_Button;
pub_msg.header.size = 0;
Luos_SendMsg(switcher_app, &pub_msg);
}
LastAsk = Luos_GetSystick();
}
}
}

The button sends us an update every 10ms!

5. Turn on the LED depending on the button's valueโ€‹

In the Switcher_Loop() function, we asked the button to send us an update every 10ms. The reply of the button will be received on the Switcher_MsgHandler function.

1. Let's add a new condition in our message handler allowing us to deal with the button's messages:โ€‹

void Switcher_MsgHandler(service_t *service, msg_t *msg)
{
if (msg->header.cmd == END_DETECTION)
{
search_result_t filter_result;
RTFilter_Reset(&filter_result); // Init your filter.
// Now your filter_result have the entire routing table. #nofilter ;)
RTFilter_Alias(&filter_result, "led"); // Filter your filter_result only keep the services with the alias "led"
ID_Led = filter_result.result_table[0]->id;//recover the first service ID with alias "led"

RTFilter_Reset(&filter_result); // Reset your filter.
RTFilter_Alias(&filter_result, "button");
ID_Button = filter_result.result_table[0]->id;

if (ID_Led > 0)
{
msg_t pub_msg;
pub_msg.header.cmd = IO_STATE;
pub_msg.header.target_mode = ID;
pub_msg.header.target = ID_Led // configure the target to be our led service ID
pub_msg.header.size = 1;
pub_msg.data[0] = 1;
Luos_SendMsg(switcher_app, &pub_msg);
}
}
// the new block to copy and paste
else if ((msg->header.cmd == IO_STATE) && (msg->header.source == ID_Button))
{
// Command the led accordingly to the button message
}
}

To properly switch the LED, we have to deal with this button's message and send a command to the LED.

2. Type the code that sends a message to turn on the LED at the end of the detection, inside the button's reception message condition:โ€‹

void Switcher_MsgHandler(service_t *service, msg_t *msg)
{
if (msg->header.cmd == END_DETECTION)
{
search_result_t filter_result;
RTFilter_Reset(&filter_result); // Init your filter.
// Now your filter_result have the entire routing table. #nofilter ;)
RTFilter_Alias(&filter_result, "led"); // Filter your filter_result only keep the services with the alias "led"
ID_Led = filter_result.result_table[0]->id;//recover the first service ID with alias "led"

RTFilter_Reset(&filter_result); // Reset your filter.
RTFilter_Alias(&filter_result, "button");
ID_Button = filter_result.result_table[0]->id;
}
else if ((msg->header.cmd == IO_STATE) && (msg->header.source == ID_Button))
{
// the new block to copy and paste
// Command the led accordingly to the button message
if (ID_Led > 0)
{
msg_t pub_msg;
pub_msg.header.cmd = IO_STATE;
pub_msg.header.target_mode = ID;
pub_msg.header.target = ID_Led // configure the target to be our led service ID
pub_msg.header.size = 1;
pub_msg.data[0] = 1;
Luos_SendMsg(switcher_app, &pub_msg);
}
}
}

At this point, everytime you receive a message from the button service, you will turn on the LED.

3. To finish, we simply need to send to the LED the state of the button.โ€‹

This button's value is recovered in the first case of the tab data of the button's message:

...
else if ((msg->header.cmd == IO_STATE) && (msg->header.source == ID_Button))
{
// Command the led accordingly to the button message
if (ID_Led > 0)
{
msg_t pub_msg;
pub_msg.header.cmd = IO_STATE;
pub_msg.header.target_mode = ID;
pub_msg.header.target = ID_Led // configure the target to be our led service ID
pub_msg.header.size = 1;
// the new line to copy and paste
pub_msg.data[0] = msg->data[0];
Luos_SendMsg(switcher_app, &pub_msg);
}
}
...

Because we asked the button to update its value every 10ms, we will receive a button update every 10ms. At each update reception a new LED command will be sent, so the LED is also updated every 10ms.

This way, your button control your LED.

6. Try to change button's valueโ€‹

  1. Compile and upload the project to the board. the LED turns on at the end of the detection.

  2. Push on your button:

To simulate a press button, connect a wire between the BTN_PIN (Pin 8) and GND.

luos_img

Congratulation, You created your first full embedded application!

gif_congrat

You can now detect all the services in your project and command them through an application.

7. Exerciseโ€‹

Now try to move your switcher package on another board, and keep the button and led packages on the first one: everything should work the same way!

Asking the value of the button every 10ms represents a not negligible portion of code. Luos engine provides an update_time command to simplify it, check the documentation associated page to learn more about it.

The author: Viktoria

Engineer at Luos
Viktoria

Embedded system engineer at Luos, MSc in Embedded Real-Time Systems. Originated from Greece, Viktoria wishes to effectively advocate the presence of women in Engineering.

Related Content


    Your first detection Repository