LSM110A FAZENDO COMUNICAÇÃO BIDIRECIONAL COM DADOS OBTIDOS PELA UART - VISUINO - RadioLib - MODBUS E ADC (PB4), DHT22 e DISPLAY 7 SEGMENTOS CONTADOR (MOSI,CLK)
O objetivo deste BLOG é demonstrar como é possível programar o módulo WISOL LSM110A via VISUINO e assim utilizá-lo como OPENCPU.
Neste exemplo será realizado uma comunicação BIDIRECIONAL entre 2 LSM110A, um dos módulos será o MASTER e o outro o SLAVE (Listen).
O MASTER receberá quando "solicitado ao SLAVE" a leitura do Endereço Holding Register 0000 de um Modbus Server emulado a cada 5 segundos.
Também solicitará a Leitura do Conversor ADC no PINO PB4, lembrando que o Visuino retorna um valor de 0.0 a 1.0 para a leitura.
Temperatura do DHT22 será também enviada.
A solicitação será através de um texto JSON
{"Id":X,"R1":Y}
Onde X é o Id do SLAVE para o qual será solicitado a leitura MODBUS do Registro Y.
Neste caso, X=0 e Y=0
{"Id":0,"R1":0}
O SLAVE, ao receber este JSON, verifica se Id=0 e então faz a leitura do endereço Modbus Y e envia para o MASTER.
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.
MODBUS
Modbus é um Protocolo de comunicação de dados utilizado em sistemas de automação industrial. Criado originalmente no final da década de 1970, mais especificamente em 1979, pela fabricante de equipamentos Modicon. É um dos mais antigos e até hoje mais utilizados[2] protocolos em redes de Controladores lógicos programáveis (PLC) para aquisição de sinais(0 ou 1) de instrumentos e comandar atuadores. A Schneider Electric (atual controladora da Modicon) transferiu os direitos do protocolo para a Modbus Organization em 2004 e a utilização é livre de taxas de licenciamento.Por esta razão, e também por se adequar facilmente a diversos meios físicos, é utilizado em milhares de equipamentos existentes e é uma das soluções de rede mais baratas a serem utilizadas em Automação Industrial.
Originalmente implementado como um protocolo de nível de aplicação destinado a transferir dados por uma camada serial, o Modbus foi ampliado para incluir implementações em comunicações seriais, TCP/IP e UDP (user datagram protocol).
O Modbus é um protocolo de requisição-resposta que utiliza um relacionamento mestre-escravo. Em um relacionamento mestre-escravo, a comunicação sempre ocorre em pares — um dispositivo deve iniciar a requisição e então aguardar por uma resposta — e o dispositivo iniciador (o mestre) é responsável por iniciar cada interação. Tipicamente, o mestre é uma interface homem-máquina (IHM) ou sistema SCADA (Supervisory Control and Data Acquisition) e o escravo é um sensor, controlador lógico programável (CLP) ou controlador programável para automação (CPA). O conteúdo dessas requisições e respostas e as camadas de rede pelas quais essas mensagens são enviadas são definidos pelas diferentes camadas do protocolo.
Acesso aos dados no Modbus e o modelo de dados do Modbus
Os dados que podem ser acessados pelo Modbus são armazenados, de forma geral, em um dos quatro bancos de dados, ou faixas de endereço: coils, entradas discretas, registradores holding e registradores de entrada. Como ocorre com muitas partes da especificação, esses nomes podem variar, dependendo da indústria ou aplicação. Por exemplo, os registradores holding podem ser denominados registradores de saída, e os coils podem ser referidos como saídas digitais ou discretas. Esses bancos de dados definem o tipo e os direitos de acesso dos dados contidos. Os dispositivos escravo têm acesso direto a esses dados, que são hospedados localmente nos dispositivos. Os dados que podem ser acessados pelo Modbus são de forma geral um subconjunto da memória principal do dispositivo. Por outro lado, os mestres Modbus precisam solicitar acesso a esses dados, utilizando diversos códigos de função
Endereçamento do modelo de dados
A especificação define que cada bloco contém um espaço de endereçamento de até 65.536 (216) elementos. Com a definição da PDU, o Modbus define o endereço de cada elemento de dados na faixa de 0 a 65.535. Entretanto, cada elemento de dados é numerado de 1 a n, onde n tem o valor máximo de 65.536. Assim, o coil 1 está no endereço 0 do bloco de coils, enquanto que o registrador holding 54 está no endereço 53 da seção de memória reservada pelo escravo para os registradores holding.
Não é obrigatório implementar as faixas completas permitidas pela especificação no dispositivo. Por exemplo, pode ser escolhido para um dado dispositivo não implementar coils, entradas discretas ou registradores de entrada e, em vez disso, utilizar registradores holding de 150 a 175 e 200 a 225. Isso é perfeitamente aceitável; nesse caso, tentativas de acesso inválidas seriam tratadas por exceções.
Faixas de endereçamento de dados
Embora a especificação defina que diferentes tipos de dados devem existir em blocos diferentes e atribua uma faixa de endereços local para cada tipo, isso não implica que haverá necessariamente um esquema de endereçamento intuitivo ou facilmente compreensível para a documentação da memória que pode ser acessada pelo Modbus para um determinado dispositivo. Para simplificar a discussão sobre as posições dos blocos de memória, foi introduzido um esquema de numeração que inclui prefixos ao endereço dos dados em questão.
DHT22
O DHT22 é um sensor de temperatura e umidade que permite fazer leituras de temperaturas entre -40 a +80 graus Celsius e umidade entre 0 a 100%, sendo muito fácil de usar com Arduino, Raspberry e outros microcontroladores pois possui apenas 1 pino com saída digital.
ARDUINO
O que é Arduino? Se você sabe pouco sobre Arduino, por favor dê uma olhada abaixo:
Você conhece Arduino. Instale o IDE primeiro:
https://www.arduino.cc/en/Main/Software
Você conhece Arduino. Instale o IDE primeiro:
https://www.arduino.cc/en/Main/Software
LSM110A e Arduino (STM32DUINO)
LSM110A é baseado em STM32WL55. No Arduino STM32 existe este core.
Como instalar Arduino STM32? adicionar em Arquivo-->Preferências-->URLs adicionais
https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
2.4.0
RadioLib (instale)
O RadioLib permite que seus usuários integrem todos os tipos de diferentes módulos de comunicação sem fio, protocolos e até mesmo modos digitais em um único sistema consistente. Deseja adicionar uma interface Bluetooth à sua rede LoRa? Coisa certa! Você só quer ir realmente à moda antiga e brincar com teletipo de rádio, TV de varredura lenta ou até mesmo Hellschreiber usando nada além de um módulo de rádio barato? Por que não!
O RadioLib suporta nativamente o Arduino, mas também pode ser executado em ambientes não-Arduino! Veja esta página Wiki e exemplos/NonArduino.
O RadioLib foi originalmente criado como um driver para o RadioShield, mas pode ser usado para controlar quantos módulos sem fio diferentes você desejar - ou pelo menos quantos seu microcontrolador puder suportar!O RadioLib permite que seus usuários integrem todos os tipos de diferentes módulos de comunicação sem fio, protocolos e até mesmo modos digitais em um único sistema consistente. Deseja adicionar uma interface Bluetooth à sua rede LoRa? Coisa certa! Você só quer ir realmente à moda antiga e brincar com teletipo de rádio, TV de varredura lenta ou até mesmo Hellschreiber usando nada além de um módulo de rádio barato? Por que não!
O RadioLib suporta nativamente o Arduino, mas também pode ser executado em ambientes não-Arduino! Veja esta página Wiki e exemplos/NonArduino.
O RadioLib foi originalmente criado como um driver para o RadioShield, mas pode ser usado para controlar quantos módulos sem fio diferentes você desejar - ou pelo menos quantos seu microcontrolador puder suportar!
VISUINO
Visuino é o mais recente software inovador da Mitov Software. Um ambiente de programação visual que permite programar suas placas Arduino.
Os componentes encontrados no software Visuino representam seus componentes de hardware e você poderá facilmente criar e projetar seus programas arrastando e soltando. Nenhum equipamento ou hardware é necessário para executar o software no modo de design. Depois de concluir o projeto, você pode conectar o upload da placa Arduino e executá-lo.
Para aquelas pessoas que não são fortes em escrever código, projetar, compilar e criar programas Arduino nunca foi tão fácil! Por que perder tempo codificando quando todo o trabalho duro é feito para você? Você tem sua placa Arduino e um ótimo design de hardware, coloque-a em funcionamento em minutos, não em horas!
No Visuino, altere Mitov.Boards.STM32Duino.vcomp para
//---------------------------------------------------------------------------
[Name( 'Blue Pill (STM32F103)' )]
[ArduinoBoardCompileParams( 'STM32:stm32:GenF1' )]
[Category( TSTM32_F103_Category )]
+TArduino_STM32_Blue_Pill_Board : TArduino_STM32_Basic_Modules_Board
[AddItem( TArduinoSTM32HardwareSerial1 )]
[AddItem( TArduinoSTM32HardwareSerial0 )]
Serial
[AddItem( TArduinoI2C, 1 )]
I2CChannels
[AddItem( TArduinoSPI, 1 )]
SPIChannels
[ArduinoBoard_Add_DigitalAnalogChannel( 0, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA0 (BUT1) 3.3V', 'PA0' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 1, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA1 (BUT2) (WKUP) 3.3V', 'PA1' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 2, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMSerial0Channel, 'PA2 (TX0) 3.3V', 'PA2' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 3, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMSerial0Channel, 'PA3 (RX0) 3.3V', 'PA3' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 4, TArduinoCombinedAnalogDigitalPullDownOpenDrainChannel, 'PA4 (SPI1-NSS) 3.3V', 'PA4' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 5, TArduinoCombinedAnalogDigitalPullDownOpenDrainChannel, 'PA5 (SPI1-SCK) 3.3V', 'PA5' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 6, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMSPI0Channel, 'PA6(SPI1-MISO) 3.3V', 'PA6' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 7, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMSPI0Channel, 'PB5(SPI1-MOSI) 3.3V', 'PB5' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 8, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA7 3.3V', 'PA7' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 9, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA8 3.3V', 'PA8' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 10, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMSerial1Channel, 'PA9 (TX1) 3.3V', 'PA9' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 11, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMSerial1Channel, 'PA10 (RX1) 3.3V', 'PA10' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 12, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA11 3.3V', 'PA11' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 13, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA12 3.3V', 'PA12' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 14, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA13 (SWDIO) 3.3V', 'PA13' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 15, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA14 (SWCLK) 3.3V', 'PA14' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 16, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PA15 (LED3) 3.3V', 'PA15' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 17, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PB2 3.3V (ADC-IN4)', 'PB2' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 18, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PB3 3.3V', 'PB3' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 19, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PB4 3.3V', 'PB4' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 20, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, '3.3V', 'PB6' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 21, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, '3.3V', 'PB7' )]
[ArduinoBoard_Add_DigitalAnalogChannel( 22, TArduinoCombinedAnalogDigitalPullDownOpenDrainPWMChannel, 'PB8 3.3V', 'PB8' )]
Digital : TArduinoDigitalChannels
;
//---------------------------------------------------------------------------
Execute o Visuino faça o projeto abaixo
SLAVE
Configure as Seriais 1 e 2
Em Global Declarations de CustomCode (Uart1), coloque
HardwareSerial Serial1(USART1);
Em Global Implementations de CustomCode (RadioLib), coloque
void ReceivedPackage(String Txt)
{
Declarations::Instances::RadioLib.Received.Send(Txt);
}
void SendSNR(double Value)
{
Declarations::Instances::RadioLib.SNR.Send(Value);
}
void SendRSSI(double Value)
{
Declarations::Instances::RadioLib.RSSI.Send(Value);
}
void StatusTransmit(String Txt)
{
Declarations::Instances::RadioLib.Status.Send(Txt);
}
void CodeTransmit(byte Value)
{
Declarations::Instances::RadioLib.Code.Send(Value);
}
o qual enviará para o OUTPUT do CustomCode (RadioLib)
Em Global Declarations do CustomCode (RadioLib), coloque
// no need to configure pins, signals are routed to the radio internally
STM32WLx radio = new STM32WLx_Module();
// set RF switch configuration for Nucleo WL55JC1
// NOTE: other boards may be different!
static const uint32_t rfswitch_pins[] =
{PB12, PC13, PC5};
static const Module::RfSwitchMode_t rfswitch_table[] = {
{STM32WLx::MODE_IDLE, {LOW, LOW, LOW}},
{STM32WLx::MODE_RX, {HIGH, LOW, LOW}},
{STM32WLx::MODE_TX_LP, {HIGH, HIGH, HIGH}},
{STM32WLx::MODE_TX_HP, {HIGH, HIGH, HIGH}},
END_OF_MODE_TABLE,
};
// save transmission states between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate transmission or reception state
bool transmitFlag = false;
// flag to indicate that a packet was sent or received
volatile bool operationDone = false;
// this function is called when a complete packet
// is transmitted or received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
void setFlag(void) {
// we sent or received a packet, set the flag
operationDone = true;
}
Em Includes do CustomCode(RadioLib), coloque
#include <RadioLib.h>
Em OnExecute do CustomCode (RadioLib), coloque
// check if the previous operation finished
if(operationDone) {
// reset flag
operationDone = false;
if(transmitFlag) {
// the previous operation was transmission, listen for response
// print the result
if (transmissionState == RADIOLIB_ERR_NONE) {
// packet was successfully sent
//Serial.println(F("transmission finished!"));
//CustomCode Output Status
StatusTransmit(F("transmission finished!"));
} else {
Serial.print(F("failed, code "));
//CustomCode Output Status
StatusTransmit(F("transmission finished!"));
//CustomCode Output Code
CodeTransmit(transmissionState);
//Serial.println(transmissionState);
}
// listen for response
radio.startReceive();
transmitFlag = false;
} else {
// the previous operation was reception
// print data and send another packet
String str;
int state = radio.readData(str);
if (state == RADIOLIB_ERR_NONE) {
// packet was successfully received
//Serial.println(F("[LSM110A] Received packet!"));
// print data of the packet
//Serial.print(F("[LSM110A] Data:\t\t"));
//Serial.println(str);
//RadioLib CustomCode OUTPUT
ReceivedPackage(str);
// print RSSI (Received Signal Strength Indicator)
//Serial.print(F("[LSM110A] RSSI:\t\t"));
//Serial.print(radio.getRSSI());
//Serial.println(F(" dBm"));
//RadioLib CustomCode OUTPUT
SendRSSI(radio.getRSSI());
// print SNR (Signal-to-Noise Ratio)
//Serial.print(F("[LSM110A] SNR:\t\t"));
//Serial.print(radio.getSNR());
//Serial.println(F(" dB"));
//RadioLib CustomCode OUTPUT
SendSNR(radio.getSNR());
}
// wait a second before transmitting again
//delay(1000);
// send another one
//Serial.print(F("[SX1262] Sending another packet ... "));
//transmissionState = radio.startTransmit("Hello World!");
//transmitFlag = true;
}
}
Em On Init do CustomCode (RadioLib), coloque
// set RF switch control configuration
// this has to be done prior to calling begin()
radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
// initialize STM32WL with default settings, except frequency
//CustomCode Output Status
StatusTransmit(F("[STM32WL] Initializing ... "));
//Serial.print(F("[STM32WL] Initializing ... "));
int state = radio.begin(926.6, 125.0, 10, 5, 0x34, 2, 20);
if (state == RADIOLIB_ERR_NONE) {
//CustomCode Output Status
StatusTransmit(F("success!"));
//Serial.println(F("success!"));
} else {
//CustomCode Output Status
StatusTransmit(F("failed, code "));
//Serial.print(F("failed, code "));
//CustomCode Output Code
CodeTransmit(state);
//Serial.println(state);
while (true);
}
// set appropriate TCXO voltage for Nucleo WL55JC1
state = radio.setTCXO(1.7);
if (state == RADIOLIB_ERR_NONE) {
//CustomCode Output Status
StatusTransmit(F("success!"));
//Serial.println(F("success!"));
} else {
//CustomCode Output Code
StatusTransmit(F("failed, code "));
//CustomCode Output Code
CodeTransmit(state);
//Serial.println(state);
while (true);
}
// set the function that will be called
// when new packet is received
radio.setDio1Action(setFlag);
//#define INITIATING_NODE 1
#if defined(INITIATING_NODE)
// send the first packet on this node
//CustomCode Output Status
StatusTransmit(F("[SX1262] Sending first packet ... "));
//Serial.print(F("[SX1262] Sending first packet ... "));
transmissionState = radio.startTransmit("Smartcore");
transmitFlag = true;
#else
// start listening for LoRa packets on this node
//CustomCode Output Status
StatusTransmit(F("[SX1262] Starting to listen ... "));
//Serial.print(F("[SX1262] Starting to listen ... "));
state = radio.startReceive();
if (state == RADIOLIB_ERR_NONE) {
//CustomCode Output Status
StatusTransmit(F("success!"));
//Serial.println(F("success!"));
} else {
//CustomCode Output Code
StatusTransmit(F("failed, code "));
//Serial.print(F("failed, code "));
//CustomCode Output Code
CodeTransmit(state);
//Serial.println(state);
while (true);
}
#endif
Em Input On Data do CustomCode (RadioLib), coloque
// send another one
//Serial.print(F("[SX1262] Sending another packet ... "));
transmissionState = radio.startTransmit(AValue);
transmitFlag = true;
Configure Modbus Client - Serial 1 - Ascii Format
SLAVE enviando dados para o MASTER
Extraindo Id e Registrador Modbus do Pacote JSON
Comparando se o Id = 0 e então enviando pacote para o Master
Lendo ADC (PB4) via Potenciômetro
Lendo DHT22 (PA0)
Display de 7 Segmentos CONTADOR
Altere Placa para STM32WL series e compile
Transferindo (utilizado o STM32CubeProgrammer)
Via STLINK V2
Configurando ambiente para testes
Resultado da execução (colocando via Potenciômetro no ADC aproximadamente 1.20V e 0AH no endereço 0000H do emulador do MODBUS) e lida a temperatura do DHT22
ADC
WEAK const PinMap PinMap_ADC[] = {
{PA_10, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 6, 0)}, // ADC_IN6
{PA_11, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 7, 0)}, // ADC_IN7
{PA_12, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 8, 0)}, // ADC_IN8
{PA_13, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 9, 0)}, // ADC_IN9
{PA_14, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC_IN10
{PA_15, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC_IN11
{PB_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 5, 0)}, // ADC_IN5
{PB_2, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 4, 0)}, // ADC_IN4
{PB_3, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 2, 0)}, // ADC_IN2
{PB_4, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC_IN3
{PB_13, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 0, 0)}, // ADC_IN0
{PB_14, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 1, 0)}, // ADC_IN1
{NC, NP, 0}
};
Fontes:
PeripheralPins.c
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
Nenhum comentário:
Postar um comentário