segunda-feira, 9 de maio de 2022

UTILIZANDO LOM204A02 COMO OPENCPU - BME280

 UTILIZANDO LOM204A02 COMO OPENCPU


O objetivo deste BLOG é demonstrar como é possível interagir com o módulo LOM204A02 via API mode ou seja, com acesso aos comandos via API e utilizá-lo como OPENCPU.


Neste exemplo, utilizaremos o LOM204A2 (EVL20XA R1) para requisitar dados do sensor BME280 via barramento I2C.
A programação será via KEIL C, o mesmo utilizado para compilar o firmware dos comandos CLI.

Neste exemplo, será transmitido via LoRa (P2P), pois o objetivo é apenas ler o BME280.

A LIB utilizada foi


BME280
BME280

- O Sensor de Pressão BME280 é um exclusivo modelo capaz de realizar a medição de pressão atmosférica, umidade e temperatura, também conhecido como barômetro é um módulo digital de alta capacidade e resolução, utilizado nas mais diversas aplicações junto a microcontroladores, entre eles, o Arduino.
- Utilizado em projetos de estações meteorológicas e aperfeiçoamento de navegação GPS, ele apresenta grande potencial e mostra ser um produto de grande auxílio para projetistas que procuram um exclusivo produto capaz de executar as três funcionalidades principais sem ocupar muito espaço.
- Através de seu padrão de conexão por I2C, o Sensor de Pressão BME280 aumenta a sua praticidade de utilização, além de contribuir na maior precisão da obtenção de resultados.
- Desenvolvido com base no sensor Bosh ME280, o Sensor possui design simplificado com pequenas dimensõe que tornam este pequeno módulo um produto de fácil adaptação nos mais diversificados projetos, além de contar com 2 exclusivos furos para melhorar a fixação do mesmo junto aos mais diversificados projetos.

CARACTERÍSTICAS:

- Sensor de Pressão BME280;
- Sensor de Umidade;
- Sensor de Temperatura;
- Produto pequeno de fácil utilização;
- Sistema de comunicação I2C;
- Compatível com diversos modelos de microcontroladores;
- Acompanha barra de pinos 180º;

ESPECIFICAÇÕES:

- Modelo:BME280;
- Tensão de operação: 1,8 a 3,6VDC;
- Faixa de Umidade: 0 a 100%;
- Faixa de Temperatura: -40 a 85ºC;
- Faixa de Pressão: 300 a 1100hPa;
- Precisão da umidade: 0,008%;
- Precisão da temperatura: 0,01ºC;
- Precisão da pressão: +/- 1Pa;
- Comunicação: I2C (até 3,4MHz) e SPI (até 10MHz);
- Dimensões (CxLxA): 15,5x11,5x2,5mm;
- Peso: 1,5g.
A ligação foi realizada desta forma


ALGUMAS MUDANÇAS REALIZADAS PARA FUNCIONAR I2C

1) EM stm32l0xx_hal_conf.h,  descomentar

#define HAL_I2C_MODULE_ENABLED


2) EM stm32l0xx_hal_msp.h, incluir

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_I2C1;


3) EM main.c configurar pinos  SDA e SCL (HAL_I2C_MspInit)

#define MAIN_C_
#include <stddef.h> #include <string.h> #include "stm32l0xx_hal.h" #include <math.h> #include "board.h" #include "Utilities.h" #include "misc.h" #include "process.h" #include "timer.h" #include "init.h" #include "timer.h" #include "main.h" #include "WISOL_API.h" #include "BMP280.h" extern uint8_t I2C_Read_Register(uint8_t device_adr, uint8_t internal_adr); extern void I2C_Write_Register(uint8_t device_adr, uint8_t internal_adr, uint8_t data); extern I2C_HandleTypeDef hi2c1; //--------------------------------------------------------------------------------------------------------- // Example // This example shows how to use the P2P function to send a message or command // for LIB ver 1.01 //--------------------------------------------------------------------------------------------------------- extern uint8_t ProductState; extern uint8_t Uart_Rx_buff[272]; char string[200]; /** * @brief I2C MSP Initialization * This function configures the hardware resources used in this example * @param hi2c: I2C handle pointer * @retval None */ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(hi2c->Instance==I2C1) { /* USER CODE BEGIN I2C1_MspInit 0 */ /* USER CODE END I2C1_MspInit 0 */ __HAL_RCC_GPIOB_CLK_ENABLE(); /**I2C1 GPIO Configuration PB9 ------> I2C1_SDA PB8 ------> I2C1_SCL */ GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* Peripheral clock enable */ __HAL_RCC_I2C1_CLK_ENABLE(); /* USER CODE BEGIN I2C1_MspInit 1 */ /* USER CODE END I2C1_MspInit 1 */ } } /** * @brief I2C1 Initialization Function * @param None * @retval None */ static void MX_I2C1_Init(void) { /* USER CODE BEGIN I2C1_Init 0 */ /* USER CODE END I2C1_Init 0 */ /* USER CODE BEGIN I2C1_Init 1 */ /* USER CODE END I2C1_Init 1 */ hi2c1.Instance = I2C1; hi2c1.Init.Timing = 0x40011A22; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { //Error_Handler(); } /** Configure Analogue filter */ if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) { //Error_Handler(); } /** Configure Digital filter */ if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) { //Error_Handler(); } /* USER CODE BEGIN I2C1_Init 2 */ /* USER CODE END I2C1_Init 2 */ } /* USER CODE BEGIN PFP */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE END PFP */ /* USER CODE BEGIN 0 */ uint8_t string_compare(char array1[], char array2[], uint16_t lenght) { uint8_t comVAR=0, i; for(i=0;i<lenght;i++) { if(array1[i]==array2[i]) comVAR++; else comVAR=0; } if (comVAR==lenght) return 1; else return 0; } // reverses a string 'str' of length 'len' void reverse(char *str, int len) { int i=0, j=len-1, temp; while (i<j) { temp = str[i]; str[i] = str[j]; str[j] = temp; i++; j--; } } // Converts a given integer x to string str[]. d is the number // of digits required in output. If d is more than the number // of digits in x, then 0s are added at the beginning. int intToStr(int x, char str[], int d) { int i = 0; while (x) { str[i++] = (x%10) + '0'; x = x/10; } // If number of digits required is more, then // add 0s at the beginning while (i < d) str[i++] = '0'; reverse(str, i); str[i] = '\0'; return i; } // Converts a floating point number to string. void ftoa(float n, char *res, int afterpoint) { unsigned char minus_flag = 0; if(n<0) { minus_flag = 1; n = -n; } // Extract integer part int ipart = (int)n; // Extract floating part float fpart = n - (float)ipart; // convert integer part to string int i = intToStr(ipart, res, 0); // check for display option after point if (afterpoint != 0) { res[i] = '.'; // add dot // Get the value of fraction part upto given no. // of points after dot. The third parameter is needed // to handle cases like 233.007 fpart = fpart * pow(10, afterpoint); intToStr((int)fpart, res + i + 1, afterpoint); } char string[30]; if(minus_flag==1) { memset(string, 0, 30); string[0]='-'; if(n<1.0f) { string[1]='0'; strcpy(&string[2], res); }else strcpy(&string[1], res); memset(res, 0, strlen(res)); strcpy(res, string); }else if(n<1.0f) { string[0]='0'; strcpy(&string[1], res); memset(res, 0, strlen(res)); strcpy(res, string); } } int main(void) { Start_Init(); MX_I2C1_Init(); BMP280_init(); BMP280_calc_values(); init_height=altitude; do { BMP280_calc_values(); memset(&string, 0, strlen(string)); strcat(string, "Temperature: "); ftoa(temperature, &string[strlen(string)], 3); strcat(string, " C\n"); strcat(string, "Pressure: "); ftoa(pressure, &string[strlen(string)], 3); strcat(string, " Pa\n"); strcat(string, "Altitude: "); ftoa(altitude, &string[strlen(string)], 3); strcat(string, " m\n"); strcat(string, "Relative altitude: "); ftoa(altitude-init_height, &string[strlen(string)], 3); strcat(string, " m\n\n\n"); PRINTF("%s",string); HAL_Delay(1000); }while(true); } void Start_Init(void) { HW_SystemClock_Config(); StartNVInit(); BoardInitPeriph( ); BoardInitMcu( ); Var_Init(); sub_process_init(); // set receive mode for uart #ifdef DEBUG_GPIO Timer_1ms_Start(IDLE_MODE_TIME_OUT,200,0xff,BIT0_fn); // When a module enters sleep, it no longer works. #endif TimerInit( &TxNext, Txnext_fn ); // Do not modify /* #if defined (USE_BAND_920) #ifndef OLD_CLI_COMPATIBILITY_MODE TimerInit( &Rest_send, restrict_send); #endif #endif */ nvm_init(); // To read the configuration saved in EEPROM. Clr_BIT2(); LDO_on(); } void Restart_Init(void) { BoardInitPeriph( ); BoardInitMcu( ); Var_Init(); sub_process_init(); // set receive mode for uart #ifdef DEBUG_GPIO Timer_1ms_Start(IDLE_MODE_TIME_OUT,200,0xff,BIT0_fn); // When a module enters sleep, it no longer works. #endif TimerInit( &TxNext, Txnext_fn ); // Do not modify /* #if defined (USE_BAND_920) #ifndef OLD_CLI_COMPATIBILITY_MODE TimerInit( &Rest_send, restrict_send); #endif #endif */ nvm_init(); // To read the configuration saved in EEPROM. Clr_BIT2(); LDO_on(); }
4) Compilando


5) Fazendo o UPLOAD


Melhorias do projeto acima

REDUÇÃO DA VELOCIDADE DE FREQUÊNCIA DO I²C

MELHORIA DO TEMPO DE SUBIDA E DESCIDA DO CLOCK DO I²C
 
REDUÇÃO DO CLOCK DE PCLK1 (I²C)
REDUÇÃO DO CLOCK PLL (PLLCLK)

PRINT DA TELA DE CONFIGURAÇÃO DE CLOCK DO STM CUBE MX

RESULTADO FINAL DO CLOCK (PINO SCL) MEDIDO COM O OSCILOSCÓPIO


Projeto


Fontes:


Datasheets

SCH_EVL20xA_R1_170630.pdf
Datasheet_LOM204A_V0.1_20190715.pdf

Dúvidas

suporte@smartcore.com.br


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