sexta-feira, 30 de junho de 2023

LSM110A FAZENDO COMUNICAÇÃO BIDIRECIONAL COM DADOS OBTIDOS PELA UART - VISUINO - RadioLib - MODBUS E ADC (PB4), DHT22, DISPLAY 7 SEGMENTOS CONTADOR (MOSI,CLK) e CONTROLE DE BRILHO DE LED VIA PWM

LSM110A FAZENDO COMUNICAÇÃO BIDIRECIONAL COM DADOS OBTIDOS PELA UART - VISUINO - RadioLib - MODBUS E ADC (PB4),  DHT22,  DISPLAY 7 SEGMENTOS CONTADOR (MOSI,CLK) e CONTROLE DE BRILHO DE LED VIA PWM

      

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.


Neste endereço Holding Register é armazenado o valor 0030H (48), via MODBUS SERIAL RS-232


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.

Você pode trocar Sigfox ou LoRa com ele para que você também possa reduzir o custo. É altamente otimizado para solução de IoT (Alto Consumo de Energia, Baixo Custo)

BREAKOUT para testes


Esquema Elétrico - últimas correções





PLACA MONTADA



CONEXÃO COM ST-LINK V2 E UART


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

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


BSP

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

MASTER



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


Formatted Text: Dado do Holding Register: %0 0000H e ADC: %1


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

MOSI PB5 e SCK PA5 (SPI)

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




Montagem


PWM NO PINO PB6 (controlado pelo Potenciômetro)


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:


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