agrobot_base/Firmware/Sensoriamento/lora/lora.ino

332 lines
8.9 KiB
Arduino
Raw Normal View History

2025-04-30 21:49:17 +00:00
#include <HardwareSerial.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
// Definições de pinos
#define PIN_M0 7
#define PIN_M1 15
#define PIN_AUX 18
// Definições de Serial
HardwareSerial SerialLoRa(2); // UART2 para o E220
HardwareSerial SerialCAN(1); // UART1 simulando o CAN
// Estado atual do módulo
enum LoRaMode { NORMAL, WAKE_UP, POWER_SAVING, CONFIG };
LoRaMode currentMode = NORMAL;
// Prototipagem
bool setLoRaMode(LoRaMode mode);
bool checkLoRaConnected();
void taskBridge(void *pvParameters);
void readParameters();
void saveParameters();
// Config inicial
void setup() {
Serial.begin(115200);
Serial.println("Iniciando ESP32-S3 + E220...");
// Inicializa GPIOs
pinMode(PIN_M0, OUTPUT);
pinMode(PIN_M1, OUTPUT);
pinMode(PIN_AUX, INPUT);
// Inicializa Seriais
SerialLoRa.begin(9600, SERIAL_8N1, 17, 16); // RX=17, TX=16
SerialCAN.begin(115200, SERIAL_8N1, 9, 10); // Simulação CAN (mude os pinos conforme seu setup)
// Coloca o módulo em modo normal
setLoRaMode(NORMAL);
delay(500); // Aguarda estabilização
// Testa conexão
if (checkLoRaConnected()) {
requisitarParametrosLoRa();
Serial.println("LoRa E220 detectado!");
} else {
Serial.println("Erro: LoRa E220 não detectado.");
}
// Cria a task de ponte entre LoRa e CAN
xTaskCreatePinnedToCore(
taskBridge,
"TaskBridge",
4096,
NULL,
1,
NULL,
1
);
}
void loop() {
// Você pode colocar comandos de teste aqui se quiser.
}
// Define o modo do LoRa
bool setLoRaMode(LoRaMode mode) {
// Ajusta os pinos M0 e M1 conforme o modo desejado
switch (mode) {
case NORMAL:
digitalWrite(PIN_M0, LOW);
digitalWrite(PIN_M1, LOW);
break;
case WAKE_UP:
digitalWrite(PIN_M0, HIGH);
digitalWrite(PIN_M1, LOW);
break;
case POWER_SAVING:
digitalWrite(PIN_M0, LOW);
digitalWrite(PIN_M1, HIGH);
break;
case CONFIG:
digitalWrite(PIN_M0, HIGH);
digitalWrite(PIN_M1, HIGH);
break;
}
currentMode = mode;
delay(100); // Aguarda sinalização inicial de troca
// ESPERA o AUX ir para HIGH, indicando que a troca completou
unsigned long timeout = millis() + 1000;
while (digitalRead(PIN_AUX) == LOW) {
if (millis() > timeout) {
Serial.println("Erro: Timeout aguardando AUX após mudança de modo.");
return false;
}
}
delay(100); // Manual pede 2ms após AUX ficar HIGH
return true;
}
// Verifica se o E220 responde
bool checkLoRaConnected() {
if (!setLoRaMode(CONFIG)) {
Serial.println("Falha ao mudar para CONFIG!");
return false;
}
bool conectado = false;
SerialLoRa.write(0xC1);
delay(100);
while (SerialLoRa.available()) {
uint8_t dado = SerialLoRa.read();
if (dado == 0xC1) {
conectado = true;
}
}
setLoRaMode(NORMAL);
return conectado;
}
String comandoRecebido = "";
// Task que faz o espelhamento Serial e interpreta comandos de texto
void taskBridge(void *pvParameters) {
while (true) {
if (Serial.available()) {
char c = (char)Serial.read();
if (c == '\n' || c == '\r') {
// Quando apertar ENTER, processa o comando recebido
if (comandoRecebido.length() > 0) {
if (comandoRecebido == "1") {
Serial.println("Comando: Requisitar parâmetros do LoRa");
requisitarParametrosLoRa();
}
else if (comandoRecebido.startsWith("2") && comandoRecebido.length() == 11) {
// comando: 2 + 10 digitos (2 digitos por byte em hexadecimal)
Serial.println("Comando: Configurar LoRa com novos parâmetros");
// Parseia os números
byte addr = strtol(comandoRecebido.substring(1, 3).c_str(), NULL, 16);
byte baud = strtol(comandoRecebido.substring(3, 5).c_str(), NULL, 16);
byte packet = strtol(comandoRecebido.substring(5, 7).c_str(), NULL, 16);
byte channel = strtol(comandoRecebido.substring(7, 9).c_str(), NULL, 16);
byte worCycle = strtol(comandoRecebido.substring(9, 11).c_str(), NULL, 16);
Serial.print("Addr: "); Serial.println(addr, HEX);
Serial.print("Baud: "); Serial.println(baud, HEX);
Serial.print("Packet: "); Serial.println(packet, HEX);
Serial.print("Channel: "); Serial.println(channel, HEX);
Serial.print("WorCycle: "); Serial.println(worCycle, HEX);
configurarModuloLoRa(addr, baud, packet, channel, worCycle);
}
else {
Serial.println("Comando inválido.");
}
comandoRecebido = ""; // Limpa para próxima leitura
}
}
else {
comandoRecebido += c;
}
}
// Dados recebidos do LoRa -> envia para o CAN normalmente
if (SerialLoRa.available()) {
while (SerialLoRa.available()) {
SerialCAN.write(SerialLoRa.read());
}
}
vTaskDelay(1);
}
}
struct LoRaParametrosModel {
uint8_t address;
uint8_t baudAndAirRate;
uint8_t packetSizeAndPower;
uint8_t channel;
uint8_t tranModeAndWorCycle;
};
// Parâmetros globais
LoRaParametrosModel parametrosAtual;
// Método que monta o comando de configuração
bool configurarModuloLoRa(byte addr, byte baud, byte packet, byte channel, byte worCycle) {
if (!setLoRaMode(CONFIG)) {
Serial.println("Falha ao mudar para CONFIG!");
return false;
}
limparBufferLoRa();
uint8_t command[9] = {
0xC0, // Código para configurar
0x00, // Registro inicial
0x06, // Quantidade de registros
0x00, // Reservado
addr,
baud,
packet,
channel,
worCycle
};
SerialLoRa.write(command, sizeof(command));
Serial.println("Comando de configuração enviado!");
unsigned long startTime = millis();
bool sucesso = false;
while (millis() - startTime < 3000) { // timeout 3 segundos
if (SerialLoRa.available()) {
uint8_t cabecalho = SerialLoRa.read();
if (cabecalho == 0xC1) { // 0xC1 é Resposta de Configuração
sucesso = true;
Serial.println("Confirmação de configuração recebida!");
} else {
Serial.print("Resposta inesperada: 0x");
Serial.println(cabecalho, HEX);
}
break;
}
delay(10);
}
setLoRaMode(NORMAL);
return sucesso;
}
// Método que requisita a leitura dos parâmetros atuais
bool requisitarParametrosLoRa() {
if (!setLoRaMode(CONFIG)) {
Serial.println("Falha ao mudar para CONFIG!");
return false;
}
limparBufferLoRa();
uint8_t command[3] = { 0xC1, 0x00, 0x0B };
SerialLoRa.write(command, sizeof(command));
Serial.println("Comando de requisição enviado!");
unsigned long startTime = millis();
bool sucesso = false;
while (!sucesso && millis() - startTime < 3000) { // timeout 3 segundos
if (SerialLoRa.available()) {
uint8_t cabecalho = SerialLoRa.read();
if (cabecalho == 0xC1) { // Cabeçalho de resposta correta
uint8_t startAddr = SerialLoRa.read(); // Deve ser 0x00
uint8_t dataLen = SerialLoRa.read(); // Deve ser 0x0B
if (startAddr == 0x00 && dataLen == 0x0B) {
Serial.println("Parâmetros recebidos corretamente.");
// Agora ler os registros
parametrosAtual.address = SerialLoRa.read();
parametrosAtual.baudAndAirRate = SerialLoRa.read();
parametrosAtual.packetSizeAndPower = SerialLoRa.read();
parametrosAtual.channel = SerialLoRa.read();
parametrosAtual.tranModeAndWorCycle = SerialLoRa.read();
// Exibe os valores lidos
Serial.println("Parametros lidos do módulo:");
Serial.print("Address: 0x");
Serial.println(parametrosAtual.address, HEX);
Serial.print("Baud and AirRate: 0x");
Serial.println(parametrosAtual.baudAndAirRate, HEX);
Serial.print("Packet Size and Power: 0x");
Serial.println(parametrosAtual.packetSizeAndPower, HEX);
Serial.print("Channel: 0x");
Serial.println(parametrosAtual.channel, HEX);
Serial.print("TranMode and WorCycle: 0x");
Serial.println(parametrosAtual.tranModeAndWorCycle, HEX);
// Ignorar os bytes restantes (Reservados, etc)
for (int i = 0; i < (0x0B - 5); i++) {
SerialLoRa.read();
}
sucesso = true;
}
} else if (cabecalho == 0xFC) {
Serial.println("Modo invalido!");
}
/*else {
Serial.print("Resposta inesperada: 0x");
Serial.println(cabecalho, HEX);
Serial.println("Resposta recebida: ");
while (SerialLoRa.available()) {
uint8_t byteLido = SerialLoRa.read();
Serial.print("0x");
Serial.print(byteLido, HEX);
Serial.print(" ");
}
Serial.println();
}*/
}
delay(10);
}
setLoRaMode(NORMAL);
return sucesso;
}
// Limpa buffer anterior
void limparBufferLoRa() {
while (SerialLoRa.available()) {
SerialLoRa.read();
}
}