O objetivo deste BLOG é demonstrar como é possível programar o módulo WISOL LSM110A via ARDUINO e assim utilizá-lo como OPENCPU.
Este exemplo aguarda que o Payload a ser enviado via LoRaWAN seja enviado pela UART, seguindo a sequência
*@PAYLOAD
*#SLEEP
Após o RESET, você verá a configuração atual e pode mandar o comando AT para alterar em no máximo 2 segundos.
Comandos
AT+DEVEUI=00xxE115xx1Fxx0A
AT+APPKEY=A614D59963A0861EDF2702AE6F0E1AD6
AT+BAND=6
AT+MASK=0002
AT+CLASS=A
AT+CFM=1
LSM110A Starter KIT
Módulo
O LSM110A é um módulo de última geração que integra o STMicroelectronics STM32WL. É muito menos consumo atual para o dispositivo IoT para estender a vida útil da bateria. E, também suporta ambas as tecnologias – Sigfox e LoRa – com o próprio módulo LSM110A.
Altere radio_board_if.c para
int32_t RBI_ConfigRFSwitch(RBI_Switch_TypeDef Config)
{
switch (Config)
{
case RBI_SWITCH_OFF:
{
/* Turn off switch */
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_RESET);
break;
}
case RBI_SWITCH_RX:
{
/*Turns On in Rx Mode the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_RESET);
break;
}
case RBI_SWITCH_RFO_LP:
{
/*Turns On in Tx Low Power the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_SET);
break;
}
case RBI_SWITCH_RFO_HP:
{
/*Turns On in Tx High Power the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_SET);
break;
}
default:
break;
}
return 0;
}
Altere radio_board_if.h para
#define RF_SW_CTRL1_PIN GPIO_PIN_12
#define RF_SW_CTRL1_GPIO_PORT GPIOB
#define RF_SW_CTRL1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define RF_SW_CTRL1_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()
/* official version */
#define RF_SW_CTRL2_PIN GPIO_PIN_13
#define RF_SW_CTRL2_GPIO_PORT GPIOC
#define RF_SW_CTRL2_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define RF_SW_CTRL2_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()
Altere Placa para RAK3272-SIP, compile
Grave com o STM32 Programmer o BOOTLOADER no LSM110A
Assim, pode-se transferir o programa via Serial, através dos pinos PA2 e PA3 do LSM110A.
RAK3272-SiP_latest_final.hex
Transferindo
Executando
Segue código final
//#define LOG true
/***
* This example shows LoRaWan protocol joining the network in OTAA mode, class A, region EU868.
* Device will send uplink every 20 seconds.
***/
//uint16_t maskBuff = 0x0002;
uint8_t data_len = 0;
uint8_t flash_read[4] = {0};
uint32_t time_sleep = 0;
//#define OTAA_PERIOD (10000)
/*************************************
LoRaWAN band setting:
RAK_REGION_EU433
RAK_REGION_CN470
RAK_REGION_RU864
RAK_REGION_IN865
RAK_REGION_EU868
RAK_REGION_US915
RAK_REGION_AU915
RAK_REGION_KR920
RAK_REGION_AS923
*************************************/
#define OTAA_BAND (RAK_REGION_AU915)
#define OTAA_DEVEUI {0x00, 0xXX, 0xXX, 0x15, 0xXX, 0xXX, 0xXX, 0xXX}
#define OTAA_APPEUI {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99} //ignorado pelo CHIRPSTACK
#define OTAA_APPKEY {0xA6, 0x14, 0xD5, 0x99, 0x63, 0xA0, 0x86, 0x1E, 0xDF, 0x27, 0x02, 0xAE, 0x6F, 0x0E, 0x1A, 0xD6}
/** Packet buffer for sending */
char collected_data[64] = { 0 };
void recvCallback(SERVICE_LORA_RECEIVE_T * data)
{
if (data->BufferSize > 0) {
#ifdef LOG
Serial.println("Something received!");
#endif
for (int i = 0; i < data->BufferSize; i++) {
Serial.printf("%x", data->Buffer[i]);
}
Serial.print("\r\n");
}
}
void joinCallback(int32_t status)
{
Serial.printf("Join status: %d\r\n", status);
}
/*************************************
* enum type for LoRa Event
RAK_LORAMAC_STATUS_OK = 0,
RAK_LORAMAC_STATUS_ERROR,
RAK_LORAMAC_STATUS_TX_TIMEOUT,
RAK_LORAMAC_STATUS_RX1_TIMEOUT,
RAK_LORAMAC_STATUS_RX2_TIMEOUT,
RAK_LORAMAC_STATUS_RX1_ERROR,
RAK_LORAMAC_STATUS_RX2_ERROR,
RAK_LORAMAC_STATUS_JOIN_FAIL,
RAK_LORAMAC_STATUS_DOWNLINK_REPEATED,
RAK_LORAMAC_STATUS_TX_DR_PAYLOAD_SIZE_ERROR,
RAK_LORAMAC_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS,
RAK_LORAMAC_STATUS_ADDRESS_FAIL,
RAK_LORAMAC_STATUS_MIC_FAIL,
RAK_LORAMAC_STATUS_MULTICAST_FAIL,
RAK_LORAMAC_STATUS_BEACON_LOCKED,
RAK_LORAMAC_STATUS_BEACON_LOST,
RAK_LORAMAC_STATUS_BEACON_NOT_FOUND,
*************************************/
void sendCallback(int32_t status)
{
if (status == RAK_LORAMAC_STATUS_OK) {
#ifdef LOG
Serial.println("Successfully sent");
#endif
} else {
#ifdef LOG
Serial.println("Sending failed");
#endif
}
}
void setup()
{
uint8_t buff[16];
uint16_t maskBuff = 0x0002;
Serial.begin(115200, RAK_AT_MODE);
Serial.setTimeout(2000);
delay(2000); //APROVEITE AQUI PARA MANDAR COMANDO AT
//Sleep time...
if (api.system.flash.get(0, flash_read, 4))
{
time_sleep |= flash_read[0] << 0;
time_sleep |= flash_read[1] << 8;
time_sleep |= flash_read[2] << 16;
time_sleep |= flash_read[3] << 24;
}
else
{
Serial.println("Failed to read data from Flash");
}
Serial.println("------------------------------------------------------");
if(api.lorawan.appkey.get(buff, 16) == true) {
Serial.print("LoRaWan AppKey = 0x");
for(int i = 0; i < 16; i++) {
Serial.printf("%02X", buff[i]);
}
Serial.println("");
} else {
Serial.println("LoRaWan AppKey get fail");
}
if(api.lorawan.deui.get(buff, 8) == true) {
Serial.print("LoRaWan device EUI = 0x");
for(int i = 0; i < 8; i++) {
Serial.printf("%02X", buff[i]);
}
Serial.println("");
} else {
Serial.println("LoRaWan device EUI get fail");
}
Serial.printf("LoRa region = %d\r\n", api.lorawan.band.get());
switch(api.lorawan.deviceClass.get()) {
case 0:
Serial.println("Device is in Class A");
break;
case 1:
Serial.println("Device is in Class B");
break;
case 2:
Serial.println("Device is in Class C");
break;
}
Serial.printf("Get channel mask %s\r\n", api.lorawan.mask.get(&maskBuff) ? "Success" : "Fail");
Serial.printf("Channel mask = %04X\r\n", maskBuff);
Serial.printf("Packet is %s\n\r", api.lorawan.cfm.get() ? "CONFIRMED" : "UNCONFIRMED");
Serial.printf("Sleep interval %u", time_sleep);
Serial.println();
Serial.println("------------------------------------------------------");
if(api.lorawan.nwm.get() != 1)
{
Serial.printf("Set Node device work mode %s\r\n",
api.lorawan.nwm.set(1) ? "Success" : "Fail");
api.system.reboot();
}
// OTAA Device EUI MSB first
uint8_t node_device_eui[8] = OTAA_DEVEUI;
// OTAA Application EUI MSB first
uint8_t node_app_eui[8] = OTAA_APPEUI;
// OTAA Application Key MSB first
uint8_t node_app_key[16] = OTAA_APPKEY;
//if (!api.lorawan.appeui.set(node_app_eui, 8)) {
// Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");
// return;
//}
//if (!api.lorawan.appkey.set(node_app_key, 16)) {
// Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");
// return;
//}
//if (!api.lorawan.deui.set(node_device_eui, 8)) {
// Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");
// return;
//}
//if (!api.lorawan.band.set(OTAA_BAND)) {
// Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");
// return;
//}
//if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {
// Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");
// return;
//}
//Serial.printf("Set channel mask %s\r\n", api.lorawan.mask.set(&maskBuff) ? "Success" : "Fail");
if (!api.lorawan.njm.set(RAK_LORA_OTAA)) // Set the network join mode to OTAA
{
#ifdef LOG
Serial.printf("LoRaWan OTAA - set network join mode is incorrect! \r\n");
#endif
return;
}
if (!api.lorawan.join()) // Join to Gateway
{
#ifdef LOG
Serial.printf("LoRaWan OTAA - join fail! \r\n");
#endif
return;
}
/** Wait for Join success */
while (api.lorawan.njs.get() == 0) {
#ifdef LOG
Serial.print("Wait for LoRaWAN join...");
#endif
api.lorawan.join();
delay(10000);
}
if (!api.lorawan.adr.set(true)) {
#ifdef LOG
Serial.printf("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
#endif
return;
}
//if (!api.lorawan.rety.set(1)) {
// Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
// return;
//}
//NAO PEDIR CONFIRMACAO
//if (!api.lorawan.cfm.set(0)) {
// Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
// return;
//}
/** Check LoRaWan Status*/
Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF"); // Check Duty Cycle status
Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED"); // Check Confirm status
uint8_t assigned_dev_addr[4] = { 0 };
api.lorawan.daddr.get(assigned_dev_addr, 4);
Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]); // Check Device Address
Serial.printf("Uplink period is %ums\r\n", time_sleep);
Serial.println("");
api.lorawan.registerRecvCallback(recvCallback);
api.lorawan.registerJoinCallback(joinCallback);
api.lorawan.registerSendCallback(sendCallback);
}
void uplink_routine()
{
//Serial.println("++++++++++++++++++++++++++++");
//Serial.println(data_len);
//Serial.println("++++++++++++++++++++++++++++");
if(!(data_len==0))
{
/** Payload of Uplink */
#ifdef LOG
Serial.println("Data Packet:");
for (int i = 0; i < data_len; i++) {
Serial.printf("0x%02X ", collected_data[i]);
}
Serial.println("");
#endif
//Serial.printf("Set channel mask %s\r\n", api.lorawan.mask.set(&maskBuff) ? "Success" : "Fail");
/** Send the data package */
if (api.lorawan.send(data_len, (uint8_t *) & collected_data, 2, true, 1)) {
#ifdef LOG
Serial.println("Sending is requested");
#endif
} else {
#ifdef LOG
Serial.println("Sending failed");
#endif
}
}
data_len = 0;
}
uint8_t flash_value[4] = {0};
bool wr_result = false;
uint32_t data_to_save;
void loop()
{
static uint64_t last = 0;
static uint64_t elapsed;
String returnString = "";
if ((elapsed = millis() - last) > time_sleep) {
uplink_routine();
last = millis();
}
#ifdef LOG
Serial.printf("Try sleep %ums..", time_sleep);
#endif
api.system.sleep.all(time_sleep);
#ifdef LOG
Serial.println("Wakeup..");
#endif
returnString = Serial.readStringUntil('\r');
//Some payload received
if (!(returnString == ""))
{
//remove the first character, sometimes read it
if(returnString.indexOf("*") >= 0)
returnString.remove(0,1);
if(returnString.substring(0,1)=="@") {
//Remove @
returnString.remove(0,1)
//Convert to collected_data
data_len = returnString.length();
returnString.toCharArray(collected_data, data_len+1);
}
if(returnString.substring(0,1)=="#") {
//Remove #
returnString.remove(0,1);
data_to_save = returnString.toInt();
//save time sleep
flash_value[0] = (uint8_t)(data_to_save >> 0);
flash_value[1] = (uint8_t)(data_to_save >> 8);
flash_value[2] = (uint8_t)(data_to_save >> 16);
flash_value[3] = (uint8_t)(data_to_save >> 24);
wr_result = api.system.flash.set(0, flash_value, 4);
Serial.printf("Storing Sleep Interval ");
if(wr_result)
Serial.printf("OK");
else
Serial.printf("ERROR");
Serial.println();
}
//Serial.println(returnString);
//Serial.println(data_len);
//Serial.println("----------------------");
//for(int i=0; i<data_len; i++)
//Serial.println(collected_data[i]);
//Serial.println("----------------------");
}
/** Wait for Join success */
while (api.lorawan.njs.get() == 0) {
#ifdef LOG
Serial.print("Wait for LoRaWAN join...");
#endif
api.lorawan.join();
delay(10000);
}
}
Execução
Entre um caractere e outro, dar uma pausa de 1ms
Fontes:
Atenção
Dúvidas
FORUM
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