summaryrefslogtreecommitdiff
path: root/esp/estacao_principal/NEW.ino
blob: 86aafccf7ede1f2f67e6fff23dca2fb3cca9ed9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
// Bibliotecas originais
#include <Wire.h>
#include <Adafruit_BMP280.h>
#include <BH1750.h>
#include <DHT.h>
#include <WiFi.h>
#include <PubSubClient.h> // Para MQTT
#include <ArduinoJson.h>  // Para o payload
#include <time.h>         // Para o timestamp NTP

//wifi
const char* ssid = "NOME_DA_SUA_REDE_WIFI";
const char* password = "SENHA_DA_SUA_REDE_WIFI";

//MQTT
const char* mqtt_server = "IP_OU_DOMINIO_DO_SEU_BROKER_MQTT"; // Ex: "192.168.1.100" ou "broker.hivemq.com"
const int   mqtt_port = 1883;
const char* station_id = "estacao_principal_01"; // <stationid> do seu tópico

//NTP (Timestamp)
const char* ntpServer = "pool.ntp.org";
const long  gmtOffset_sec = -3 * 3600; // Offset GMT (Ex: -3 horas para Brasil)
const int   daylightOffset_sec = 0;     // Horário de verão (0 = desativado)

WiFiClient espClient;
PubSubClient client(espClient);

//codigo sensores

// LM393
#define LM393_INTERVAL 1000
#define LM393_PIN 35
volatile unsigned long contagem_lm393 = 0; [cite_start]// [cite: 1]
volatile bool prevLm393State = LOW; [cite_start]// [cite: 2]
void isr_lm393() {
  bool state = digitalRead(LM393_PIN);
  [cite_start]if (prevLm393State != state) { // [cite: 3]
    contagem_lm393++;
  }
  prevLm393State = state;
}
unsigned long lastTime_lm393 = 0;

// BH1750
#define BH1750_INTERVAL 2000
BH1750 lightMeter;
unsigned long lastTime_bh1750 = 0;

// DHT11
#define DHT_PIN 32
#define DHTTYPE DHT11
DHT dht(DHT_PIN, DHTTYPE);
[cite_start]#define DHT11_HUM_INTERVAL  4000 // [cite: 5]
unsigned long lastTime_dht11_hum = 0;

// BMP280
Adafruit_BMP280 bmp;
#define BMP280_PRESSURE_INTERVAL 5000
#define BMP280_TEMPERATURE_INTERVAL 3000
unsigned long lastTime_bmp280_press = 0;
unsigned long lastTime_bmp280_temp = 0; [cite_start]// [cite: 6]

// Função para obter o timestamp Unix (segundos desde 1970)
unsigned long getTimestamp() {
  time_t now;
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) {
    Serial.println("Falha ao obter hora local (NTP)");
    return 0;
  }
  time(&now);
  return (unsigned long)now;
}

// Função para publicar a mensagem no formato solicitado
void publishMqttMessage(String sensor_id, String unit_id, float reading_value) {
  if (!client.connected()) {
    Serial.println("Cliente MQTT desconectado. Ignorando publicação.");
    return;
  }

  unsigned long timestamp = getTimestamp();
  if (timestamp == 0) {
    Serial.println("Timestamp inválido. Ignorando publicação.");
    return;
  }
  
  // Monta o tópico: /weather/<stationid>
  String topic = "/weather/" + String(station_id);

  // Monta o Payload JSON
  StaticJsonDocument<256> doc;
  doc["sensor"] = sensor_id;
  doc["unit"] = unit_id;
  doc.createNestedArray("reading_values").add(reading_value);
  doc.createNestedArray("reading_timestamps").add(timestamp);

  // Serializa o JSON para uma string
  String payload;
  serializeJson(doc, payload);

  // Publica a mensagem
  if (client.publish(topic.c_str(), payload.c_str())) {
    Serial.print("Mensagem MQTT publicada [");
    Serial.print(topic);
    Serial.print("]: ");
    Serial.println(payload);
  } else {
    Serial.println("Falha ao publicar mensagem MQTT.");
  }
}

// Função de Callback do MQTT
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Mensagem recebida [");
  Serial.print(topic);
  Serial.print("]: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

// Conecta ao WiFi
void setupWiFi() {
  delay(10);
  Serial.println();
  Serial.print("Conectando em ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi Conectado!");
  Serial.print("Endereco IP: ");
  Serial.println(WiFi.localIP());
}

// Sincroniza o relógio com o servidor NTP
void setupNTP() {
  Serial.println("Sincronizando hora com NTP...");
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  
  // Espera até que o tempo seja sincronizado
  unsigned long startAttempt = millis();
  while (getTimestamp() < 1672531200) { // Espera até ser um timestamp válido (após 2023)
    delay(500);
    Serial.print(".");
    if (millis() - startAttempt > 10000) { // Timeout de 10s
        Serial.println("\nFalha ao sincronizar NTP. Reiniciando...");
        ESP.restart();
    }
  }
  Serial.println("\nNTP Sincronizado!");
}

// Reconecta ao Broker MQTT
void reconnectMQTT() {
  while (!client.connected()) {
    Serial.print("Tentando conexao MQTT...");
    // Tenta conectar
    // (Pode adicionar usuário/senha aqui se precisar)
    if (client.connect(station_id)) {
      Serial.println("conectado!");
      // Você pode se inscrever em tópicos aqui, se necessário
      // client.subscribe("seu/topico/de/comando");
    } else {
      Serial.print("falha, rc=");
      Serial.print(client.state());
      Serial.println(" tentando novamente em 5 segundos");
      delay(5000);
    }
  }
}

//SETUP
void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);

  // Inicia WiFi
  setupWiFi();
  
  // Inicia NTP
  setupNTP();

  // Configura o cliente MQTT
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(mqttCallback);

  // LM393
  pinMode(LM393_PIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(LM393_PIN), isr_lm393, CHANGE);
  
  // BH1750
  lightMeter.begin(); [cite_start]// [cite: 7]

  // DHT11
  dht.begin();

  // BMP280
  bmp.begin(0x76);

  Serial.println("Estacao iniciada"); [cite_start]// [cite: 8]
}

//LOOP
void loop() {
  unsigned long now = millis();

  // Garante que o MQTT está conectado
  if (!client.connected()) {
    reconnectMQTT();
  }
  client.loop(); // Essencial para o PubSubClient

  // LM393
  if (now - lastTime_lm393 >= LM393_INTERVAL) {
    int pulsos;
    const float FATOR_KHM = 2.4; [cite_start]// [cite: 9]
    
    noInterrupts();
    pulsos = contagem_lm393;
    contagem_lm393 = 0;
    interrupts();
    
    int giros = pulsos / 10;
    float rps = ((float)pulsos/10.0f) / (LM393_INTERVAL / 1000.0f); [cite_start]// [cite: 10]
    float velocidade = rps * FATOR_KHM;

    Serial.print("Velocidade do vento: "); // (Corrigi de "tempo")
    Serial.print(velocidade);
    Serial.println(" km/h"); [cite_start]// [cite: 11]
    
    //PUBLICA MQTT
    // (sensor_id, unit_id, valor)
    publishMqttMessage("LM393_Vento", "km/h", velocidade);
    
    lastTime_lm393 = now;
  }

  // BH1750
  if (now - lastTime_bh1750 >= BH1750_INTERVAL) {
    float luz = lightMeter.readLightLevel(); [cite_start]// [cite: 12]
    
    Serial.print("Luz: ");
    Serial.print(luz);
    Serial.println(" lux");

    //PUBLICA MQTT
    publishMqttMessage("BH1750", "lux", luz);

    lastTime_bh1750 = now;
  }

  // DHT11 - Umidade
  if (now - lastTime_dht11_hum >= DHT11_HUM_INTERVAL) {
    float umidade = dht.readHumidity(); [cite_start]// [cite: 13]
    
    Serial.print("Umidade: ");
    Serial.print(umidade);
    Serial.println(" %");
    
    // --- PUBLICA MQTT ---
    publishMqttMessage("DHT11", "percent", umidade);
    
    lastTime_dht11_hum = now;
  }

  // BMP280 - AIR PRESSURE
  if (now - lastTime_bmp280_press >= BMP280_PRESSURE_INTERVAL) {
    float pressao = bmp.readPressure() / 100.0f; [cite_start]// [cite: 14]
    
    Serial.print("Pressao: ");
    Serial.print(pressao);
    Serial.println(" hPa");
    
    //PUBLICA MQTT
    publishMqttMessage("BMP280_Pressao", "hPa", pressao);
    
    lastTime_bmp280_press = now;
  }

  // BMP280 - TEMPERATURE
  if (now - lastTime_bmp280_temp >= BMP280_TEMPERATURE_INTERVAL) {
    float temperatura = bmp.readTemperature(); [cite_start]// [cite: 15]
    
    Serial.print("Temperatura: ");
    Serial.print(temperatura);
    Serial.println(" C");
    
    //PUBLICA MQTT
    publishMqttMessage("BMP280_Temp", "celsius", temperatura);
    
    lastTime_bmp280_temp = now;
  }
}