├── Alfabeto Stranger Things └── alfabeto_stranger_things.pdf ├── README.md └── Exemplos ├── Cap3 └── hello_world_modulo.ino ├── Cap4 ├── lora_ponto_a_ponto_emissor.ino └── lora_ponto_a_ponto_receptor.ino ├── Cap7 ├── turbidez_agua_receptor.ino └── turbidez_agua_emissor.ino ├── Cap5 ├── leitura_temp_umid_mqtt_lora_receptor.ino ├── leitura_temp_umid_local.ino ├── leitura_temp_umid_mqtt.ino └── leitura_temp_umid_mqtt_lora_emissor.ino ├── Cap8 └── alfabeto_stranger_things_publicacao.ino └── Cap6 ├── rover_esp32_reles.ino └── rover_esp32_L298N.ino /Alfabeto Stranger Things/alfabeto_stranger_things.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phfbertoleti/livro_projetos_esp32_LoRa/HEAD/Alfabeto Stranger Things/alfabeto_stranger_things.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Repositório oficial do livro "Projetos com ESP32 e LoRa" 2 | 3 | Repositório oficial dos exemplos e demais documentos do livro "Projetos com ESP32 e LoRa", do autor Pedro Bertoleti. 4 | 5 | Neste repositório, você encontrará: 6 | 7 | * Todos os códigos-fonte dos exemplos abordados no livro 8 | * Alfabeto Stranger Things (para utilizar no projeto abordado no capítulo 8) 9 | 10 | **Importante:** 11 | Todos os exemplos que envolvem uso de LoRa utilizam esta biblioteca para comunicação com o chip LoRa (SX1276): https://github.com/sandeepmistry/arduino-LoRa 12 | -------------------------------------------------------------------------------- /Exemplos/Cap3/hello_world_modulo.ino: -------------------------------------------------------------------------------- 1 | /* Includes para header files das biliotecas do OLED */ 2 | #include 3 | #include 4 | #include 5 | 6 | /* Endereço I2C do display */ 7 | #define OLED_ADDR 0x3c 8 | 9 | /* distancia, em pixels, de cada linha em relacao ao topo do display */ 10 | #define OLED_LINE1 0 11 | #define OLED_LINE2 10 12 | #define OLED_LINE3 20 13 | #define OLED_LINE4 30 14 | #define OLED_LINE5 40 15 | 16 | /* Configuração da resolucao do display (este modulo possui display 128x64) */ 17 | #define SCREEN_WIDTH 128 18 | #define SCREEN_HEIGHT 64 19 | 20 | /* Objeto do display */ 21 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 16); 22 | 23 | /* Variaveis */ 24 | int contador = 0; 25 | 26 | /* Funcao setup */ 27 | void setup() 28 | { 29 | /* inicializa display OLED */ 30 | Wire.begin(4, 15); 31 | 32 | if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) 33 | Serial.println("Display OLED: falha ao inicializar"); 34 | else 35 | { 36 | Serial.println("Display OLED: inicializacao ok"); 37 | 38 | /* Limpa display e configura tamanho de fonte */ 39 | display.clearDisplay(); 40 | display.setTextSize(1); 41 | display.setTextColor(WHITE); 42 | } 43 | } 44 | 45 | /* Programa principal */ 46 | void loop() 47 | { 48 | display.clearDisplay(); 49 | 50 | display.setCursor(0, OLED_LINE1); 51 | display.println("Ola!"); 52 | 53 | display.setCursor(0, OLED_LINE2); 54 | display.println("Programa:"); 55 | 56 | display.setCursor(0, OLED_LINE3); 57 | display.println("teste oled"); 58 | 59 | display.setCursor(0, OLED_LINE4); 60 | display.print("Tempo ligado: "); 61 | 62 | display.setCursor(0, OLED_LINE5); 63 | display.print(contador); 64 | display.println("s"); 65 | 66 | display.display(); 67 | 68 | contador++; 69 | delay(1000); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /Exemplos/Cap4/lora_ponto_a_ponto_emissor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Projeto: emissor - comunicação LoRa ponto-a-ponto 3 | * Autor: Pedro Bertoleti 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | /* Definicoes para comunicação com radio LoRa */ 10 | #define SCK_LORA 5 11 | #define MISO_LORA 19 12 | #define MOSI_LORA 27 13 | #define RESET_PIN_LORA 14 14 | #define SS_PIN_LORA 18 15 | 16 | #define HIGH_GAIN_LORA 20 /* dBm */ 17 | #define BAND 915E6 /* 915MHz de frequencia */ 18 | 19 | /* Definicoes gerais */ 20 | #define DEBUG_SERIAL_BAUDRATE 115200 21 | 22 | /* Variaveis globais */ 23 | long informacao_a_ser_enviada = 0; 24 | 25 | /* Local prototypes */ 26 | bool init_comunicacao_lora(void); 27 | 28 | /* Funcao: inicia comunicação com chip LoRa 29 | * Parametros: nenhum 30 | * Retorno: true: comunicacao ok 31 | * false: falha na comunicacao 32 | */ 33 | bool init_comunicacao_lora(void) 34 | { 35 | bool status_init = false; 36 | Serial.println("[LoRa Sender] Tentando iniciar comunicacao com o radio LoRa..."); 37 | SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA); 38 | LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN); 39 | 40 | if (!LoRa.begin(BAND)) 41 | { 42 | Serial.println("[LoRa Sender] Comunicacao com o radio LoRa falhou. Nova tentativa em 1 segundo..."); 43 | delay(1000); 44 | status_init = false; 45 | } 46 | else 47 | { 48 | /* Configura o ganho do receptor LoRa para 20dBm, o maior ganho possível (visando maior alcance possível) */ 49 | LoRa.setTxPower(HIGH_GAIN_LORA); 50 | Serial.println("[LoRa Sender] Comunicacao com o radio LoRa ok"); 51 | status_init = true; 52 | } 53 | 54 | return status_init; 55 | } 56 | 57 | /* Funcao de setup */ 58 | void setup() 59 | { 60 | Serial.begin(DEBUG_SERIAL_BAUDRATE); 61 | while (!Serial); 62 | 63 | /* Tenta, até obter sucesso, comunicacao com o chip LoRa */ 64 | while(init_comunicacao_lora() == false); 65 | } 66 | 67 | /* Programa principal */ 68 | void loop() 69 | { 70 | /* Envia a informação */ 71 | LoRa.beginPacket(); 72 | LoRa.write((unsigned char *)&informacao_a_ser_enviada, sizeof(informacao_a_ser_enviada)); 73 | LoRa.endPacket(); 74 | 75 | /* Incrementa a informação para o próximo envio e aguarda 76 | 1 segundo até enviar a próxima informação */ 77 | informacao_a_ser_enviada++; 78 | delay(1000); 79 | 80 | } 81 | -------------------------------------------------------------------------------- /Exemplos/Cap7/turbidez_agua_receptor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Projeto: receptor - medição de turbudez da agua via LoRa 3 | * Autor: Pedro Bertoleti 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* Definicoes para comunicação com radio LoRa */ 13 | #define SCK_LORA 5 14 | #define MISO_LORA 19 15 | #define MOSI_LORA 27 16 | #define RESET_PIN_LORA 14 17 | #define SS_PIN_LORA 18 18 | #define HIGH_GAIN_LORA 20 /* dBm */ 19 | #define BAND 915E6 /* 915MHz de frequencia */ 20 | 21 | /* Definicoes do OLED */ 22 | #define OLED_SDA_PIN 4 23 | #define OLED_SCL_PIN 15 24 | #define SCREEN_WIDTH 128 25 | #define SCREEN_HEIGHT 64 26 | #define OLED_ADDR 0x3C 27 | #define OLED_RESET 16 28 | 29 | /* Offset de linhas no display OLED */ 30 | #define OLED_LINE1 0 31 | #define OLED_LINE2 10 32 | #define OLED_LINE3 20 33 | #define OLED_LINE4 30 34 | #define OLED_LINE5 40 35 | #define OLED_LINE6 50 36 | 37 | /* Definicoes gerais */ 38 | #define DEBUG_SERIAL_BAUDRATE 115200 39 | 40 | /* Variaveis e objetos globais */ 41 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 42 | 43 | /* Local prototypes */ 44 | void display_init(void); 45 | bool init_comunicacao_lora(void); 46 | 47 | /* Funcao: inicializa comunicacao com o display OLED 48 | * Parametros: nenhnum 49 | * Retorno: nenhnum 50 | */ 51 | void display_init(void) 52 | { 53 | if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) 54 | { 55 | Serial.println("[Modulo receptor] Falha ao inicializar comunicacao com OLED"); 56 | } 57 | else 58 | { 59 | Serial.println("[Modulo receptor] Comunicacao com OLED inicializada com sucesso"); 60 | 61 | /* Limpa display e configura tamanho de fonte */ 62 | display.clearDisplay(); 63 | display.setTextSize(1); 64 | display.setTextColor(WHITE); 65 | } 66 | } 67 | 68 | /* Funcao: inicia comunicação com chip LoRa 69 | * Parametros: nenhum 70 | * Retorno: true: comunicacao ok 71 | * false: falha na comunicacao 72 | */ 73 | bool init_comunicacao_lora(void) 74 | { 75 | bool status_init = false; 76 | 77 | Serial.println("[Modulo receptor] Tentando iniciar comunicacao com o radio LoRa..."); 78 | SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA); 79 | LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN); 80 | 81 | if (!LoRa.begin(BAND)) 82 | { 83 | Serial.println("[Modulo receptor] Comunicacao com o radio LoRa falhou. Nova tentativa em 1 segundo..."); 84 | delay(1000); 85 | status_init = false; 86 | } 87 | else 88 | { 89 | /* Configura o ganho do receptor LoRa para 20dBm, o maior ganho possível (visando maior alcance possível) */ 90 | LoRa.setTxPower(HIGH_GAIN_LORA); 91 | Serial.println("[Modulo receptor] Comunicacao com o radio LoRa ok"); 92 | status_init = true; 93 | } 94 | return status_init; 95 | } 96 | 97 | /* Funcao de setup */ 98 | void setup() 99 | { 100 | /* Configuracao da I²C para o display OLED */ 101 | Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN); 102 | 103 | /* Display init */ 104 | display_init(); 105 | 106 | /* Print message telling to wait */ 107 | display.clearDisplay(); 108 | display.setCursor(0, OLED_LINE1); 109 | display.print("Aguarde..."); 110 | display.display(); 111 | 112 | Serial.begin(DEBUG_SERIAL_BAUDRATE); 113 | 114 | while (!Serial); 115 | 116 | /* Tenta, até obter sucesso, comunicacao com o chip LoRa */ 117 | while(init_comunicacao_lora() == false); 118 | } 119 | 120 | /* Programa principal */ 121 | void loop() 122 | { 123 | char byte_recebido; 124 | int packet_size = 0; 125 | float turbidez_recebida = 0; 126 | char str_turbidez_agua[30] = {0}; 127 | char * ptTurbidezRecebida = NULL; 128 | 129 | /* Verifica se chegou alguma informação do tamanho esperado */ 130 | packet_size = LoRa.parsePacket(); 131 | if (packet_size == sizeof(float)) 132 | { 133 | Serial.print("[Modulo receptor] Há dados a serem lidos"); 134 | 135 | /* Recebe turbidez enviada */ 136 | ptTurbidezRecebida = (char *)&turbidez_recebida; 137 | 138 | while (LoRa.available()) 139 | { 140 | byte_recebido = (char)LoRa.read(); 141 | *ptTurbidezRecebida = byte_recebido; 142 | ptTurbidezRecebida++; 143 | } 144 | 145 | /* Cria uma string do valor da turbidez da água lida (com 2 casas decimais) */ 146 | sprintf(str_turbidez_agua, "%.2fNTU", turbidez_recebida); 147 | 148 | /* Exibe a turbidez da agua recebida via LoRa no display OLED */ 149 | display.clearDisplay(); 150 | display.setCursor(0, OLED_LINE1); 151 | display.println("Turbidez da agua:"); 152 | display.setCursor(0, OLED_LINE2); 153 | display.print(str_turbidez_agua); 154 | display.display(); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /Exemplos/Cap4/lora_ponto_a_ponto_receptor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Projeto: receptor - comunicação LoRa ponto-a-ponto 3 | * Autor: Pedro Bertoleti 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /* Definicoes para comunicação com radio LoRa */ 12 | #define SCK_LORA 5 13 | #define MISO_LORA 19 14 | #define MOSI_LORA 27 15 | #define RESET_PIN_LORA 14 16 | #define SS_PIN_LORA 18 17 | 18 | #define HIGH_GAIN_LORA 20 /* dBm */ 19 | #define BAND 915E6 /* 915MHz de frequencia */ 20 | 21 | /* Definicoes do OLED */ 22 | #define OLED_SDA_PIN 4 23 | #define OLED_SCL_PIN 15 24 | #define SCREEN_WIDTH 128 25 | #define SCREEN_HEIGHT 64 26 | #define OLED_ADDR 0x3C 27 | #define OLED_RESET 16 28 | 29 | /* Offset de linhas no display OLED */ 30 | #define OLED_LINE1 0 31 | #define OLED_LINE2 10 32 | #define OLED_LINE3 20 33 | #define OLED_LINE4 30 34 | #define OLED_LINE5 40 35 | #define OLED_LINE6 50 36 | 37 | /* Definicoes gerais */ 38 | #define DEBUG_SERIAL_BAUDRATE 115200 39 | 40 | /* Variaveis e objetos globais */ 41 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 42 | 43 | /* Local prototypes */ 44 | void display_init(void); 45 | bool init_comunicacao_lora(void); 46 | 47 | /* Funcao: inicializa comunicacao com o display OLED 48 | * Parametros: nenhnum 49 | * Retorno: nenhnum 50 | */ 51 | void display_init(void) 52 | { 53 | if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) 54 | { 55 | Serial.println("[LoRa Receiver] Falha ao inicializar comunicacao com OLED"); 56 | } 57 | else 58 | { 59 | Serial.println("[LoRa Receiver] Comunicacao com OLED inicializada com sucesso"); 60 | 61 | /* Limpa display e configura tamanho de fonte */ 62 | display.clearDisplay(); 63 | display.setTextSize(1); 64 | display.setTextColor(WHITE); 65 | } 66 | } 67 | 68 | /* Funcao: inicia comunicação com chip LoRa 69 | * Parametros: nenhum 70 | * Retorno: true: comunicacao ok 71 | * false: falha na comunicacao 72 | */ 73 | bool init_comunicacao_lora(void) 74 | { 75 | bool status_init = false; 76 | Serial.println("[LoRa Receiver] Tentando iniciar comunicacao com o radio LoRa..."); 77 | SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA); 78 | LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN); 79 | 80 | if (!LoRa.begin(BAND)) 81 | { 82 | Serial.println("[LoRa Receiver] Comunicacao com o radio LoRa falhou. Nova tentativa em 1 segundo..."); 83 | delay(1000); 84 | status_init = false; 85 | } 86 | else 87 | { 88 | /* Configura o ganho do receptor LoRa para 20dBm, o maior ganho possível (visando maior alcance possível) */ 89 | LoRa.setTxPower(HIGH_GAIN_LORA); 90 | Serial.println("[LoRa Receiver] Comunicacao com o radio LoRa ok"); 91 | status_init = true; 92 | } 93 | 94 | return status_init; 95 | } 96 | 97 | /* Funcao de setup */ 98 | void setup() 99 | { 100 | /* Configuracao da I²C para o display OLED */ 101 | Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN); 102 | 103 | /* Display init */ 104 | display_init(); 105 | 106 | /* Print message telling to wait */ 107 | display.clearDisplay(); 108 | display.setCursor(0, OLED_LINE1); 109 | display.print("Aguarde..."); 110 | display.display(); 111 | 112 | Serial.begin(DEBUG_SERIAL_BAUDRATE); 113 | while (!Serial); 114 | 115 | /* Tenta, até obter sucesso, comunicacao com o chip LoRa */ 116 | while(init_comunicacao_lora() == false); 117 | } 118 | 119 | /* Programa principal */ 120 | void loop() 121 | { 122 | char byte_recebido; 123 | int packet_size = 0; 124 | int lora_rssi = 0; 125 | long informacao_recebida = 0; 126 | char * ptInformaraoRecebida = NULL; 127 | 128 | /* Verifica se chegou alguma informação do tamanho esperado */ 129 | packet_size = LoRa.parsePacket(); 130 | 131 | if (packet_size == sizeof(informacao_recebida)) 132 | { 133 | Serial.print("[LoRa Receiver] Há dados a serem lidos"); 134 | 135 | /* Recebe os dados conforme protocolo */ 136 | ptInformaraoRecebida = (char *)&informacao_recebida; 137 | while (LoRa.available()) 138 | { 139 | byte_recebido = (char)LoRa.read(); 140 | *ptInformaraoRecebida = byte_recebido; 141 | ptInformaraoRecebida++; 142 | } 143 | 144 | /* Escreve RSSI de recepção e informação recebida */ 145 | lora_rssi = LoRa.packetRssi(); 146 | display.clearDisplay(); 147 | display.setCursor(0, OLED_LINE1); 148 | display.print("RSSI: "); 149 | display.println(lora_rssi); 150 | display.setCursor(0, OLED_LINE2); 151 | display.print("Informacao: "); 152 | display.setCursor(0, OLED_LINE3); 153 | display.println(informacao_recebida); 154 | display.display(); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /Exemplos/Cap5/leitura_temp_umid_mqtt_lora_receptor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Projeto: receptor - medição local, via LoRa e via mqtt de temperatura e umidade 3 | * Autor: Pedro Bertoleti 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | /* Definicoes para comunicação com radio LoRa */ 12 | #define SCK_LORA 5 13 | #define MISO_LORA 19 14 | #define MOSI_LORA 27 15 | #define RESET_PIN_LORA 14 16 | #define SS_PIN_LORA 18 17 | 18 | #define HIGH_GAIN_LORA 20 /* dBm */ 19 | #define BAND 915E6 /* 915MHz de frequencia */ 20 | 21 | /* Definicoes do OLED */ 22 | #define OLED_SDA_PIN 4 23 | #define OLED_SCL_PIN 15 24 | #define SCREEN_WIDTH 128 25 | #define SCREEN_HEIGHT 64 26 | #define OLED_ADDR 0x3C 27 | #define OLED_RESET 16 28 | 29 | /* Offset de linhas no display OLED */ 30 | #define OLED_LINE1 0 31 | #define OLED_LINE2 10 32 | #define OLED_LINE3 20 33 | #define OLED_LINE4 30 34 | #define OLED_LINE5 40 35 | #define OLED_LINE6 50 36 | 37 | /* Definicoes gerais */ 38 | #define DEBUG_SERIAL_BAUDRATE 115200 39 | 40 | /* Variaveis e objetos globais */ 41 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 42 | 43 | /* Local prototypes */ 44 | void display_init(void); 45 | bool init_comunicacao_lora(void); 46 | 47 | /* typedefs */ 48 | typedef struct __attribute__((__packed__)) 49 | { 50 | float temperatura; 51 | float umidade; 52 | float temperatura_min; 53 | float temperatura_max; 54 | }TDadosLora; 55 | 56 | /* Funcao: inicializa comunicacao com o display OLED 57 | * Parametros: nenhnum 58 | * Retorno: nenhnum 59 | */ 60 | void display_init(void) 61 | { 62 | if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) 63 | { 64 | Serial.println("[LoRa Receiver] Falha ao inicializar comunicacao com OLED"); 65 | } 66 | else 67 | { 68 | Serial.println("[LoRa Receiver] Comunicacao com OLED inicializada com sucesso"); 69 | 70 | /* Limpa display e configura tamanho de fonte */ 71 | display.clearDisplay(); 72 | display.setTextSize(1); 73 | display.setTextColor(WHITE); 74 | } 75 | } 76 | 77 | /* Funcao: inicia comunicação com chip LoRa 78 | * Parametros: nenhum 79 | * Retorno: true: comunicacao ok 80 | * false: falha na comunicacao 81 | */ 82 | bool init_comunicacao_lora(void) 83 | { 84 | bool status_init = false; 85 | Serial.println("[LoRa Receiver] Tentando iniciar comunicacao com o radio LoRa..."); 86 | SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA); 87 | LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN); 88 | 89 | if (!LoRa.begin(BAND)) 90 | { 91 | Serial.println("[LoRa Receiver] Comunicacao com o radio LoRa falhou. Nova tentativa em 1 segundo..."); 92 | delay(1000); 93 | status_init = false; 94 | } 95 | else 96 | { 97 | /* Configura o ganho do receptor LoRa para 20dBm, o maior ganho possível (visando maior alcance possível) */ 98 | LoRa.setTxPower(HIGH_GAIN_LORA); 99 | Serial.println("[LoRa Receiver] Comunicacao com o radio LoRa ok"); 100 | status_init = true; 101 | } 102 | 103 | return status_init; 104 | } 105 | 106 | /* Funcao de setup */ 107 | void setup() 108 | { 109 | /* Configuracao da I²C para o display OLED */ 110 | Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN); 111 | 112 | /* Display init */ 113 | display_init(); 114 | 115 | /* Print message telling to wait */ 116 | display.clearDisplay(); 117 | display.setCursor(0, OLED_LINE1); 118 | display.print("Aguarde..."); 119 | display.display(); 120 | 121 | Serial.begin(DEBUG_SERIAL_BAUDRATE); 122 | while (!Serial); 123 | 124 | /* Tenta, até obter sucesso, comunicacao com o chip LoRa */ 125 | while(init_comunicacao_lora() == false); 126 | } 127 | 128 | /* Programa principal */ 129 | void loop() 130 | { 131 | char byte_recebido; 132 | int packet_size = 0; 133 | int lora_rssi = 0; 134 | TDadosLora dados_lora; 135 | char * ptInformaraoRecebida = NULL; 136 | 137 | /* Verifica se chegou alguma informação do tamanho esperado */ 138 | packet_size = LoRa.parsePacket(); 139 | 140 | if (packet_size == sizeof(TDadosLora)) 141 | { 142 | Serial.print("[LoRa Receiver] Há dados a serem lidos"); 143 | 144 | /* Recebe os dados conforme protocolo */ 145 | ptInformaraoRecebida = (char *)&dados_lora; 146 | while (LoRa.available()) 147 | { 148 | byte_recebido = (char)LoRa.read(); 149 | *ptInformaraoRecebida = byte_recebido; 150 | ptInformaraoRecebida++; 151 | } 152 | 153 | /* Escreve RSSI de recepção e informação recebida */ 154 | lora_rssi = LoRa.packetRssi(); 155 | display.clearDisplay(); 156 | display.setCursor(0, OLED_LINE1); 157 | display.print("Temp: "); 158 | display.println(dados_lora.temperatura); 159 | 160 | display.setCursor(0, OLED_LINE2); 161 | display.print("Umid: "); 162 | display.println(dados_lora.umidade); 163 | 164 | display.setCursor(0, OLED_LINE3); 165 | display.println("Temp min/max:"); 166 | display.setCursor(0, OLED_LINE4); 167 | display.print(dados_lora.temperatura_min); 168 | display.print("/"); 169 | display.print(dados_lora.temperatura_max); 170 | 171 | display.display(); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /Exemplos/Cap5/leitura_temp_umid_local.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Projeto: medição local de temperatura e umidade 3 | * Autor: Pedro Bertoleti 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 11 | * Defines do projeto 12 | */ 13 | /* GPIO do módulo WiFi LoRa 32(V2) que o pino de comunicação do sensor está ligado. */ 14 | #define DHTPIN 13 /* (GPIO 13) */ 15 | 16 | /* Endereço I2C do display */ 17 | #define OLED_ADDR 0x3c 18 | 19 | /* distancia, em pixels, de cada linha em relacao ao topo do display */ 20 | #define OLED_LINE1 0 21 | #define OLED_LINE2 10 22 | #define OLED_LINE3 20 23 | #define OLED_LINE4 30 24 | #define OLED_LINE5 40 25 | #define OLED_LINE6 50 26 | 27 | /* Configuração da resolucao do display (este modulo possui display 128x64) */ 28 | #define SCREEN_WIDTH 128 29 | #define SCREEN_HEIGHT 64 30 | 31 | /* 32 | A biblioteca serve para os sensores DHT11, DHT22 e DHT21. 33 | No nosso caso, usaremos o DHT22, porém se você desejar utilizar 34 | algum dos outros disponíveis, basta descomentar a linha correspondente. 35 | */ 36 | //#define DHTTYPE DHT11 // DHT 11 37 | #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 38 | //#define DHTTYPE DHT21 // DHT 21 (AM2301) 39 | 40 | /* 41 | * Variáveis e objetos globais 42 | */ 43 | /* objeto para comunicação com sensor DHT22 */ 44 | DHT dht(DHTPIN, DHTTYPE); 45 | 46 | /* objeto do display */ 47 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 16); 48 | 49 | /* variáveis que armazenam os valores máximo e mínimo de temperatura registrados. */ 50 | float temperatura_max; 51 | float temperatura_min; 52 | 53 | /* prototypes */ 54 | void atualiza_temperatura_max_e_minima(float temp_lida); 55 | void envia_medicoes_para_serial(float temp_lida, float umid_lida); 56 | void escreve_temperatura_umidade_display(float temp_lida, float umid_lida); 57 | 58 | /* 59 | * Implementações 60 | */ 61 | 62 | /* Função: verifica se os valores de temperatura máxima e mínima devem ser atualizados 63 | * Parâmetros: temperatura lida 64 | * Retorno: nenhum 65 | */ 66 | void atualiza_temperatura_max_e_minima(float temp_lida) 67 | { 68 | if (temp_lida > temperatura_max) 69 | temperatura_max = temp_lida; 70 | 71 | if (temp_lida < temperatura_min) 72 | temperatura_min = temp_lida; 73 | } 74 | 75 | /* Função: envia, na forma de mensagens textuais, as medições para a serial 76 | * Parâmetros: - Temperatura lida 77 | * - Umidade relativa do ar lida 78 | * - Máxima temperatura registrada 79 | * - Mínima temperatura registrada 80 | * Retorno: nenhum 81 | */ 82 | void envia_medicoes_para_serial(float temp_lida, float umid_lida) 83 | { 84 | char mensagem[200]; 85 | char i; 86 | 87 | /* pula 80 linhas, de forma que no monitor serial seja exibida somente as mensagens atuais (impressao de refresh de tela) */ 88 | for(i=0; i<80; i++) 89 | Serial.println(" "); 90 | 91 | /* constrói mensagens e as envia */ 92 | /* - temperatura atual */ 93 | memset(mensagem,0,sizeof(mensagem)); 94 | sprintf(mensagem,"- Temperatura: %.2f C", temp_lida); 95 | Serial.println(mensagem); 96 | 97 | //- umidade relativa do ar atual 98 | memset(mensagem,0,sizeof(mensagem)); 99 | sprintf(mensagem,"- Umidade atual: %.2f \\%",umid_lida); 100 | Serial.println(mensagem); 101 | 102 | //- temperatura maxima 103 | memset(mensagem,0,sizeof(mensagem)); 104 | sprintf(mensagem,"- Temperatura maxima: %.2f C", temperatura_max); 105 | Serial.println(mensagem); 106 | 107 | //- temperatura minima 108 | memset(mensagem,0,sizeof(mensagem)); 109 | sprintf(mensagem,"- Temperatura minima: %.2f C", temperatura_min); 110 | Serial.println(mensagem); 111 | } 112 | 113 | /* Função: escreve no display OLED a temperatura e umidade lidas, assim como as temperaturas máxima e mínima 114 | * Parâmetros: - Temperatura lida 115 | * - Umidade relativa do ar lida 116 | * Retorno: nenhum 117 | */ 118 | void escreve_temperatura_umidade_display(float temp_lida, float umid_lida) 119 | { 120 | char str_temp[10] = {0}; 121 | char str_umid[10] = {0}; 122 | char str_temp_max_min[20] = {0}; 123 | 124 | /* formata para o display as strings de temperatura e umidade */ 125 | sprintf(str_temp, "%.2fC", temp_lida); 126 | sprintf(str_umid, "%.2f/100", umid_lida); 127 | sprintf(str_temp_max_min, "%.2fC / %.2fC", temperatura_min, temperatura_max); 128 | 129 | display.clearDisplay(); 130 | display.setCursor(0, OLED_LINE1); 131 | display.println("Temperatura:"); 132 | display.setCursor(0, OLED_LINE2); 133 | display.println(str_temp); 134 | display.setCursor(0, OLED_LINE3); 135 | display.println("Umidade:"); 136 | display.setCursor(0, OLED_LINE4); 137 | display.print(str_umid); 138 | display.setCursor(0, OLED_LINE5); 139 | display.println("Temp. min / max:"); 140 | display.setCursor(0, OLED_LINE6); 141 | display.print(str_temp_max_min); 142 | display.display(); 143 | } 144 | 145 | 146 | void setup() { 147 | /* configura comunicação serial (para enviar mensgens com as medições) 148 | e inicializa comunicação com o sensor. 149 | */ 150 | Serial.begin(115200); 151 | dht.begin(); 152 | 153 | /* inicializa temperaturas máxima e mínima com a leitura inicial do sensor */ 154 | temperatura_max = dht.readTemperature(); 155 | temperatura_min = temperatura_max; 156 | 157 | /* inicializa display OLED */ 158 | Wire.begin(4, 15); 159 | 160 | if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) 161 | Serial.println("Display OLED: falha ao inicializar"); 162 | else 163 | { 164 | Serial.println("Display OLED: inicializacao ok"); 165 | 166 | /* Limpa display e configura tamanho de fonte */ 167 | display.clearDisplay(); 168 | display.setTextSize(1); 169 | display.setTextColor(WHITE); 170 | } 171 | } 172 | 173 | /* 174 | * Programa principal 175 | */ 176 | void loop() { 177 | float temperatura_lida; 178 | float umidade_lida; 179 | 180 | /* Faz a leitura de temperatura e umidade do sensor */ 181 | temperatura_lida = dht.readTemperature(); 182 | umidade_lida = dht.readHumidity(); 183 | 184 | /* se houve falha na leitura do sensor, escreve mensagem de erro na serial */ 185 | if ( isnan(temperatura_lida) || isnan(umidade_lida) ) 186 | Serial.println("Erro ao ler sensor DHT22!"); 187 | else 188 | { 189 | /*Se a leitura foi bem sucedida, ocorre o seguinte: 190 | - Os valores mínimos e máximos são verificados e comparados à medição atual de temperatura 191 | se a temperatura atual for menor que a mínima ou maior que a máxima até então 192 | registrada, os limites máximo ou mínimo são atualizados. 193 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 194 | enviados pela serial na forma de mensagem textual. Tais mensagens podem ser vistas 195 | no monitor serial. 196 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 197 | escritas no display OLED 198 | */ 199 | atualiza_temperatura_max_e_minima(temperatura_lida); 200 | envia_medicoes_para_serial(temperatura_lida, umidade_lida); 201 | escreve_temperatura_umidade_display(temperatura_lida, umidade_lida); 202 | } 203 | 204 | /* espera cinco segundos até a próxima leitura */ 205 | delay(5000); 206 | } 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /Exemplos/Cap7/turbidez_agua_emissor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Projeto: emissor - medição de turbudez da agua via LoRa 3 | * Autor: Pedro Bertoleti 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | /* Definicoes para comunicação com radio LoRa */ 11 | #define SCK_LORA 5 12 | #define MISO_LORA 19 13 | #define MOSI_LORA 27 14 | #define RESET_PIN_LORA 14 15 | #define SS_PIN_LORA 18 16 | #define HIGH_GAIN_LORA 20 /* dBm */ 17 | #define BAND 915E6 /* 915MHz de frequencia */ 18 | 19 | /* Definições gerais */ 20 | #define DEBUG_SERIAL_BAUDRATE 115200 21 | 22 | /* Definições do buffer (para filtro de média móvel) */ 23 | #define TAMANHO_BUFFER 50 24 | 25 | /* Definições da leitura do sensor de turbidez */ 26 | #define ADC_MAX 4095 /* ADC do modulo WiFi LoRa 32(V2) tem 12 bits de resolucao */ 27 | #define ENTRADA_ANALOGICA_SENSOR_TURBIDEZ 13 /* GPIO 13 => ADC2_CH4 */ 28 | #define TENSAO_MAXIMA_SAIDA_SENSOR_TURBIDEZ 5 /* Sensor apresenta saida analogica de 0 a 5V */ 29 | #define FATOR_DIVISOR_TENSAO 10 /* No projeto, para serem respeitados os limites de operação do 30 | ADC e fazer com que a tensão do sensor excursione corretamente em 31 | todo seu range, ha um divisor resistivo para que a tensão lida pelo 32 | canal do ADC utilizado seja igual a 10% da tensão real de saída do sensor. 33 | Portanto, no cálculo da tensão real, este fator é utilizado 34 | para se recuperar corretamente este valor */ 35 | #define NUM_LEITURAS_OVERSAMPLING 512 36 | 37 | /* Variáveis globais */ 38 | float buffer_tensao_sensor_turbidez[TAMANHO_BUFFER]; 39 | 40 | /* Protótipos */ 41 | bool init_comunicacao_lora(void); 42 | float le_tensao_sensor_turbidez_sem_filtro(void); 43 | float le_tensao_sensor_turbidez_com_filtro(void); 44 | float le_turbidez_da_agua(void); 45 | 46 | /* Função: inicia comunicação com chip LoRa 47 | * Parâmetros: nenhum 48 | * Retorno: true: comunicação ok 49 | * false: falha na comunicação 50 | */ 51 | bool init_comunicacao_lora(void) 52 | { 53 | bool status_init = false; 54 | 55 | Serial.println("[Modulo medidor] Tentando iniciar comunicacao com o radio LoRa..."); 56 | SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA); 57 | LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN); 58 | 59 | if (!LoRa.begin(BAND)) 60 | { 61 | Serial.println("[Modulo medidor] Comunicacao com o radio LoRa falhou. Nova tentativa em 1 segundo..."); 62 | delay(1000); 63 | status_init = false; 64 | } 65 | else 66 | { 67 | /* Configura o ganho do receptor LoRa para 20dBm, o maior ganho possível (visando maior alcance possível) */ 68 | LoRa.setTxPower(HIGH_GAIN_LORA); 69 | Serial.println("[Modulo medidor] Comunicacao com o radio LoRa ok"); 70 | status_init = true; 71 | } 72 | return status_init; 73 | } 74 | 75 | /* Função: faz a leitura da tensão de saída do sensor de turbidez (sem filtro) 76 | * Parâmetros: nenhum 77 | * Retorno: tensão de saída (de 0 até 5V) 78 | */ 79 | float le_tensao_sensor_turbidez_sem_filtro(void) 80 | { 81 | float tensao_saida_sensor = 0.0; 82 | int leitura_adc = 0; 83 | 84 | /* Faz a leitura do canal do ADC do modulo que a saida do sensor de turbidez está ligado */ 85 | leitura_adc = analogRead(ENTRADA_ANALOGICA_SENSOR_TURBIDEZ); 86 | 87 | /* converte a leitura do ADC (canal onde está ligada a saída do sensor de turbidez) em uma tensão de leitura de 0 a 5V */ 88 | tensao_saida_sensor = ((leitura_adc/(float)ADC_MAX)*(float)TENSAO_MAXIMA_SAIDA_SENSOR_TURBIDEZ); 89 | Serial.print("[Modulo medidor] Tensao de saida (no divisor): "); 90 | Serial.print(tensao_saida_sensor); 91 | Serial.println("V"); 92 | tensao_saida_sensor = tensao_saida_sensor*FATOR_DIVISOR_TENSAO; /* Corrige a leitura com base no divisor resistivo utilizado */ 93 | return tensao_saida_sensor; 94 | } 95 | 96 | /* Função: faz a leitura da tensao de saida do sensor de turbidez (com filtro) 97 | * Parâmetros: nenhum 98 | * Retorno: tensão de saída (de 0 até 5V) 99 | */ 100 | float le_tensao_sensor_turbidez_com_filtro(void) 101 | { 102 | float tensao_saida_sensor = 0.0; 103 | int leitura_adc = 0; 104 | long soma_leituras_adc = 0; 105 | int i = 0; 106 | float soma = 0.0; 107 | float tensao_filtrada = 0.0; 108 | 109 | /* Faz a leitura do canal do ADC do modulo que a saída do sensor de turbidez está ligado */ 110 | /* Para amenizar efeitos de leituras ruidosas / com oscilações, um oversampling é feito */ 111 | soma_leituras_adc = 0; 112 | for (i=0; i 4.2) 161 | tensao_filtrada = 4.2; 162 | 163 | Serial.print("[Modulo medidor] Tensao de saida do sensor de turbidez: "); 164 | Serial.print(tensao_filtrada); 165 | Serial.println("V"); 166 | 167 | /* Calcula a turbidez */ 168 | primeiro_fator = ((-1)*(1120.4) * tensao_filtrada * tensao_filtrada); 169 | segundo_fator = (5742.3 * tensao_filtrada); 170 | terceiro_fator = ((-1)*4352.9); 171 | turbidez_agua = primeiro_fator + segundo_fator + terceiro_fator; 172 | 173 | return turbidez_agua; 174 | } 175 | 176 | /* Função de setup */ 177 | void setup() 178 | { 179 | int i; 180 | 181 | Serial.begin(DEBUG_SERIAL_BAUDRATE); 182 | 183 | /* Configura ADC em sua resolução máxima (12 bits) */ 184 | analogReadResolution(12); 185 | 186 | /* Inicializa buffer de leituras de tensão do sensor de turbidez (para inicializar o buffer do filtro de média móvel)*/ 187 | for(i=0; i 6 | #include 7 | #include 8 | 9 | /* Defines gerais*/ 10 | #define BAUDRATE_SERIAL_DEBUG 115200 11 | #define SIM 1 12 | #define NAO 0 13 | #define OFFSET_CONVERSAO_CHAR 0x41 14 | #define TEMPO_ACENDIMENTO_LED 500 //ms 15 | 16 | /* Defines da Fita LED */ 17 | #define NUM_LETRAS_ALFABETO 26 /* A, B, C, ... Z */ 18 | #define NUM_LEDS NUM_LETRAS_ALFABETO /* Número de LEDs do projeto */ 19 | #define DATA_PIN 13 /* GPIO do módulo que será ligado ao Data Pin */ 20 | #define LED_TYPE WS2811 /* Tipo de fita led do projeto */ 21 | #define ORDEM_DAS_CORES GRB 22 | #define COR_LEDS CRGB::Blue /* Cor que os LEDs devem ter ao acender */ 23 | #define LED_APAGADO CRGB::Black 24 | 25 | /* Defines de id mqtt e tópicos para publicação e subscribe */ 26 | #define TOPICO_SUB "MQTTStrangerThingsMsg" /* tópico MQTT de escuta */ 27 | #define ID_MQTT "StrangerThingsINCB" /* id mqtt (para identificação de sessão) */ 28 | /* IMPORTANTE: este deve ser único no broker (ou seja, 29 | se um client MQTT tentar entrar com o mesmo 30 | id de outro já conectado ao broker, o broker 31 | irá fechar a conexão de um deles). 32 | */ 33 | 34 | /* Variáveis globais */ 35 | /* Variáveis gerais */ 36 | CRGB leds_projeto[NUM_LEDS]; 37 | int ha_mensagem_a_ser_escrita = NAO; 38 | 39 | /* Mensagem a ser escrita */ 40 | String msg_a_ser_escrita = ""; 41 | 42 | /* WIFI */ 43 | const char* SSID_WIFI = " "; /* Coloque aqui o SSID_WIFI / nome da rede WI-FI que deseja se conectar */ 44 | const char* PASSWORD_WIFI = " "; /* Coloque aqui a senha da rede WI-FI que deseja se conectar */ 45 | 46 | /* MQTT */ 47 | const char* BROKER_MQTT = "broker.hivemq.com"; /* URL do broker MQTT que se deseja utilizar */ 48 | int BROKER_PORT = 1883; /* Porta do Broker MQTT */ 49 | 50 | WiFiClient espClient; /* cria o objeto espClient */ 51 | PubSubClient MQTT(espClient); /* objeto PubSubClient */ 52 | 53 | /* Prototypes */ 54 | void init_serial_debug(void); 55 | void init_wifi(void); 56 | void init_MQTT(void); 57 | void connect_wifi(void); 58 | void init_outputs(void); 59 | void mqtt_callback(char* topic, byte* payload, unsigned int length); 60 | void verifica_conexoes_wifi_e_MQTT(void); 61 | void escreve_mensagem_alfabeto(void); 62 | 63 | /* 64 | * Implementações 65 | */ 66 | 67 | /* Função: inicializa comunicação serial com baudrate 115200 (para fins de monitorar no terminal serial 68 | o que está acontecendo. 69 | Parâmetros: nenhum 70 | Retorno: nenhum 71 | */ 72 | void init_serial_debug(void) 73 | { 74 | Serial.begin(BAUDRATE_SERIAL_DEBUG); 75 | } 76 | 77 | /* Função: inicializa e conecta-se na rede WI-FI desejada 78 | Parâmetros: nenhum 79 | Retorno: nenhum 80 | */ 81 | void init_wifi(void) 82 | { 83 | delay(10); 84 | Serial.println("------Conexao WI-FI -----"); 85 | Serial.print("Conectando-se na rede: "); 86 | Serial.println(SSID_WIFI); 87 | Serial.println("Aguarde"); 88 | 89 | connect_wifi(); 90 | } 91 | 92 | /* Função: inicializa parâmetros de conexão MQTT(endereço do 93 | broker, porta e seta função de callback) 94 | Parâmetros: nenhum 95 | Retorno: nenhum 96 | */ 97 | void init_MQTT(void) 98 | { 99 | MQTT.setServer(BROKER_MQTT, BROKER_PORT); //informa qual broker e porta deve ser conectado 100 | MQTT.setCallback(mqtt_callback); //atribui função de callback (função chamada quando qualquer informação de um dos tópicos subescritos chega) 101 | } 102 | 103 | /* Função: função de callback 104 | esta função é chamada toda vez que uma informação de 105 | um dos tópicos subescritos chega) 106 | Parâmetros: nenhum 107 | Retorno: nenhum 108 | */ 109 | void mqtt_callback(char* topic, byte* payload, unsigned int length) 110 | { 111 | String msg_recebida; 112 | int i; 113 | 114 | /* Se o tamanho estiver dentro dos limites permitidos, obtem a string do payload recebido */ 115 | for(i = 0; i < length; i++) 116 | { 117 | char c = (char)payload[i]; 118 | msg_recebida += c; 119 | } 120 | 121 | Serial.println("Mensagem recebida: "); 122 | Serial.print(msg_recebida); 123 | 124 | /* Faz o upper case da string */ 125 | msg_recebida.toUpperCase(); 126 | msg_a_ser_escrita = msg_recebida; 127 | ha_mensagem_a_ser_escrita = SIM; 128 | } 129 | 130 | /* Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair) 131 | em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito. 132 | Parâmetros: nenhum 133 | Retorno: nenhum 134 | */ 135 | void reconnectMQTT() 136 | { 137 | while (!MQTT.connected()) 138 | { 139 | Serial.print("* Tentando se conectar ao Broker MQTT: "); 140 | Serial.println(BROKER_MQTT); 141 | if (MQTT.connect(ID_MQTT)) 142 | { 143 | Serial.println("Conectado com sucesso ao broker MQTT!"); 144 | MQTT.subscribe(TOPICO_SUB); 145 | } 146 | else 147 | { 148 | Serial.println("Falha ao reconectar no broker."); 149 | Serial.println("Havera nova tentativa de conexao em 2s"); 150 | delay(2000); 151 | } 152 | } 153 | } 154 | 155 | /* Função: reconecta-se ao WiFi 156 | Parâmetros: nenhum 157 | Retorno: nenhum 158 | */ 159 | void connect_wifi(void) 160 | { 161 | /* se já está conectado a rede WI-FI, nada é feito. 162 | Caso contrário, são efetuadas tentativas de conexão 163 | */ 164 | if (WiFi.status() == WL_CONNECTED) 165 | return; 166 | 167 | WiFi.begin(SSID_WIFI, PASSWORD_WIFI); // Conecta na rede WI-FI 168 | 169 | while (WiFi.status() != WL_CONNECTED) 170 | { 171 | delay(100); 172 | Serial.print("."); 173 | } 174 | 175 | Serial.println(); 176 | Serial.print("Conectado com sucesso na rede "); 177 | Serial.print(SSID_WIFI); 178 | Serial.println("IP obtido: "); 179 | Serial.println(WiFi.localIP()); 180 | } 181 | 182 | /* Função: verifica o estado das conexões WiFI e ao broker MQTT. 183 | Em caso de desconexão (qualquer uma das duas), a conexão 184 | é refeita. 185 | Parâmetros: nenhum 186 | Retorno: nenhum 187 | */ 188 | void verifica_conexoes_wifi_e_MQTT(void) 189 | { 190 | connect_wifi(); //se não há conexão com o WiFI, a conexão é refeita 191 | 192 | if (!MQTT.connected()) 193 | reconnectMQTT(); //se não há conexão com o Broker, a conexão é refeita 194 | } 195 | 196 | /* Função: escreve mensagem recebida no alfabeto stranger things 197 | Parâmetros: nenhum 198 | Retorno: nenhum 199 | */ 200 | void escreve_mensagem_alfabeto(void) 201 | { 202 | int i; 203 | int led_para_acender=0; 204 | char caracter_msg=0x00; 205 | 206 | for(i=0; i < msg_a_ser_escrita.length(); i++) 207 | 208 | /* Obtem qual led da fita deve acender 209 | Ex: A: led 0; B: led 1; ... ; Z: led 25 */ 210 | caracter_msg = msg_a_ser_escrita.charAt(i); 211 | 212 | /* Qualquer caracter fora do range A..Z é ignorado */ 213 | if ( (caracter_msg < 'A') && (caracter_msg > 'Z') ) 214 | continue; 215 | 216 | led_para_acender = int(caracter_msg) - OFFSET_CONVERSAO_CHAR; 217 | 218 | leds_projeto[led_para_acender] = COR_LEDS; 219 | FastLED.show(); 220 | delay(TEMPO_ACENDIMENTO_LED); 221 | 222 | leds_projeto[led_para_acender] = LED_APAGADO; 223 | FastLED.show(); 224 | delay(TEMPO_ACENDIMENTO_LED); 225 | 226 | } 227 | 228 | 229 | /* Função de setup */ 230 | void setup() 231 | { 232 | /* Inicializa serial de debug / serial monitor */ 233 | init_serial_debug(); 234 | 235 | /* Inicializa wifi e MQTT */ 236 | init_wifi(); 237 | init_MQTT(); 238 | 239 | /* Inicializa biblioteca de LEDs para operar com fita led do projeto (WS2811) */ 240 | FastLED.addLeds(leds_projeto, NUM_LEDS).setCorrection(TypicalLEDStrip); 241 | } 242 | 243 | void loop() 244 | { 245 | int i; 246 | 247 | /* Verifica se o wi-fi e MQTT estão conectados */ 248 | verifica_conexoes_wifi_e_MQTT(); 249 | 250 | /* Verifica se há mensagem a ser excrita. 251 | Se sim, faz a escrita no alfabeto Stranger Things */ 252 | if (ha_mensagem_a_ser_escrita == SIM) 253 | { 254 | escreve_mensagem_alfabeto(); 255 | ha_mensagem_a_ser_escrita = NAO; 256 | msg_a_ser_escrita = ""; 257 | } 258 | 259 | /* Faz o keep-alive do MQTT */ 260 | MQTT.loop(); 261 | } 262 | 263 | 264 | 265 | -------------------------------------------------------------------------------- /Exemplos/Cap6/rover_esp32_reles.ino: -------------------------------------------------------------------------------- 1 | /* Programa: código-fonte do robô tipo rover (controle e acionamento de motores 2 | com relés 3 | Descrição: código-fonte do robô tipo rover, controlado por Internet via MQTT. 4 | Sua movimentação é feita conforme a recepção de caracteres via MQTT: 5 | F: rover se move para frente 6 | D: rover se move para a direita 7 | E: rover se move para a esquerda 8 | P: o rover para (os motores são desacionados) 9 | Autor: Pedro Bertoleti 10 | */ 11 | 12 | /* includes */ 13 | #include 14 | #include 15 | 16 | /* defines gerais */ 17 | #define BAUDRATE_SERIAL_DEBUG 115200 18 | 19 | /* defines de id mqtt e tópicos para publicação e subscribe */ 20 | #define TOPICO_SUB "MQTTRoverEnvia" /* tópico MQTT de escuta */ 21 | #define TOPICO_PUB "MQTTRoverRecebe" /* tópico MQTT de envio de informações para Broker */ 22 | #define ID_MQTT "RoboRoverINCB" /* id mqtt (para identificação de sessão) */ 23 | /* IMPORTANTE: este deve ser único no broker (ou seja, 24 | se um client MQTT tentar entrar com o mesmo 25 | id de outro já conectado ao broker, o broker 26 | irá fechar a conexão de um deles). 27 | */ 28 | 29 | /* defines - motores */ 30 | #define MOTOR_DIRETO 12 /* GPIO 12 */ 31 | #define MOTOR_ESQUERDO 13 /* GPIO 13 */ 32 | 33 | /* defines - movimentacao */ 34 | #define CARACTER_MOVE_FRENTE "F" 35 | #define CARACTER_MOVE_DIREITA "D" 36 | #define CARACTER_MOVE_ESQUERDA "E" 37 | #define CARACTER_PARA_ROVER "P" 38 | 39 | 40 | /* Variáveis e objetos globais: */ 41 | /* WIFI */ 42 | const char* SSID_WIFI = " "; /* Coloque aqui o SSID_WIFI / nome da rede WI-FI que deseja se conectar */ 43 | const char* PASSWORD_WIFI = " "; /* Coloque aqui a senha da rede WI-FI que deseja se conectar */ 44 | 45 | /* MQTT */ 46 | const char* BROKER_MQTT = "iot.eclipse.org"; /* URL do broker MQTT que se deseja utilizar */ 47 | int BROKER_PORT = 1883; /* Porta do Broker MQTT */ 48 | 49 | /* Variáveis e objetos globais */ 50 | WiFiClient espClient; /* cria o objeto espClient */ 51 | PubSubClient MQTT(espClient); /* objeto PubSubClient */ 52 | char estado_motor_direito = '0'; /* estado atual do motor da direita */ 53 | char estado_motor_esquerdo = '0'; /* estado atual do motor da esquerda */ 54 | 55 | /* Prototypes */ 56 | void init_serial_debug(void); 57 | void init_wifi(void); 58 | void init_MQTT(void); 59 | void connect_wifi(void); 60 | void init_outputs(void); 61 | void mqtt_callback(char* topic, byte* payload, unsigned int length); 62 | void verifica_conexoes_wifi_e_MQTT(void); 63 | void envia_estado_output_MQTT(void); 64 | 65 | /* 66 | * Implementações das funções 67 | */ 68 | void setup() 69 | { 70 | //Faz as inicializações necessárias 71 | init_outputs(); 72 | init_serial_debug(); 73 | init_wifi(); 74 | init_MQTT(); 75 | } 76 | 77 | /* Função: inicializa comunicação serial com baudrate 115200 (para fins de monitorar no terminal serial 78 | o que está acontecendo. 79 | Parâmetros: nenhum 80 | Retorno: nenhum 81 | */ 82 | void init_serial_debug(void) 83 | { 84 | Serial.begin(BAUDRATE_SERIAL_DEBUG); 85 | } 86 | 87 | /* Função: inicializa e conecta-se na rede WI-FI desejada 88 | Parâmetros: nenhum 89 | Retorno: nenhum 90 | */ 91 | void init_wifi(void) 92 | { 93 | delay(10); 94 | Serial.println("------Conexao WI-FI -----"); 95 | Serial.print("Conectando-se na rede: "); 96 | Serial.println(SSID_WIFI); 97 | Serial.println("Aguarde"); 98 | 99 | connect_wifi(); 100 | } 101 | 102 | /* Função: inicializa parâmetros de conexão MQTT(endereço do 103 | broker, porta e seta função de callback) 104 | Parâmetros: nenhum 105 | Retorno: nenhum 106 | */ 107 | void init_MQTT(void) 108 | { 109 | MQTT.setServer(BROKER_MQTT, BROKER_PORT); //informa qual broker e porta deve ser conectado 110 | MQTT.setCallback(mqtt_callback); //atribui função de callback (função chamada quando qualquer informação de um dos tópicos subescritos chega) 111 | } 112 | 113 | /* Função: função de callback 114 | esta função é chamada toda vez que uma informação de 115 | um dos tópicos subescritos chega) 116 | Parâmetros: nenhum 117 | Retorno: nenhum 118 | */ 119 | void mqtt_callback(char* topic, byte* payload, unsigned int length) 120 | { 121 | String msg; 122 | int i; 123 | 124 | /* obtem a string do payload recebido */ 125 | for(i = 0; i < length; i++) 126 | { 127 | char c = (char)payload[i]; 128 | msg += c; 129 | } 130 | 131 | /* toma ação dependendo da string recebida: */ 132 | if (msg.equals(CARACTER_MOVE_FRENTE)) 133 | { 134 | //para ir para frente, os dois motores são ligados 135 | digitalWrite(MOTOR_DIRETO, HIGH); 136 | digitalWrite(MOTOR_ESQUERDO, HIGH); 137 | 138 | estado_motor_direito = '1'; 139 | estado_motor_esquerdo = '1'; 140 | } 141 | 142 | if (msg.equals(CARACTER_MOVE_DIREITA)) 143 | { 144 | /* para ir para a direita, somente o motor da esquerda é ligado */ 145 | digitalWrite(MOTOR_DIRETO, LOW); 146 | digitalWrite(MOTOR_ESQUERDO, HIGH); 147 | 148 | estado_motor_direito = '0'; 149 | estado_motor_esquerdo = '1'; 150 | } 151 | 152 | if (msg.equals(CARACTER_MOVE_ESQUERDA)) 153 | { 154 | /* para ir para a esquerda, somente o motor da direita é ligado */ 155 | digitalWrite(MOTOR_DIRETO, HIGH); 156 | digitalWrite(MOTOR_ESQUERDO, LOW); 157 | 158 | estado_motor_direito = '1'; 159 | estado_motor_esquerdo = '0'; 160 | } 161 | 162 | if (msg.equals(CARACTER_PARA_ROVER)) 163 | { 164 | /* para parar, os dois motores são desligados */ 165 | digitalWrite(MOTOR_DIRETO, LOW); 166 | digitalWrite(MOTOR_ESQUERDO, LOW); 167 | 168 | estado_motor_direito = '0'; 169 | estado_motor_esquerdo = '0'; 170 | } 171 | } 172 | 173 | /* Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair) 174 | em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito. 175 | Parâmetros: nenhum 176 | Retorno: nenhum 177 | */ 178 | void reconnectMQTT() 179 | { 180 | while (!MQTT.connected()) 181 | { 182 | Serial.print("* Tentando se conectar ao Broker MQTT: "); 183 | Serial.println(BROKER_MQTT); 184 | if (MQTT.connect(ID_MQTT)) 185 | { 186 | Serial.println("Conectado com sucesso ao broker MQTT!"); 187 | MQTT.subscribe(TOPICO_SUB); 188 | } 189 | else 190 | { 191 | Serial.println("Falha ao reconectar no broker."); 192 | Serial.println("Havera nova tentatica de conexao em 2s"); 193 | delay(2000); 194 | } 195 | } 196 | } 197 | 198 | /* Função: reconecta-se ao WiFi 199 | Parâmetros: nenhum 200 | Retorno: nenhum 201 | */ 202 | void connect_wifi(void) 203 | { 204 | /* se já está conectado a rede WI-FI, nada é feito. 205 | Caso contrário, são efetuadas tentativas de conexão */ 206 | if (WiFi.status() == WL_CONNECTED) 207 | return; 208 | 209 | WiFi.begin(SSID_WIFI, PASSWORD_WIFI); // Conecta na rede WI-FI 210 | 211 | while (WiFi.status() != WL_CONNECTED) 212 | { 213 | delay(100); 214 | Serial.print("."); 215 | } 216 | 217 | Serial.println(); 218 | Serial.print("Conectado com sucesso na rede "); 219 | Serial.print(SSID_WIFI); 220 | Serial.println("IP obtido: "); 221 | Serial.println(WiFi.localIP()); 222 | } 223 | 224 | /* Função: verifica o estado das conexões WiFI e ao broker MQTT. 225 | Em caso de desconexão (qualquer uma das duas), a conexão 226 | é refeita. 227 | Parâmetros: nenhum 228 | Retorno: nenhum 229 | */ 230 | void verifica_conexoes_wifi_e_MQTT(void) 231 | { 232 | if (!MQTT.connected()) 233 | reconnectMQTT(); //se não há conexão com o Broker, a conexão é refeita 234 | 235 | connect_wifi(); //se não há conexão com o WiFI, a conexão é refeita 236 | } 237 | 238 | /* Função: envia ao Broker o estado atual do output 239 | Parâmetros: nenhum 240 | Retorno: nenhum 241 | */ 242 | void envia_estado_output_MQTT(void) 243 | { 244 | char estados_motores[4]; 245 | char separador = '-'; 246 | 247 | estados_motores[0] = estado_motor_direito; 248 | estados_motores[1] = separador; 249 | estados_motores[2] = estado_motor_esquerdo; 250 | estados_motores[3] = '\0'; 251 | 252 | MQTT.publish(TOPICO_PUB, estados_motores); 253 | Serial.print("- Estados dos motores enviados via MQTT ("); 254 | Serial.print(estados_motores); 255 | Serial.println(")"); 256 | delay(1000); 257 | } 258 | 259 | /* Função: inicializa os outputs em nível lógico baixo (desliga os dois motores) 260 | Parâmetros: nenhum 261 | Retorno: nenhum 262 | */ 263 | void init_outputs(void) 264 | { 265 | pinMode(MOTOR_DIRETO, OUTPUT); 266 | pinMode(MOTOR_ESQUERDO, OUTPUT); 267 | 268 | digitalWrite(MOTOR_DIRETO, LOW); 269 | digitalWrite(MOTOR_ESQUERDO, LOW); 270 | } 271 | 272 | /* 273 | * Programa principal 274 | */ 275 | void loop() 276 | { 277 | /* 278 | Ações a serem leitas no loop principak: 279 | - garante funcionamento das conexões WiFi e ao broker MQTT 280 | - envia o status de todos os outputs para o Broker 281 | - envia keep-alive da comunicação com broker MQTT 282 | */ 283 | 284 | verifica_conexoes_wifi_e_MQTT(); 285 | envia_estado_output_MQTT(); 286 | MQTT.loop(); 287 | } 288 | -------------------------------------------------------------------------------- /Exemplos/Cap6/rover_esp32_L298N.ino: -------------------------------------------------------------------------------- 1 | /* Programa: código-fonte do robô tipo rover (controle e acionamento de motores 2 | com amplificador e ponte H L298N 3 | Descrição: código-fonte do robô tipo rover, controlado por Internet via MQTT. 4 | Sua movimentação é feita conforme a recepção de caracteres via MQTT: 5 | F: rover se move para frente 6 | D: rover se move para a direita 7 | E: rover se move para a esquerda 8 | R: rover se move para trás 9 | P: o rover para (os motores são desacionados) 10 | Autor: Pedro Bertoleti 11 | */ 12 | 13 | /* includes */ 14 | #include 15 | #include 16 | 17 | /* defines gerais */ 18 | #define BAUDRATE_SERIAL_DEBUG 115200 19 | 20 | /* defines de id mqtt e tópicos para publicação e subscribe */ 21 | #define TOPICO_SUB "MQTTRoverEnvia" /* tópico MQTT de escuta */ 22 | #define TOPICO_PUB "MQTTRoverRecebe" /* tópico MQTT de envio de informações para Broker */ 23 | #define ID_MQTT "RoboRoverINCB" /* id mqtt (para identificação de sessão) */ 24 | /* IMPORTANTE: este deve ser único no broker (ou seja, 25 | se um client MQTT tentar entrar com o mesmo 26 | id de outro já conectado ao broker, o broker 27 | irá fechar a conexão de um deles). 28 | */ 29 | 30 | /* defines - controle do L298N */ 31 | #define IN1 13 /* GPIO 13 */ 32 | #define IN2 12 /* GPIO 12 */ 33 | #define IN3 25 /* GPIO 25 */ 34 | #define IN4 17 /* GPIO 17 */ 35 | 36 | /* defines - movimentacao */ 37 | #define CARACTER_MOVE_FRENTE "F" 38 | #define CARACTER_MOVE_DIREITA "D" 39 | #define CARACTER_MOVE_ESQUERDA "E" 40 | #define CARACTER_MOVE_TRAS "R" 41 | #define CARACTER_PARA_ROVER "P" 42 | 43 | 44 | /* Variáveis e objetos globais: */ 45 | /* WIFI */ 46 | const char* SSID_WIFI = " "; /* Coloque aqui o SSID_WIFI / nome da rede WI-FI que deseja se conectar */ 47 | const char* PASSWORD_WIFI = " "; /* Coloque aqui a senha da rede WI-FI que deseja se conectar */ 48 | 49 | /* MQTT */ 50 | const char* BROKER_MQTT = "iot.eclipse.org"; /* URL do broker MQTT que se deseja utilizar */ 51 | int BROKER_PORT = 1883; /* Porta do Broker MQTT */ 52 | 53 | /* Variáveis e objetos globais */ 54 | WiFiClient espClient; /* cria o objeto espClient */ 55 | PubSubClient MQTT(espClient); /* objeto PubSubClient */ 56 | char sentido_motor_direito = 'P'; /* sentido de rotação atual do motor da direita */ 57 | char sentido_motor_esquerdo = 'P'; /* sentido de rotação atual do motor da esquerda */ 58 | 59 | /* Prototypes */ 60 | void init_serial_debug(void); 61 | void init_wifi(void); 62 | void init_MQTT(void); 63 | void connect_wifi(void); 64 | void init_outputs(void); 65 | void mqtt_callback(char* topic, byte* payload, unsigned int length); 66 | void verifica_conexoes_wifi_e_MQTT(void); 67 | void envia_estado_output_MQTT(void); 68 | 69 | /* 70 | * Implementações das funções 71 | */ 72 | void setup() 73 | { 74 | //Faz as inicializações necessárias 75 | init_outputs(); 76 | init_serial_debug(); 77 | init_wifi(); 78 | init_MQTT(); 79 | } 80 | 81 | /* Função: inicializa comunicação serial com baudrate 115200 (para fins de monitorar no terminal serial 82 | o que está acontecendo. 83 | Parâmetros: nenhum 84 | Retorno: nenhum 85 | */ 86 | void init_serial_debug(void) 87 | { 88 | Serial.begin(BAUDRATE_SERIAL_DEBUG); 89 | } 90 | 91 | /* Função: inicializa e conecta-se na rede WI-FI desejada 92 | Parâmetros: nenhum 93 | Retorno: nenhum 94 | */ 95 | void init_wifi(void) 96 | { 97 | delay(10); 98 | Serial.println("------Conexao WI-FI -----"); 99 | Serial.print("Conectando-se na rede: "); 100 | Serial.println(SSID_WIFI); 101 | Serial.println("Aguarde"); 102 | 103 | connect_wifi(); 104 | } 105 | 106 | /* Função: inicializa parâmetros de conexão MQTT(endereço do 107 | broker, porta e seta função de callback) 108 | Parâmetros: nenhum 109 | Retorno: nenhum 110 | */ 111 | void init_MQTT(void) 112 | { 113 | MQTT.setServer(BROKER_MQTT, BROKER_PORT); //informa qual broker e porta deve ser conectado 114 | MQTT.setCallback(mqtt_callback); //atribui função de callback (função chamada quando qualquer informação de um dos tópicos subescritos chega) 115 | } 116 | 117 | /* Função: função de callback 118 | esta função é chamada toda vez que uma informação de 119 | um dos tópicos subescritos chega) 120 | Parâmetros: nenhum 121 | Retorno: nenhum 122 | */ 123 | void mqtt_callback(char* topic, byte* payload, unsigned int length) 124 | { 125 | String msg; 126 | int i; 127 | 128 | /* obtem a string do payload recebido */ 129 | for(i = 0; i < length; i++) 130 | { 131 | char c = (char)payload[i]; 132 | msg += c; 133 | } 134 | 135 | /* toma ação dependendo da string recebida: */ 136 | if (msg.equals(CARACTER_MOVE_FRENTE)) 137 | { 138 | /* para ir para frente, os dois motores são ligados em sentido horário */ 139 | digitalWrite(IN1, HIGH); 140 | digitalWrite(IN2, LOW); 141 | digitalWrite(IN3, HIGH); 142 | digitalWrite(IN4, LOW); 143 | 144 | sentido_motor_direito = 'H'; 145 | sentido_motor_esquerdo = 'H'; 146 | } 147 | 148 | if (msg.equals(CARACTER_MOVE_TRAS)) 149 | { 150 | /* para ir para trás, os dois motores são ligados em sentido anti-horário */ 151 | digitalWrite(IN1, LOW); 152 | digitalWrite(IN2, HIGH); 153 | digitalWrite(IN3, LOW); 154 | digitalWrite(IN4, HIGH); 155 | 156 | sentido_motor_direito = 'A'; 157 | sentido_motor_esquerdo = 'A'; 158 | } 159 | 160 | if (msg.equals(CARACTER_MOVE_DIREITA)) 161 | { 162 | /* para ir para a direita,o motor da direita move-se em sentido anti-horário e 163 | o motor da esquerda em sentido horário */ 164 | digitalWrite(IN1, LOW); 165 | digitalWrite(IN2, HIGH); 166 | digitalWrite(IN3, HIGH); 167 | digitalWrite(IN4, LOW); 168 | 169 | sentido_motor_direito = 'A'; 170 | sentido_motor_esquerdo = 'H'; 171 | } 172 | 173 | if (msg.equals(CARACTER_MOVE_ESQUERDA)) 174 | { 175 | /* para ir para a direita,o motor da direita move-se em sentido horário e 176 | o motor da esquerda em sentido anti-horário */ 177 | digitalWrite(IN1, HIGH); 178 | digitalWrite(IN2, LOW); 179 | digitalWrite(IN3, LOW); 180 | digitalWrite(IN4, HIGH); 181 | 182 | sentido_motor_direito = 'H'; 183 | sentido_motor_esquerdo = 'A'; 184 | } 185 | 186 | if (msg.equals(CARACTER_PARA_ROVER)) 187 | { 188 | /* para parar, os dois motores são desligados */ 189 | digitalWrite(IN1, HIGH); 190 | digitalWrite(IN2, HIGH); 191 | digitalWrite(IN3, HIGH); 192 | digitalWrite(IN4, HIGH); 193 | 194 | sentido_motor_direito = 'P'; 195 | sentido_motor_esquerdo = 'P'; 196 | } 197 | } 198 | 199 | /* Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair) 200 | em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito. 201 | Parâmetros: nenhum 202 | Retorno: nenhum 203 | */ 204 | void reconnectMQTT() 205 | { 206 | while (!MQTT.connected()) 207 | { 208 | Serial.print("* Tentando se conectar ao Broker MQTT: "); 209 | Serial.println(BROKER_MQTT); 210 | if (MQTT.connect(ID_MQTT)) 211 | { 212 | Serial.println("Conectado com sucesso ao broker MQTT!"); 213 | MQTT.subscribe(TOPICO_SUB); 214 | } 215 | else 216 | { 217 | Serial.println("Falha ao reconectar no broker."); 218 | Serial.println("Havera nova tentatica de conexao em 2s"); 219 | delay(2000); 220 | } 221 | } 222 | } 223 | 224 | /* Função: reconecta-se ao WiFi 225 | Parâmetros: nenhum 226 | Retorno: nenhum 227 | */ 228 | void connect_wifi(void) 229 | { 230 | /* se já está conectado a rede WI-FI, nada é feito. 231 | Caso contrário, são efetuadas tentativas de conexão 232 | */ 233 | if (WiFi.status() == WL_CONNECTED) 234 | return; 235 | 236 | WiFi.begin(SSID_WIFI, PASSWORD_WIFI); // Conecta na rede WI-FI 237 | 238 | while (WiFi.status() != WL_CONNECTED) 239 | { 240 | delay(100); 241 | Serial.print("."); 242 | } 243 | 244 | Serial.println(); 245 | Serial.print("Conectado com sucesso na rede "); 246 | Serial.print(SSID_WIFI); 247 | Serial.println("IP obtido: "); 248 | Serial.println(WiFi.localIP()); 249 | } 250 | 251 | /* Função: verifica o estado das conexões WiFI e ao broker MQTT. 252 | Em caso de desconexão (qualquer uma das duas), a conexão 253 | é refeita. 254 | Parâmetros: nenhum 255 | Retorno: nenhum 256 | */ 257 | void verifica_conexoes_wifi_e_MQTT(void) 258 | { 259 | if (!MQTT.connected()) 260 | reconnectMQTT(); //se não há conexão com o Broker, a conexão é refeita 261 | 262 | connect_wifi(); //se não há conexão com o WiFI, a conexão é refeita 263 | } 264 | 265 | /* Função: envia ao Broker o estado atual do output 266 | Parâmetros: nenhum 267 | Retorno: nenhum 268 | */ 269 | void envia_estado_output_MQTT(void) 270 | { 271 | char estados_motores[4]; 272 | char separador = '-'; 273 | 274 | estados_motores[0] = sentido_motor_direito; 275 | estados_motores[1] = separador; 276 | estados_motores[2] = sentido_motor_esquerdo; 277 | estados_motores[3] = '\0'; 278 | 279 | MQTT.publish(TOPICO_PUB, estados_motores); 280 | Serial.print("- Estados dos motores enviados via MQTT ("); 281 | Serial.print(estados_motores); 282 | Serial.println(")"); 283 | delay(1000); 284 | } 285 | 286 | /* Função: inicializa os outputs de controle dos motores 287 | Parâmetros: nenhum 288 | Retorno: nenhum 289 | */ 290 | void init_outputs(void) 291 | { 292 | pinMode(IN1, OUTPUT); 293 | pinMode(IN2, OUTPUT); 294 | pinMode(IN3, OUTPUT); 295 | pinMode(IN4, OUTPUT); 296 | 297 | /* Configura controles para que o robô fique parado (ambos os motores parados) */ 298 | digitalWrite(IN1, HIGH); 299 | digitalWrite(IN2, HIGH); 300 | digitalWrite(IN3, HIGH); 301 | digitalWrite(IN4, HIGH); 302 | } 303 | 304 | /* 305 | * Programa principal 306 | */ 307 | void loop() 308 | { 309 | /* 310 | Ações a serem leitas no loop principak: 311 | - garante funcionamento das conexões WiFi e ao broker MQTT 312 | - envia o status de todos os outputs para o Broker 313 | - envia keep-alive da comunicação com broker MQTT 314 | */ 315 | 316 | verifica_conexoes_wifi_e_MQTT(); 317 | envia_estado_output_MQTT(); 318 | MQTT.loop(); 319 | } 320 | 321 | -------------------------------------------------------------------------------- /Exemplos/Cap5/leitura_temp_umid_mqtt.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Projeto: medição local e via mqtt de temperatura e umidade 3 | * Autor: Pedro Bertoleti 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | * Defines do projeto 14 | */ 15 | /* GPIO do módulo WiFi LoRa 32(V2) que o pino de comunicação do sensor está ligado. */ 16 | #define DHTPIN 13 /* (GPIO 13) */ 17 | 18 | /* Endereço I2C do display */ 19 | #define OLED_ADDR 0x3c 20 | 21 | /* distancia, em pixels, de cada linha em relacao ao topo do display */ 22 | #define OLED_LINE1 0 23 | #define OLED_LINE2 10 24 | #define OLED_LINE3 20 25 | #define OLED_LINE4 30 26 | #define OLED_LINE5 40 27 | #define OLED_LINE6 50 28 | 29 | /* Configuração da resolucao do display (este modulo possui display 128x64) */ 30 | #define SCREEN_WIDTH 128 31 | #define SCREEN_HEIGHT 64 32 | 33 | /* 34 | A biblioteca serve para os sensores DHT11, DHT22 e DHT21. 35 | No nosso caso, usaremos o DHT22, porém se você desejar utilizar 36 | algum dos outros disponíveis, basta descomentar a linha correspondente. 37 | */ 38 | //#define DHTTYPE DHT11 // DHT 11 39 | #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 40 | //#define DHTTYPE DHT21 // DHT 21 (AM2301) 41 | 42 | /* defines de id mqtt e tópicos para publicação e subscribe */ 43 | #define TOPICO_PUBLISH "MQTTINCBTempUmid" /*tópico MQTT de envio de informações para Broker 44 | IMPORTANTE: recomenda-se fortemente alterar os nomes 45 | desses tópicos. Caso contrário, há grandes 46 | chances de você controlar e monitorar o módulo 47 | de outra pessoa (pois o broker utilizado contém 48 | dispositivos do mundo todo). Altere-o para algo 49 | o mais único possível para você. */ 50 | 51 | #define ID_MQTT "INCBTempUmid" /* id mqtt (para identificação de sessão) 52 | IMPORTANTE: este deve ser único no broker (ou seja, 53 | se um client MQTT tentar entrar com o mesmo 54 | id de outro já conectado ao broker, o broker 55 | irá fechar a conexão de um deles). Pelo fato 56 | do broker utilizado conter dispositivos do mundo 57 | todo, recomenda-se fortemente que seja alterado 58 | para algo o mais único possível para você.*/ 59 | 60 | 61 | /* Constantes */ 62 | const char* SSID = " "; // coloque aqui o SSID / nome da rede WI-FI que deseja se conectar 63 | const char* PASSWORD = " "; // coloque aqui a senha da rede WI-FI que deseja se conectar 64 | 65 | const char* BROKER_MQTT = "iot.eclipse.org"; //URL do broker MQTT que se deseja utilizar 66 | int BROKER_PORT = 1883; // Porta do Broker MQTT 67 | 68 | /* Variáveis e objetos globais*/ 69 | WiFiClient espClient; // Cria o objeto espClient 70 | PubSubClient MQTT(espClient); // Instancia o Cliente MQTT passando o objeto espClient 71 | 72 | 73 | /* 74 | * Variáveis e objetos globais 75 | */ 76 | /* objeto para comunicação com sensor DHT22 */ 77 | DHT dht(DHTPIN, DHTTYPE); 78 | 79 | /* objeto do display */ 80 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 16); 81 | 82 | /* variáveis que armazenam os valores máximo e mínimo de temperatura registrados. */ 83 | float temperatura_max; 84 | float temperatura_min; 85 | 86 | /* prototypes */ 87 | void atualiza_temperatura_max_e_minima(float temp_lida); 88 | void envia_medicoes_para_serial(float temp_lida, float umid_lida); 89 | void escreve_temperatura_umidade_display(float temp_lida, float umid_lida); 90 | void init_wifi(void); 91 | void init_MQTT(void); 92 | void reconnect_wifi(void); 93 | void reconnect_MQTT(void); 94 | void verifica_conexoes_wifi_e_MQTT(void); 95 | void envia_informacoes_por_mqtt(float temp_lida, float umid_lida); 96 | 97 | /* 98 | * Implementações 99 | */ 100 | 101 | /* Função: inicializa e conecta-se na rede WI-FI desejada 102 | * Parâmetros: nenhum 103 | *Retorno: nenhum 104 | */ 105 | void init_wifi(void) 106 | { 107 | delay(10); 108 | Serial.println("------Conexao WI-FI------"); 109 | Serial.print("Conectando-se na rede: "); 110 | Serial.println(SSID); 111 | Serial.println("Aguarde"); 112 | reconnect_wifi(); 113 | } 114 | 115 | /* Função: inicializa parâmetros de conexão MQTT(endereço do broker e porta) 116 | * Parâmetros: nenhum 117 | * Retorno: nenhum 118 | */ 119 | void init_MQTT(void) 120 | { 121 | //informa qual broker e porta deve ser conectado 122 | MQTT.setServer(BROKER_MQTT, BROKER_PORT); 123 | } 124 | 125 | /* Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair) 126 | * em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito. 127 | * Parâmetros: nenhum 128 | * Retorno: nenhum 129 | */ 130 | void reconnect_MQTT(void) 131 | { 132 | while (!MQTT.connected()) 133 | { 134 | Serial.print("* Tentando se conectar ao Broker MQTT: "); 135 | Serial.println(BROKER_MQTT); 136 | if (MQTT.connect(ID_MQTT)) 137 | Serial.println("Conectado com sucesso ao broker MQTT!"); 138 | else 139 | { 140 | Serial.println("Falha ao reconectar no broker."); 141 | Serial.println("Havera nova tentatica de conexao em 2s"); 142 | delay(2000); 143 | } 144 | } 145 | } 146 | 147 | /* Função: reconecta-se ao WiFi 148 | * Parâmetros: nenhum 149 | * Retorno: nenhum 150 | */ 151 | void reconnect_wifi(void) 152 | { 153 | /* se já está conectado a rede WI-FI, nada é feito. 154 | Caso contrário, são efetuadas tentativas de conexão */ 155 | if (WiFi.status() == WL_CONNECTED) 156 | return; 157 | 158 | WiFi.begin(SSID, PASSWORD); // Conecta na rede WI-FI 159 | 160 | while (WiFi.status() != WL_CONNECTED) 161 | { 162 | delay(100); 163 | Serial.print("."); 164 | } 165 | 166 | Serial.println(); 167 | Serial.print("Conectado com sucesso na rede "); 168 | Serial.print(SSID); 169 | Serial.println("IP obtido: "); 170 | Serial.println(WiFi.localIP()); 171 | } 172 | 173 | /* Função: verifica o estado das conexões WiFI e ao broker MQTT. 174 | * Em caso de desconexão (qualquer uma das duas), a conexão 175 | * é refeita. 176 | * Parâmetros: nenhum 177 | * Retorno: nenhum 178 | */ 179 | void verifica_conexoes_wifi_e_MQTT(void) 180 | { 181 | /* se não há conexão com o WiFI, a conexão é refeita */ 182 | reconnect_wifi(); 183 | 184 | /* se não há conexão com o Broker, a conexão é refeita */ 185 | if (!MQTT.connected()) 186 | reconnect_MQTT(); 187 | } 188 | 189 | 190 | /* Função: verifica se os valores de temperatura máxima e mínima devem ser atualizados 191 | * Parâmetros: temperatura lida 192 | * Retorno: nenhum 193 | */ 194 | void atualiza_temperatura_max_e_minima(float temp_lida) 195 | { 196 | if (temp_lida > temperatura_max) 197 | temperatura_max = temp_lida; 198 | 199 | if (temp_lida < temperatura_min) 200 | temperatura_min = temp_lida; 201 | } 202 | 203 | /* Função: envia, na forma de mensagens textuais, as medições para a serial 204 | * Parâmetros: - Temperatura lida 205 | * - Umidade relativa do ar lida 206 | * - Máxima temperatura registrada 207 | * - Mínima temperatura registrada 208 | * Retorno: nenhum 209 | */ 210 | void envia_medicoes_para_serial(float temp_lida, float umid_lida) 211 | { 212 | char mensagem[200]; 213 | char i; 214 | 215 | /* pula 80 linhas, de forma que no monitor serial seja exibida somente as mensagens atuais (impressao de refresh de tela) */ 216 | for(i=0; i<80; i++) 217 | Serial.println(" "); 218 | 219 | /* constrói mensagens e as envia */ 220 | /* - temperatura atual */ 221 | memset(mensagem,0,sizeof(mensagem)); 222 | sprintf(mensagem,"- Temperatura: %.2f C", temp_lida); 223 | Serial.println(mensagem); 224 | 225 | //- umidade relativa do ar atual 226 | memset(mensagem,0,sizeof(mensagem)); 227 | sprintf(mensagem,"- Umidade atual: %.2f/100",umid_lida); 228 | Serial.println(mensagem); 229 | 230 | //- temperatura maxima 231 | memset(mensagem,0,sizeof(mensagem)); 232 | sprintf(mensagem,"- Temperatura maxima: %.2f C", temperatura_max); 233 | Serial.println(mensagem); 234 | 235 | //- temperatura minima 236 | memset(mensagem,0,sizeof(mensagem)); 237 | sprintf(mensagem,"- Temperatura minima: %.2f C", temperatura_min); 238 | Serial.println(mensagem); 239 | } 240 | 241 | /* Função: escreve no display OLED a temperatura e umidade lidas, assim como as temperaturas máxima e mínima 242 | * Parâmetros: - Temperatura lida 243 | * - Umidade relativa do ar lida 244 | * Retorno: nenhum 245 | */ 246 | void escreve_temperatura_umidade_display(float temp_lida, float umid_lida) 247 | { 248 | char str_temp[10] = {0}; 249 | char str_umid[10] = {0}; 250 | char str_temp_max_min[20] = {0}; 251 | 252 | /* formata para o display as strings de temperatura e umidade */ 253 | sprintf(str_temp, "%.2fC", temp_lida); 254 | sprintf(str_umid, "%.2f/100", umid_lida); 255 | sprintf(str_temp_max_min, "%.2fC / %.2fC", temperatura_min, temperatura_max); 256 | 257 | display.clearDisplay(); 258 | display.setCursor(0, OLED_LINE1); 259 | display.println("Temperatura:"); 260 | display.setCursor(0, OLED_LINE2); 261 | display.println(str_temp); 262 | display.setCursor(0, OLED_LINE3); 263 | display.println("Umidade:"); 264 | display.setCursor(0, OLED_LINE4); 265 | display.print(str_umid); 266 | display.setCursor(0, OLED_LINE5); 267 | display.println("Temp. min / max:"); 268 | display.setCursor(0, OLED_LINE6); 269 | display.print(str_temp_max_min); 270 | display.display(); 271 | } 272 | 273 | /* 274 | * Função: envia por MQTT as informações de temperatura e umidade lidas, assim como as temperaturas máxima e mínima 275 | * Parâmetros: - Temperatura lida 276 | * - Umidade relativa do ar lida 277 | * Retorno: nenhum 278 | */ 279 | void envia_informacoes_por_mqtt(float temp_lida, float umid_lida) 280 | { 281 | char mensagem_MQTT[200] = {0}; 282 | 283 | //constrói mensagens e as envia 284 | //- temperatura atual 285 | sprintf(mensagem_MQTT,"Temperatura: %.2f C, Umidade atual: %.2f/100, Temperatura maxima: %.2f C, Temperatura minima: %.2f C", temp_lida, 286 | umid_lida, 287 | temperatura_max, 288 | temperatura_min); 289 | 290 | MQTT.publish(TOPICO_PUBLISH, mensagem_MQTT); 291 | 292 | } 293 | 294 | void setup() { 295 | /* configura comunicação serial (para enviar mensgens com as medições) 296 | e inicializa comunicação com o sensor. 297 | */ 298 | Serial.begin(115200); 299 | dht.begin(); 300 | 301 | /* inicializa temperaturas máxima e mínima com a leitura inicial do sensor */ 302 | temperatura_max = dht.readTemperature(); 303 | temperatura_min = temperatura_max; 304 | 305 | /* inicializa display OLED */ 306 | Wire.begin(4, 15); 307 | 308 | if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) 309 | Serial.println("Display OLED: falha ao inicializar"); 310 | else 311 | { 312 | Serial.println("Display OLED: inicializacao ok"); 313 | 314 | /* Limpa display e configura tamanho de fonte */ 315 | display.clearDisplay(); 316 | display.setTextSize(1); 317 | display.setTextColor(WHITE); 318 | } 319 | 320 | /* inicializações do WI-FI e MQTT */ 321 | init_wifi(); 322 | init_MQTT(); 323 | } 324 | 325 | /* 326 | * Programa principal 327 | */ 328 | void loop() { 329 | float temperatura_lida; 330 | float umidade_lida; 331 | 332 | /* Verifica se as conexões MQTT e wi-fi estão ativas 333 | Se alguma delas não estiver ativa, a reconexão é feita */ 334 | verifica_conexoes_wifi_e_MQTT(); 335 | 336 | /* Faz a leitura de temperatura e umidade do sensor */ 337 | temperatura_lida = dht.readTemperature(); 338 | umidade_lida = dht.readHumidity(); 339 | 340 | /* se houve falha na leitura do sensor, escreve mensagem de erro na serial */ 341 | if ( isnan(temperatura_lida) || isnan(umidade_lida) ) 342 | Serial.println("Erro ao ler sensor DHT22!"); 343 | else 344 | { 345 | /*Se a leitura foi bem sucedida, ocorre o seguinte: 346 | - Os valores mínimos e máximos são verificados e comparados à medição atual de temperatura 347 | se a temperatura atual for menor que a mínima ou maior que a máxima até então 348 | registrada, os limites máximo ou mínimo são atualizados. 349 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 350 | enviados pela serial na forma de mensagem textual. Tais mensagens podem ser vistas 351 | no monitor serial. 352 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 353 | escritas no display OLED 354 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 355 | enviadas por MQTT 356 | */ 357 | atualiza_temperatura_max_e_minima(temperatura_lida); 358 | envia_medicoes_para_serial(temperatura_lida, umidade_lida); 359 | escreve_temperatura_umidade_display(temperatura_lida, umidade_lida); 360 | envia_informacoes_por_mqtt(temperatura_lida, umidade_lida); 361 | } 362 | 363 | /* Faz o keep-alive do MQTT */ 364 | MQTT.loop(); 365 | 366 | /* espera cinco segundos até a próxima leitura */ 367 | delay(5000); 368 | } 369 | 370 | -------------------------------------------------------------------------------- /Exemplos/Cap5/leitura_temp_umid_mqtt_lora_emissor.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Projeto: emissor- medição local, via LoRa e via mqtt de temperatura e umidade 3 | * Autor: Pedro Bertoleti 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* 15 | * Defines do projeto 16 | */ 17 | /* GPIO do módulo WiFi LoRa 32(V2) que o pino de comunicação do sensor está ligado. */ 18 | #define DHTPIN 13 /* (GPIO 13) */ 19 | 20 | /* Endereço I2C do display */ 21 | #define OLED_ADDR 0x3c 22 | 23 | /* distancia, em pixels, de cada linha em relacao ao topo do display */ 24 | #define OLED_LINE1 0 25 | #define OLED_LINE2 10 26 | #define OLED_LINE3 20 27 | #define OLED_LINE4 30 28 | #define OLED_LINE5 40 29 | #define OLED_LINE6 50 30 | 31 | /* Configuração da resolucao do display (este modulo possui display 128x64) */ 32 | #define SCREEN_WIDTH 128 33 | #define SCREEN_HEIGHT 64 34 | 35 | /* 36 | A biblioteca serve para os sensores DHT11, DHT22 e DHT21. 37 | No nosso caso, usaremos o DHT22, porém se você desejar utilizar 38 | algum dos outros disponíveis, basta descomentar a linha correspondente. 39 | */ 40 | //#define DHTTYPE DHT11 // DHT 11 41 | #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 42 | //#define DHTTYPE DHT21 // DHT 21 (AM2301) 43 | 44 | /* defines de id mqtt e tópicos para publicação e subscribe */ 45 | #define TOPICO_PUBLISH "MQTTINCBTempUmid" /*tópico MQTT de envio de informações para Broker 46 | IMPORTANTE: recomenda-se fortemente alterar os nomes 47 | desses tópicos. Caso contrário, há grandes 48 | chances de você controlar e monitorar o módulo 49 | de outra pessoa (pois o broker utilizado contém 50 | dispositivos do mundo todo). Altere-o para algo 51 | o mais único possível para você. */ 52 | 53 | #define ID_MQTT "INCBTempUmid" /* id mqtt (para identificação de sessão) 54 | IMPORTANTE: este deve ser único no broker (ou seja, 55 | se um client MQTT tentar entrar com o mesmo 56 | id de outro já conectado ao broker, o broker 57 | irá fechar a conexão de um deles). Pelo fato 58 | do broker utilizado conter dispositivos do mundo 59 | todo, recomenda-se fortemente que seja alterado 60 | para algo o mais único possível para você.*/ 61 | 62 | /* Definicoes para comunicação com radio LoRa */ 63 | #define SCK_LORA 5 64 | #define MISO_LORA 19 65 | #define MOSI_LORA 27 66 | #define RESET_PIN_LORA 14 67 | #define SS_PIN_LORA 18 68 | 69 | #define HIGH_GAIN_LORA 20 /* dBm */ 70 | #define BAND 915E6 /* 915MHz de frequencia */ 71 | 72 | /* Constantes */ 73 | const char* SSID = " "; // coloque aqui o SSID / nome da rede WI-FI que deseja se conectar 74 | const char* PASSWORD = " "; // coloque aqui a senha da rede WI-FI que deseja se conectar 75 | 76 | const char* BROKER_MQTT = "iot.eclipse.org"; //URL do broker MQTT que se deseja utilizar 77 | int BROKER_PORT = 1883; // Porta do Broker MQTT 78 | 79 | /* Variáveis e objetos globais*/ 80 | WiFiClient espClient; // Cria o objeto espClient 81 | PubSubClient MQTT(espClient); // Instancia o Cliente MQTT passando o objeto espClient 82 | 83 | 84 | /* 85 | * Variáveis e objetos globais 86 | */ 87 | /* objeto para comunicação com sensor DHT22 */ 88 | DHT dht(DHTPIN, DHTTYPE); 89 | 90 | /* objeto do display */ 91 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 16); 92 | 93 | /* variáveis que armazenam os valores máximo e mínimo de temperatura registrados. */ 94 | float temperatura_max; 95 | float temperatura_min; 96 | 97 | /* typedefs */ 98 | typedef struct __attribute__((__packed__)) 99 | { 100 | float temperatura; 101 | float umidade; 102 | float temperatura_min; 103 | float temperatura_max; 104 | }TDadosLora; 105 | 106 | /* prototypes */ 107 | void atualiza_temperatura_max_e_minima(float temp_lida); 108 | void escreve_temperatura_umidade_display(float temp_lida, float umid_lida); 109 | void envia_medicoes_para_serial(float temp_lida, float umid_lida); 110 | void envia_informacoes_por_mqtt(float temp_lida, float umid_lida); 111 | void envia_informacoes_lora(float temp_lida, float umid_lida); 112 | void init_wifi(void); 113 | void init_MQTT(void); 114 | void reconnect_wifi(void); 115 | void reconnect_MQTT(void); 116 | void verifica_conexoes_wifi_e_MQTT(void); 117 | bool init_comunicacao_lora(void); 118 | 119 | /* 120 | * Implementações 121 | */ 122 | 123 | /* Função: inicializa e conecta-se na rede WI-FI desejada 124 | * Parâmetros: nenhum 125 | *Retorno: nenhum 126 | */ 127 | void init_wifi(void) 128 | { 129 | delay(10); 130 | Serial.println("------Conexao WI-FI------"); 131 | Serial.print("Conectando-se na rede: "); 132 | Serial.println(SSID); 133 | Serial.println("Aguarde"); 134 | reconnect_wifi(); 135 | } 136 | 137 | /* Função: inicializa parâmetros de conexão MQTT(endereço do broker e porta) 138 | * Parâmetros: nenhum 139 | * Retorno: nenhum 140 | */ 141 | void init_MQTT(void) 142 | { 143 | //informa qual broker e porta deve ser conectado 144 | MQTT.setServer(BROKER_MQTT, BROKER_PORT); 145 | } 146 | 147 | /* Função: reconecta-se ao broker MQTT (caso ainda não esteja conectado ou em caso de a conexão cair) 148 | * em caso de sucesso na conexão ou reconexão, o subscribe dos tópicos é refeito. 149 | * Parâmetros: nenhum 150 | * Retorno: nenhum 151 | */ 152 | void reconnect_MQTT(void) 153 | { 154 | while (!MQTT.connected()) 155 | { 156 | Serial.print("* Tentando se conectar ao Broker MQTT: "); 157 | Serial.println(BROKER_MQTT); 158 | if (MQTT.connect(ID_MQTT)) 159 | Serial.println("Conectado com sucesso ao broker MQTT!"); 160 | else 161 | { 162 | Serial.println("Falha ao reconectar no broker."); 163 | Serial.println("Havera nova tentatica de conexao em 2s"); 164 | delay(2000); 165 | } 166 | } 167 | } 168 | 169 | /* Função: reconecta-se ao WiFi 170 | * Parâmetros: nenhum 171 | * Retorno: nenhum 172 | */ 173 | void reconnect_wifi(void) 174 | { 175 | /* se já está conectado a rede WI-FI, nada é feito. 176 | Caso contrário, são efetuadas tentativas de conexão */ 177 | if (WiFi.status() == WL_CONNECTED) 178 | return; 179 | 180 | WiFi.begin(SSID, PASSWORD); // Conecta na rede WI-FI 181 | 182 | while (WiFi.status() != WL_CONNECTED) 183 | { 184 | delay(100); 185 | Serial.print("."); 186 | } 187 | 188 | Serial.println(); 189 | Serial.print("Conectado com sucesso na rede "); 190 | Serial.print(SSID); 191 | Serial.println("IP obtido: "); 192 | Serial.println(WiFi.localIP()); 193 | } 194 | 195 | /* Função: verifica o estado das conexões WiFI e ao broker MQTT. 196 | * Em caso de desconexão (qualquer uma das duas), a conexão 197 | * é refeita. 198 | * Parâmetros: nenhum 199 | * Retorno: nenhum 200 | */ 201 | void verifica_conexoes_wifi_e_MQTT(void) 202 | { 203 | /* se não há conexão com o WiFI, a conexão é refeita */ 204 | reconnect_wifi(); 205 | 206 | /* se não há conexão com o Broker, a conexão é refeita */ 207 | if (!MQTT.connected()) 208 | reconnect_MQTT(); 209 | } 210 | 211 | 212 | /* Função: verifica se os valores de temperatura máxima e mínima devem ser atualizados 213 | * Parâmetros: temperatura lida 214 | * Retorno: nenhum 215 | */ 216 | void atualiza_temperatura_max_e_minima(float temp_lida) 217 | { 218 | if (temp_lida > temperatura_max) 219 | temperatura_max = temp_lida; 220 | 221 | if (temp_lida < temperatura_min) 222 | temperatura_min = temp_lida; 223 | } 224 | 225 | /* Função: envia, na forma de mensagens textuais, as medições para a serial 226 | * Parâmetros: - Temperatura lida 227 | * - Umidade relativa do ar lida 228 | * - Máxima temperatura registrada 229 | * - Mínima temperatura registrada 230 | * Retorno: nenhum 231 | */ 232 | void envia_medicoes_para_serial(float temp_lida, float umid_lida) 233 | { 234 | char mensagem[200]; 235 | char i; 236 | 237 | /* pula 80 linhas, de forma que no monitor serial seja exibida somente as mensagens atuais (impressao de refresh de tela) */ 238 | for(i=0; i<80; i++) 239 | Serial.println(" "); 240 | 241 | /* constrói mensagens e as envia */ 242 | /* - temperatura atual */ 243 | memset(mensagem,0,sizeof(mensagem)); 244 | sprintf(mensagem,"- Temperatura: %.2f C", temp_lida); 245 | Serial.println(mensagem); 246 | 247 | //- umidade relativa do ar atual 248 | memset(mensagem,0,sizeof(mensagem)); 249 | sprintf(mensagem,"- Umidade atual: %.2f/100",umid_lida); 250 | Serial.println(mensagem); 251 | 252 | //- temperatura maxima 253 | memset(mensagem,0,sizeof(mensagem)); 254 | sprintf(mensagem,"- Temperatura maxima: %.2f C", temperatura_max); 255 | Serial.println(mensagem); 256 | 257 | //- temperatura minima 258 | memset(mensagem,0,sizeof(mensagem)); 259 | sprintf(mensagem,"- Temperatura minima: %.2f C", temperatura_min); 260 | Serial.println(mensagem); 261 | } 262 | 263 | /* Função: escreve no display OLED a temperatura e umidade lidas, assim como as temperaturas máxima e mínima 264 | * Parâmetros: - Temperatura lida 265 | * - Umidade relativa do ar lida 266 | * Retorno: nenhum 267 | */ 268 | void escreve_temperatura_umidade_display(float temp_lida, float umid_lida) 269 | { 270 | char str_temp[10] = {0}; 271 | char str_umid[10] = {0}; 272 | char str_temp_max_min[20] = {0}; 273 | 274 | /* formata para o display as strings de temperatura e umidade */ 275 | sprintf(str_temp, "%.2fC", temp_lida); 276 | sprintf(str_umid, "%.2f/100", umid_lida); 277 | sprintf(str_temp_max_min, "%.2fC / %.2fC", temperatura_min, temperatura_max); 278 | 279 | display.clearDisplay(); 280 | display.setCursor(0, OLED_LINE1); 281 | display.println("Temperatura:"); 282 | display.setCursor(0, OLED_LINE2); 283 | display.println(str_temp); 284 | display.setCursor(0, OLED_LINE3); 285 | display.println("Umidade:"); 286 | display.setCursor(0, OLED_LINE4); 287 | display.print(str_umid); 288 | display.setCursor(0, OLED_LINE5); 289 | display.println("Temp. min / max:"); 290 | display.setCursor(0, OLED_LINE6); 291 | display.print(str_temp_max_min); 292 | display.display(); 293 | } 294 | 295 | 296 | /* 297 | * Função: envia por MQTT as informações de temperatura e umidade lidas, assim como as temperaturas máxima e mínima 298 | * Parâmetros: - Temperatura lida 299 | * - Umidade relativa do ar lida 300 | * Retorno: nenhum 301 | */ 302 | void envia_informacoes_por_mqtt(float temp_lida, float umid_lida) 303 | { 304 | char mensagem_MQTT[200] = {0}; 305 | 306 | //constrói mensagens e as envia 307 | //- temperatura atual 308 | sprintf(mensagem_MQTT,"Temperatura: %.2f C, Umidade atual: %.2f/100, Temperatura maxima: %.2f C, Temperatura minima: %.2f C", temp_lida, 309 | umid_lida, 310 | temperatura_max, 311 | temperatura_min); 312 | 313 | MQTT.publish(TOPICO_PUBLISH, mensagem_MQTT); 314 | } 315 | 316 | /* 317 | * Função: envia por LoRa as informações de temperatura e umidade lidas, assim como as temperaturas máxima e mínima 318 | * Parâmetros: - Temperatura lida 319 | * - Umidade relativa do ar lida 320 | * Retorno: nenhum 321 | */ 322 | void envia_informacoes_lora(float temp_lida, float umid_lida) 323 | { 324 | TDadosLora dados_lora; 325 | 326 | dados_lora.temperatura = temp_lida; 327 | dados_lora.umidade = umid_lida; 328 | dados_lora.temperatura_min = temperatura_min; 329 | dados_lora.temperatura_max = temperatura_max; 330 | 331 | LoRa.beginPacket(); 332 | LoRa.write((unsigned char *)&dados_lora, sizeof(TDadosLora)); 333 | LoRa.endPacket(); 334 | } 335 | 336 | 337 | /* Funcao: inicia comunicação com chip LoRa 338 | * Parametros: nenhum 339 | * Retorno: true: comunicacao ok 340 | * false: falha na comunicacao 341 | */ 342 | bool init_comunicacao_lora(void) 343 | { 344 | bool status_init = false; 345 | Serial.println("[LoRa Sender] Tentando iniciar comunicacao com o radio LoRa..."); 346 | SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA); 347 | LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN); 348 | 349 | if (!LoRa.begin(BAND)) 350 | { 351 | Serial.println("[LoRa Sender] Comunicacao com o radio LoRa falhou. Nova tentativa em 1 segundo..."); 352 | delay(1000); 353 | status_init = false; 354 | } 355 | else 356 | { 357 | /* Configura o ganho do receptor LoRa para 20dBm, o maior ganho possível (visando maior alcance possível) */ 358 | LoRa.setTxPower(HIGH_GAIN_LORA); 359 | Serial.println("[LoRa Sender] Comunicacao com o radio LoRa ok"); 360 | status_init = true; 361 | } 362 | 363 | return status_init; 364 | } 365 | 366 | void setup() { 367 | /* configura comunicação serial (para enviar mensgens com as medições) 368 | e inicializa comunicação com o sensor. 369 | */ 370 | Serial.begin(115200); 371 | dht.begin(); 372 | 373 | /* inicializa temperaturas máxima e mínima com a leitura inicial do sensor */ 374 | temperatura_max = dht.readTemperature(); 375 | temperatura_min = temperatura_max; 376 | 377 | /* inicializa display OLED */ 378 | Wire.begin(4, 15); 379 | 380 | if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) 381 | Serial.println("Display OLED: falha ao inicializar"); 382 | else 383 | { 384 | Serial.println("Display OLED: inicializacao ok"); 385 | 386 | /* Limpa display e configura tamanho de fonte */ 387 | display.clearDisplay(); 388 | display.setTextSize(1); 389 | display.setTextColor(WHITE); 390 | } 391 | 392 | /* Tenta, até obter sucesso, comunicacao com o chip LoRa */ 393 | while(init_comunicacao_lora() == false); 394 | 395 | /* inicializações do WI-FI e MQTT */ 396 | init_wifi(); 397 | init_MQTT(); 398 | } 399 | 400 | /* 401 | * Programa principal 402 | */ 403 | void loop() { 404 | float temperatura_lida; 405 | float umidade_lida; 406 | 407 | /* Verifica se as conexões MQTT e wi-fi estão ativas 408 | Se alguma delas não estiver ativa, a reconexão é feita */ 409 | verifica_conexoes_wifi_e_MQTT(); 410 | 411 | /* Faz a leitura de temperatura e umidade do sensor */ 412 | temperatura_lida = dht.readTemperature(); 413 | umidade_lida = dht.readHumidity(); 414 | 415 | /* se houve falha na leitura do sensor, escreve mensagem de erro na serial */ 416 | if ( isnan(temperatura_lida) || isnan(umidade_lida) ) 417 | Serial.println("Erro ao ler sensor DHT22!"); 418 | else 419 | { 420 | /*Se a leitura foi bem sucedida, ocorre o seguinte: 421 | - Os valores mínimos e máximos são verificados e comparados à medição atual de temperatura 422 | se a temperatura atual for menor que a mínima ou maior que a máxima até então 423 | registrada, os limites máximo ou mínimo são atualizados. 424 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 425 | enviados pela serial na forma de mensagem textual. Tais mensagens podem ser vistas 426 | no monitor serial. 427 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 428 | escritas no display OLED 429 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 430 | enviadas por MQTT 431 | - As medições (temperatura, umidade, máxima temperatura e mínima temperatura) são 432 | enviadas por LoRa para um módulo receptor 433 | */ 434 | atualiza_temperatura_max_e_minima(temperatura_lida); 435 | envia_medicoes_para_serial(temperatura_lida, umidade_lida); 436 | escreve_temperatura_umidade_display(temperatura_lida, umidade_lida); 437 | envia_informacoes_por_mqtt(temperatura_lida, umidade_lida); 438 | envia_informacoes_lora(temperatura_lida, umidade_lida); 439 | } 440 | 441 | /* Faz o keep-alive do MQTT */ 442 | MQTT.loop(); 443 | 444 | /* espera cinco segundos até a próxima leitura */ 445 | delay(5000); 446 | } 447 | 448 | --------------------------------------------------------------------------------