O objetivo deste BLOG é mostrar outra opção para desenvolver código personalizado para o STM32WL55, ou seja, via Mbed-OS. É um sistema operacional de código aberto e fácil de usar para a Internet das Coisas (IoT), desenvolvido pela ARM.
BETA - EM TESTES - APENAS PARA PROGRAMADORES COM Mbed-OS
Mbed-OS
O Mbed oferece um sistema operacional IoT de código aberto gratuito com conectividade, segurança, armazenamento, gerenciamento de dispositivos e aprendizado de máquina. Construa seu próximo produto com ferramentas de desenvolvimento gratuitas, milhares de exemplos de código e suporte para centenas de placas de desenvolvimento de microcontroladores.
APP
Este é um aplicativo de exemplo baseado nas APIs de protocolo Mbed-OS LoRaWAN. A implementação da pilha Mbed-OS LoRaWAN está em conformidade com a especificação LoRaWAN v1.0.2. Este aplicativo pode funcionar com qualquer Servidor de Rede se você tiver credenciais corretas para o referido Servidor de Rede.
Compilar e atualizar o firmware
Você pode compilar e atualizar a placa com excelente framework mbed-os. A maneira mais fácil é com a IDE do Mbed Studio.
Basicamente adicionaremos a placa com STM32WL55 em stm32customtargets e finalmente, o programa principal do firmware mbed-os-example-lorawan.
Instalando a IDE do Mbed Studio
Mbed Studio | Mbed (ou Keil Studio Cloud)
- use file/import program e importe o exemplo com URL https://github.com/ARMmbed/mbed-os-example-lorawan
- clique com o botão direito no nome do projeto e selecione Adicionar Biblioteca e digite https://github.com/ARMmbed/stm32customtargets
Mantenha as LIBS atualizadas
- cole o conteúdo copiado no arquivo da pasta raiz principal custom_targets.json (sim, substitua o arquivo inteiro)
Altere os parâmetros LoRaWAN, como plano de frequência, OTAA, Duty Cycle, ...
- substitua as chaves pelas que você obteve, lora.device-eui, lora.application-eui e lora.application-key
Em seguida, no IDE, selecione o alvo "NUCLEO-WL55JC", build e faça o flash com seu programador favorito (estou usando STLink) com GND/SWDIO/SWDCLK/RESET conectado.
Escolha Target NUCLEO-WL55JC
Compilação (Build) e Gravação
A partir do IDE você pode pode dar um Build no exemplo.
Configuração e seleção do Rádio
Para módulos LoRa suportados pelo Mbed-OS, o conjunto de pinos já está fornecido target-overrides do arquivo mbed_app.json.
Sub-band
"lora.fsb-mask": "{0xFF00, 0x0000, 0x0000, 0x0000, 0x0002}"
"target_overrides": {
"*": {
"platform.stdio-convert-newlines": true,
"platform.stdio-baud-rate": 115200,
"platform.default-serial-baud-rate": 115200,
"mbed-trace.enable": false,
"mbed-trace.max-level": "TRACE_LEVEL_DEBUG",
"lora.over-the-air-activation": true,
"lora.duty-cycle-on": true,
"lora.phy": "AU915",
"lora.device-eui": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }",
"lora.application-eui": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }",
"lora.application-key": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }"
"lora.fsb-mask": "{0xFF00, 0x0000, 0x0000, 0x0000, 0x0002}"
},
Adicionando credenciais de Rede
Abra o arquivo mbed_app.json no diretório raiz do seu aplicativo. Este arquivo contém todas as configurações específicas do usuário que o aplicativo e a pilha Mbed OS LoRaWAN precisam. As credenciais de rede são normalmente fornecidas pelo provedor de rede LoRa.
Para OTAA
Por favor, adicione o Dispositivo EUI, o aplicativo EUI e a chave de aplicação necessária para ativação over-the-air(OTAA). Por exemplo:
"lora.device-eui": "{ YOUR_DEVICE_EUI }",
"lora.application-eui": "{ YOUR_APPLICATION_EUI }",
"lora.application-key": "{ YOUR_APPLICATION_KEY }"
"lora.over-the-air-activation": true,
Para ABP
Para o método de conexão ABP (Activation-By-Personalization, conexão ativação por personalização), modifique o mbed_app.json para habilitar a ABP. Você pode fazê-lo simplesmente desligando OTAA. Por exemplo:
"lora.over-the-air-activation": false,
Além disso, você precisa fornecer chave de sessão de aplicativos, chave de sessão de rede e endereço do dispositivo. Por exemplo:
"lora.appskey": "{ YOUR_APPLICATION_SESSION_KEY }",
"lora.nwkskey": "{ YOUR_NETWORK_SESSION_KEY }",
"lora.device-address": " YOUR_DEVICE_ADDRESS_IN_HEX "
Configuração do aplicativo
A pilha Mbed OS LoRaWAN fornece muitos controles de configuração para o aplicativo através do sistema de configuração Mbed OS configuration system. Esta seção destaca alguns recursos úteis que você pode configurar.
Selecionando um PHY
O protocolo LoRaWAN está sujeito a regulamentos específicos de vários países relativos às emissões de rádio. É por isso que a pilha Mbed OS LoRaWAN fornece uma classe LoRaPHY que você pode usar para implementar qualquer camada PHY específica da região. Atualmente, a pilha Mbed OS LoRaWAN fornece 10 implementações específicas de países diferentes da classe LoRaPHY. A seleção de uma camada PHY específica acontece no momento da compilação. Por padrão, a pilha Mbed OS LoRaWAN usa PHY EU 868MHz.
"lora.phy": "AU915",
Duty Cycle
A especificação LoRaWAN v1.0.2 é exclusivamente baseada em Duty Cycle. Este aplicativo vem com Duty Cycle. Em outras palavras, a pilha Mbed OS LoRaWAN impõe o Duty Cycle. A pilha mantém o controle das transmissões nos canais em uso e programa transmissões em canais que ficam disponíveis no menor tempo possível. Recomendamos que você mantenha o ciclo de serviço ligado para o cumprimento das regulamentações específicas do seu país.
"target_overrides": {
"*": {
"lora.duty-cycle-on": false
}
}
Ficando então assim mbed_app.json
{
"config": {
"main_stack_size": { "value": 4096 }
},
"target_overrides": {
"*": {
"lora.tx-max-size": 242,
"platform.stdio-convert-newlines": true,
"platform.stdio-baud-rate": 115200,
"platform.default-serial-baud-rate": 115200,
"mbed-trace.enable": false,
"mbed-trace.max-level": "TRACE_LEVEL_DEBUG",
"lora.over-the-air-activation": true,
"lora.duty-cycle-on": true,
"lora.phy": "AU915",
"lora.device-eui": "{ 0x00,0x2c,0x00,0xff,0x00,0x00,0x59,0x9e}",
"lora.application-eui": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99 }",
"lora.application-key": "{ 0x83, 0x12, 0x41, 0x00, 0xf1, 0x04, 0x00, 0x5f, 0x9c, 0xc3, 0x9f, 0x9c, 0x05, 0x66, 0x3f, 0x16 }",
"lora.fsb-mask": "{0xFF00, 0x0000, 0x0000, 0x0000, 0x0002}"
},
"NUCLEO_WL55JC": {
"stm32wl-lora-driver.debug_rx": "LED1",
"stm32wl-lora-driver.debug_tx": "LED2"
},
"MTB_MURATA_ABZ": {
"main_stack_size": 1024,
"target.components_add": ["SX1276"],
"sx1276-lora-driver.spi-mosi": "PA_7",
"sx1276-lora-driver.spi-miso": "PA_6",
"sx1276-lora-driver.spi-sclk": "PA_5",
"sx1276-lora-driver.spi-cs": "PA_4",
"sx1276-lora-driver.reset": "PA_8",
"sx1276-lora-driver.dio0": "PA_12",
"sx1276-lora-driver.dio1": "PB_2",
"sx1276-lora-driver.dio2": "PB_5",
"sx1276-lora-driver.dio3": "PB_0",
"sx1276-lora-driver.txctl": "PC_2",
"sx1276-lora-driver.rxctl": "PA_15",
"sx1276-lora-driver.pwr-amp-ctl": "PC_1",
"sx1276-lora-driver.tcxo": "PB_1"
}
},
"macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_lora_config.h\""]
}
e ficando assim o main.cpp
/**
* Copyright (c) 2017, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "lorawan/LoRaWANInterface.h"
#include "lorawan/system/lorawan_data_structures.h"
#include "events/EventQueue.h"
// Application helpers
#include "trace_helper.h"
#include "lora_radio_helper.h"
#include "mbed-os/platform/mbed-trace/include/mbed-trace/mbed_trace.h"
using namespace events;
// Max payload size can be LORAMAC_PHY_MAXPAYLOAD.
// This example only communicates with much shorter messages (<30 bytes).
// If longer messages are used, these buffers must be changed accordingly.
uint8_t tx_buffer[500];
uint8_t rx_buffer[500];
/*
* Sets up an application dependent transmission timer in ms. Used only when Duty Cycling is off for testing
*/
#define TX_TIMER 10000
/**
* Maximum number of events for the event queue.
* 10 is the safe number for the stack events, however, if application
* also uses the queue for whatever purposes, this number should be increased.
*/
#define MAX_NUMBER_OF_EVENTS 10
/**
* Maximum number of retries for CONFIRMED messages before giving up
*/
#define CONFIRMED_MSG_RETRY_COUNTER 3
/**
* This event queue is the global event queue for both the
* application and stack. To conserve memory, the stack is designed to run
* in the same thread as the application and the application is responsible for
* providing an event queue to the stack that will be used for ISR deferment as
* well as application information event queuing.
*/
static EventQueue ev_queue(MAX_NUMBER_OF_EVENTS *EVENTS_EVENT_SIZE);
/**
* Event handler.
*
* This will be passed to the LoRaWAN stack to queue events for the
* application which in turn drive the application.
*/
static void lora_event_handler(lorawan_event_t event);
/**
* Constructing Mbed LoRaWANInterface and passing it the radio object from lora_radio_helper.
*/
static LoRaWANInterface lorawan(radio);
/**
* Application specific callbacks
*/
static lorawan_app_callbacks_t callbacks;
//APB:
// static uint32_t DEV_ADDR = 0x;
// static uint8_t NWK_SKEY[] = {};
// static uint8_t APP_SKEY[] = {};
//OTAA:
static uint8_t DEV_EUI[] = { 0x10, 0x00, 0x1f, 0xff, 0x00, 0x53, 0x00, 0x9e };
static uint8_t APP_EUI[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t APP_KEY[] = { 0x33, 0x11, 0x41, 0x11, 0xf1, 0x04, 0x52, 0x51, 0x9d, 0xd3, 0x9f, 0x9c, 0x05, 0x66, 0x3f, 0x16 };
/**
* Entry point for application
*/
int main(void)
{
// stores the status of a call to LoRaWAN protocol
lorawan_status_t retcode;
// Initialize LoRaWAN stack
if (lorawan.initialize(&ev_queue) != LORAWAN_STATUS_OK) {
printf("\r\n LoRa initialization failed! \r\n");
return -1;
}
printf("\r\n Mbed LoRaWANStack initialized \r\n");
// prepare application callbacks
callbacks.events = mbed::callback(lora_event_handler);
lorawan.add_app_callbacks(&callbacks);
// Set number of retries in case of CONFIRMED messages
if (lorawan.set_confirmed_msg_retries(CONFIRMED_MSG_RETRY_COUNTER)
!= LORAWAN_STATUS_OK) {
printf("\r\n set_confirmed_msg_retries failed! \r\n\r\n");
return -1;
}
printf("\r\n CONFIRMED message retries : %d \r\n",
CONFIRMED_MSG_RETRY_COUNTER);
// Enable adaptive data rate
if (lorawan.disable_adaptive_datarate() != LORAWAN_STATUS_OK) {
printf("\r\n disable_adaptive_datarate failed! \r\n");
return -1;
}
printf("\r\n Adaptive data rate (ADR) - Disabled \r\n");
lorawan_connect_t connect_params;
//OTAA:
connect_params.connect_type = LORAWAN_CONNECTION_OTAA;
connect_params.connection_u.otaa.dev_eui = DEV_EUI;
connect_params.connection_u.otaa.app_eui = APP_EUI;
connect_params.connection_u.otaa.app_key = APP_KEY;
connect_params.connection_u.otaa.nb_trials = 3;
//ABP:
// connect_params.connect_type = LORAWAN_CONNECTION_ABP;
// connect_params.connection_u.abp.dev_addr = DEV_ADDR;
// connect_params.connection_u.abp.nwk_skey = NWK_SKEY;
// connect_params.connection_u.abp.app_skey = APP_SKEY;
retcode = lorawan.connect(connect_params);
if (retcode == LORAWAN_STATUS_OK ||
retcode == LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
} else {
printf("\r\n Connection error, code = %d \r\n", retcode);
return -1;
}
printf("\r\n Connection - In Progress ...\r\n");
// make your event queue dispatching events forever
ev_queue.dispatch_forever();
return 0;
}
/**
* Sends a message to the Network Server
*/
static void send_message()
{
static uint8_t packet_toggle = 0;
uint16_t packet_len;
int16_t retcode;
float temperature_bme = 0;
float pressure_bme = 0;
float humidity_bme = 0;
float gas_res_bme = 0;
float co2_eq_bme = 0;
float breath_voc_eq_bme = 0;
float iaq_score_bme = 0;
uint8_t iaq_acc_bme = 0;
uint32_t humidity_si = 0;
uint32_t temp_si = 0;
float x_accel = 0;
float y_accel = 0;
float z_accel = 0;
float x_mag = 0;
float y_mag = 0;
float z_mag = 0;
float x_gyro = 0;
float y_gyro = 0;
float z_gyro = 0;
uint32_t distance = 0;
float vbat = 0;
if(!packet_toggle)
packet_len = sprintf((char *) tx_buffer, "{\"Data_Msg_0\":{\"temp_bme\":%3.3f,\"pres_bme\":%3.3f,\"hum_bme\":%3.3f,\"gas_res_bme\":%3.3f,\"co2_eq_bme\":%3.3f,\"breath_voc_eq_bme\":%3.3f,"
"\"iaq_score_bme\":%3.3f,\"iaq_acc_bme\":%d}}",temperature_bme, pressure_bme, humidity_bme, gas_res_bme, co2_eq_bme, breath_voc_eq_bme, iaq_score_bme,
iaq_acc_bme);
if(packet_toggle)
packet_len = sprintf((char *) tx_buffer, "{\"Data_Msg_1\":{\"hum_si\":%lu,\"temp_si\":%lu,\"x_accel\":%3.3f,\"y_accel\":%3.3f,"
"\"z_accel\":%3.3f,\"x_mag\":%3.3f,\"y_mag\":%3.3f,\"z_mag\":%3.3f,\"x_gyro\":%3.3f,\"y_gyro\":%3.3f,\"z_gyro\":%3.3f,"
"\"dist\":%lu,\"vbat\":%3.3f}}",humidity_si, temp_si, x_accel, y_accel, z_accel,
x_mag, y_mag, z_mag,x_gyro, y_gyro, z_gyro,distance, vbat);
packet_toggle ^= 1;
retcode = lorawan.send(MBED_CONF_LORA_APP_PORT, tx_buffer, packet_len,
MSG_UNCONFIRMED_FLAG);
if (retcode < 0) {
retcode == LORAWAN_STATUS_WOULD_BLOCK ? printf("send - WOULD BLOCK\r\n")
: printf("\r\n send() - Error code %d \r\n", retcode);
if (retcode == LORAWAN_STATUS_WOULD_BLOCK) {
//retry in 3 seconds
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
ev_queue.call_in(3000, send_message);
}
}
return;
}
printf("\r\n %d bytes scheduled for transmission \r\n", retcode);
memset(tx_buffer, 0, sizeof(tx_buffer));
}
/**
* Receive a message from the Network Server
*/
static void receive_message()
{
uint8_t port;
int flags;
int16_t retcode = lorawan.receive(rx_buffer, sizeof(rx_buffer), port, flags);
if (retcode < 0) {
printf("\r\n receive() - Error code %d \r\n", retcode);
return;
}
printf(" RX Data on port %u (%d bytes): ", port, retcode);
for (uint8_t i = 0; i < retcode; i++) {
printf("%02x ", rx_buffer[i]);
}
printf("\r\n");
memset(rx_buffer, 0, sizeof(rx_buffer));
}
/**
* Event handler
*/
static void lora_event_handler(lorawan_event_t event)
{
switch (event) {
case CONNECTED:
printf("\r\n Connection - Successful \r\n");
lorawan.set_datarate(4);
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
send_message();
} else {
ev_queue.call_every(TX_TIMER, send_message);
}
break;
case DISCONNECTED:
ev_queue.break_dispatch();
printf("\r\n Disconnected Successfully \r\n");
break;
case TX_DONE:
printf("\r\n Message Sent to Network Server \r\n");
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
send_message();
}
break;
case TX_TIMEOUT:
case TX_ERROR:
case TX_CRYPTO_ERROR:
case TX_SCHEDULING_ERROR:
printf("\r\n Transmission Error - EventCode = %d \r\n", event);
// try again
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
send_message();
}
break;
case RX_DONE:
printf("\r\n Received message from Network Server \r\n");
receive_message();
break;
case RX_TIMEOUT:
case RX_ERROR:
printf("\r\n Error in reception - Code = %d \r\n", event);
break;
case JOIN_FAILURE:
printf("\r\n OTAA Failed - Check Keys \r\n");
break;
case UPLINK_REQUIRED:
printf("\r\n Uplink required by NS \r\n");
if (MBED_CONF_LORA_DUTY_CYCLE_ON) {
send_message();
}
break;
default:
MBED_ASSERT("Unknown Event");
}
}
// EOF
UART
mbed_lib.json
C:\Users\Usuario\Mbed Programs\mbed-os-example-lorawan\mbed-os\connectivity\lorawan
Máscaras
Você pode configurar a pilha Mbed LoRaWAN para usar uma sub-banda de frequência específica (FSB), o que significa que você não precisa sondar todos os conjuntos de canais. "fsb-mask" em lorawan/mbed_lib.json é o parâmetro que você pode usar para dizer ao sistema qual FSB ou conjunto de FSBs usar.
Por default, o "fsb-mask" é configurado para "{0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x00FF}".
Isso significa que todos os canais estão ativos. Em outras palavras, 64 canais de 125 kHz e 8 canais de 500 kHz estão ativos. Se você deseja usar um FSB personalizado, você precisa definir uma máscara apropriada como o valor de "fsb-mask". Por exemplo, se você deseja usar o primeiro FSB, ou seja, os primeiros canais de 8 125 kHz (0-7) e o primeiro canal de 500 kHz:
"fsb-mask" = "{0x00FF, 0x0000, 0x0000, 0x0000, 0x0001}"
Da mesma forma, se você deseja usar o segundo FSB, ou seja, o segundo conjunto de canais de 8 125 kHz (8-15) e o 2º canal de 500 kHz:
"fsb-mask" = "{0xFF00, 0x0000, 0x0000, 0x0000, 0x0002}"
Você também pode combinar FSBs se sua estação base suportar mais de 8 canais. Por exemplo:
"fsb-mask" = "{0x00FF, 0x0000, 0x0000, 0xFF00, 0x0081}"
significa usar canais 0-7 (125 kHz) + canal 64 (500 KHz) e canais 56-63 (125 kHz) + canal 71 (500 kHz), significa usar canais 0-7 (125 kHz) + canal 64 (500 KHz) e canais 56-63 (125 kHz) + canal 71 (500 kHz).
Build
Será gerado um BIN na pasta
C:\Users\Usuario\Mbed Programs\mbed-os-example-lorawan\BUILD\NUCLEO_WL55JC\ARMC6
chamado
mbed-os-example-lorawan.bin
Utilize STM32 PROGRAMMER para gravar
Resultados
O terminal serial mostra uma saída semelhante a:
Pela USB Serial do KIT - após "conexão" à rede, perde Baud Rate
Problemas com versão ONLINE do MBED (Keill Studio)
- Remova o diretório
mbed-os
do seu projeto - Importe versão recente da biblioteca mbed-os (Add Mbed Library… →
URL:https://github.com/ARMmbed/mbed-os
→ clickNext >>
) - Configure a versão para mais recente (
mbed-os-6.16.0
→ clickFinish
) - Aguarde finalizar
Agora, você pode definir NUCLEO_WJ55JC ou STM32WL55C-DK.
Questões: Fórum Mbed-OS
Fontes:
Sobre a SMARTCORE
A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.Nosso portfólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.
Mais detalhes em www.smartcore.com.br
Nenhum comentário:
Postar um comentário