1
0

Add hardware support for GPS, MAX7219, BME280, and MQ7 sensors

- Implemented GPS functionality with initialization and reading latitude and longitude.
- Added MAX7219 display support, including initialization, text display, animation control, and brightness settings.
- Integrated BME280 sensor for reading temperature, pressure, and humidity.
- Developed MQ7 sensor interface for reading gas concentration values.
- Created HTTP client for GET and POST requests.
- Implemented MQTT client for message handling and connection management.
- Added JSON serialization and deserialization functions for sensor and actuator data.
- Established WiFi connection setup for network communication.
This commit is contained in:
Jose
2025-04-25 22:29:57 +02:00
parent 0c09fcd913
commit 51db158354
18 changed files with 441 additions and 303 deletions

View File

@@ -7,10 +7,17 @@
"functional": "cpp", "functional": "cpp",
"tuple": "cpp", "tuple": "cpp",
"utility": "cpp", "utility": "cpp",
"bmp280.h": "c" "bmp280.h": "c",
"deque": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"string_view": "cpp",
"initializer_list": "cpp"
}, },
"github.copilot.enable": { "github.copilot.enable": {
"*": false, "*": true,
"plaintext": false, "plaintext": false,
"markdown": false, "markdown": false,
"scminput": false, "scminput": false,

BIN
hardware/docs/MAX7219.PDF Normal file

Binary file not shown.

View File

@@ -1,7 +1,8 @@
#include <Wire.h> #include <Wire.h>
#include <BME280I2C.h> #include <BME280I2C.h>
#define I2C_BMP280_ADDRESS 0x76 #define I2C_BME280_ADDRESS 0x76
void BME280_Init(); void BME280_Init();
bool BME280_DataReady();
bool BME280_Read(float &pressure, float &temperature, float &humidity); bool BME280_Read(float &pressure, float &temperature, float &humidity);

7
hardware/include/GPS.hpp Normal file
View File

@@ -0,0 +1,7 @@
#include "TinyGPSPlus.h"
#define RX 4
#define TX 5
void GPS_Init();
void GPS_Read(float &lat, float &lon);

View File

@@ -0,0 +1,17 @@
#include <MD_Parola.h>
#include <MD_MAX72XX.h>
#include <SPI.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4 // 4 modulos 8x8
#define DATA_PIN 19
#define CS_PIN 18
#define CLK_PIN 17
void MAX7219_Init();
void MAX7219_DisplayText(const char *text, textPosition_t align, int speed, int pause);
void MAX7219_StartAnimation();
void MAX7219_StopAnimation();
void MAX7219_ClearDisplay();
void MAX7219_SetBrightness(uint8_t brightness);

View File

@@ -4,4 +4,4 @@
#define DIGITAL_MQ7 32 #define DIGITAL_MQ7 32
void MQ7_Init(); void MQ7_Init();
void MQ7_Read(); void MQ7_Read(float &sensorVolt, float &RSAir, float &R0, float &sensorValue);

View File

@@ -1,8 +1,7 @@
#include <Arduino.h> #include <Arduino.h>
#define LED 2 #define SERVER_IP "https://contaminus.miarma.net/api/v1/"
#define SERVER_IP "192.168.1.178" #define REST_PORT 443
#define REST_PORT 80
#define MQTT_PORT 1883 #define MQTT_PORT 1883
#include "JsonTools.hpp" #include "JsonTools.hpp"
@@ -10,5 +9,12 @@
#include "WifiConnection.hpp" #include "WifiConnection.hpp"
#include "MqttClient.hpp" #include "MqttClient.hpp"
#include "BME280.hpp" #include "BME280.hpp"
#include "GPS.hpp"
#include "MAX7219.hpp"
#include "MQ7.hpp"
uint32_t getChipID(); uint32_t getChipID();
void prettyReadMQ7();
void prettyReadBME280();
void prettyReadGPS();
void testMatrix();

View File

@@ -12,8 +12,11 @@
platform = espressif32 platform = espressif32
board = esp32dev board = esp32dev
framework = arduino framework = arduino
upload_port = COM3
lib_deps = lib_deps =
knolleary/PubSubClient@^2.8 knolleary/PubSubClient@^2.8
mikalhart/TinyGPSPlus@^1.0.2 mikalhart/TinyGPSPlus@^1.0.2
bblanchon/ArduinoJson@^6.17.3 bblanchon/ArduinoJson@^6.17.3
finitespace/BME280@^3.0.0 finitespace/BME280@^3.0.0
majicdesigns/MD_MAX72XX@^3.5.1
majicdesigns/MD_Parola@^3.7.3

View File

@@ -1,24 +0,0 @@
#include "BME280.hpp"
BME280I2C bme;
void BME280_Init()
{
Wire.setPins(21, 22);
Wire.begin();
while(!bme.begin())
{
Serial.println("Could not find BME280 sensor!");
delay(1000);
}
}
bool BME280_Read(float &pressure, float &temperature, float &humidity)
{
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pressure, temperature, humidity, tempUnit, presUnit);
return (temperature != 0.0f && pressure != 0.0f);
}

View File

@@ -0,0 +1,35 @@
#include "MAX7219.hpp"
MD_Parola display = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void MAX7219_Init()
{
display.begin();
display.setIntensity(1); // 0-15
display.displayClear();
}
void MAX7219_DisplayText(const char *text, textPosition_t align, int speed, int pause)
{
display.displayText(text, align, speed, pause, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}
void MAX7219_StartAnimation()
{
display.displayAnimate();
}
void MAX7219_StopAnimation()
{
display.displayReset();
}
void MAX7219_ClearDisplay()
{
display.displayClear();
}
void MAX7219_SetBrightness(uint8_t brightness)
{
display.setIntensity(brightness);
}

View File

@@ -1,179 +1,179 @@
#include "JsonTools.hpp" #include "JsonTools.hpp"
String serializeSensorValue(int sensorId, int deviceId, String sensorType, String unit, int sensorStatus, float temperature, float humidity, float carbonMonoxide, float lat, float lon, long timestamp) String serializeSensorValue(int sensorId, int deviceId, String sensorType, String unit, int sensorStatus, float temperature, float humidity, float carbonMonoxide, float lat, float lon, long timestamp)
{ {
DynamicJsonDocument doc(2048); DynamicJsonDocument doc(2048);
doc["sensorId"] = sensorId; doc["sensorId"] = sensorId;
doc["deviceId"] = deviceId; doc["deviceId"] = deviceId;
doc["sensorType"] = sensorType; doc["sensorType"] = sensorType;
doc["unit"] = unit; doc["unit"] = unit;
doc["sesnsorStatuts"] = sensorStatus; doc["sesnsorStatuts"] = sensorStatus;
doc["temperature"] = temperature; doc["temperature"] = temperature;
doc["humidity"] = humidity; doc["humidity"] = humidity;
doc["carbonMonoxide"] = carbonMonoxide; doc["carbonMonoxide"] = carbonMonoxide;
doc["lat"] = lat; doc["lat"] = lat;
doc["lon"] = lon; doc["lon"] = lon;
doc["timestamp"] = timestamp; doc["timestamp"] = timestamp;
String output; String output;
serializeJson(doc, output); serializeJson(doc, output);
Serial.println(output); Serial.println(output);
return output; return output;
} }
String serializeActuatorStatus (int actuatorId, int deviceId, int status, long timestamp) String serializeActuatorStatus (int actuatorId, int deviceId, int status, long timestamp)
{ {
DynamicJsonDocument doc(2048); DynamicJsonDocument doc(2048);
doc["actuatorId"] = actuatorId; doc["actuatorId"] = actuatorId;
doc["deviceId"] = deviceId; doc["deviceId"] = deviceId;
doc["status"] = status; doc["status"] = status;
doc["timestamp"] = timestamp; doc["timestamp"] = timestamp;
String output; String output;
serializeJson(doc, output); serializeJson(doc, output);
Serial.println(output); Serial.println(output);
return output; return output;
} }
String serializeDevice(int sensorId, int deviceId, String sensorType, int status, long timestamp) String serializeDevice(int sensorId, int deviceId, String sensorType, int status, long timestamp)
{ {
DynamicJsonDocument doc(2048); DynamicJsonDocument doc(2048);
doc["sensorId"] = sensorId; doc["sensorId"] = sensorId;
doc["deviceId"] = deviceId; doc["deviceId"] = deviceId;
doc["sensorType"] = sensorType; doc["sensorType"] = sensorType;
doc["status"] = status; doc["status"] = status;
doc["timestamp"] = timestamp; doc["timestamp"] = timestamp;
String output; String output;
serializeJson(doc, output); serializeJson(doc, output);
Serial.println(output); Serial.println(output);
return output; return output;
} }
void deserializeSensorValue (HTTPClient &http, int httpResponseCode) void deserializeSensorValue (HTTPClient &http, int httpResponseCode)
{ {
if (httpResponseCode > 0) if (httpResponseCode > 0)
{ {
Serial.print("HTTP Response code: "); Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode); Serial.println(httpResponseCode);
String responseJson = http.getString(); String responseJson = http.getString();
DynamicJsonDocument doc(ESP.getMaxAllocHeap()); DynamicJsonDocument doc(ESP.getMaxAllocHeap());
DeserializationError error = deserializeJson(doc, responseJson); DeserializationError error = deserializeJson(doc, responseJson);
if (error) if (error)
{ {
Serial.print(F("deserializeJson() failed: ")); Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str()); Serial.println(error.f_str());
return; return;
} }
JsonArray array = doc.as<JsonArray>(); JsonArray array = doc.as<JsonArray>();
for (JsonObject sensor : array) for (JsonObject sensor : array)
{ {
int sensorId = sensor["sensorId"]; int sensorId = sensor["sensorId"];
int deviceId = sensor["deviceId"]; int deviceId = sensor["deviceId"];
String sensorType = sensor["sensorType"]; String sensorType = sensor["sensorType"];
String unit = sensor["unit"]; String unit = sensor["unit"];
int sesnsorStatuts = sensor["sesnsorStatuts"]; int sesnsorStatuts = sensor["sesnsorStatuts"];
float temperature = sensor["temperature"]; float temperature = sensor["temperature"];
float humidity = sensor["humidity"]; float humidity = sensor["humidity"];
float carbonMonoxide = sensor["carbonMonoxide"]; float carbonMonoxide = sensor["carbonMonoxide"];
float lat = sensor["lat"]; float lat = sensor["lat"];
float lon = sensor["lon"]; float lon = sensor["lon"];
long timestamp = sensor["timestamp"]; long timestamp = sensor["timestamp"];
Serial.println(("Sensor deserialized: [sensorId: " + String(sensorId) + ", deviceId: " + String(deviceId) + ", sensorType: " + sensorType + ", unit: " + unit +", sesnsorStatuts: " + String(sesnsorStatuts) +", temperature: " + String(temperature) +", humidity: " + String(humidity) +", carbonMonoxide: " + String(carbonMonoxide) +", lat: " + String(lat) +", lon: " + String(lon) +", timestamp: " + String(timestamp) + "]").c_str()); Serial.println(("Sensor deserialized: [sensorId: " + String(sensorId) + ", deviceId: " + String(deviceId) + ", sensorType: " + sensorType + ", unit: " + unit +", sesnsorStatuts: " + String(sesnsorStatuts) +", temperature: " + String(temperature) +", humidity: " + String(humidity) +", carbonMonoxide: " + String(carbonMonoxide) +", lat: " + String(lat) +", lon: " + String(lon) +", timestamp: " + String(timestamp) + "]").c_str());
} }
} }
else else
{ {
Serial.print("Error code: "); Serial.print("Error code: ");
Serial.println(httpResponseCode); Serial.println(httpResponseCode);
} }
} }
void deserializeActuatorStatus (HTTPClient &http, int httpResponseCode) void deserializeActuatorStatus (HTTPClient &http, int httpResponseCode)
{ {
if (httpResponseCode > 0) if (httpResponseCode > 0)
{ {
Serial.print("HTTP Response code: "); Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode); Serial.println(httpResponseCode);
String responseJson = http.getString(); String responseJson = http.getString();
DynamicJsonDocument doc(ESP.getMaxAllocHeap()); DynamicJsonDocument doc(ESP.getMaxAllocHeap());
DeserializationError error = deserializeJson(doc, responseJson); DeserializationError error = deserializeJson(doc, responseJson);
if (error) if (error)
{ {
Serial.print(F("deserializeJson() failed: ")); Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str()); Serial.println(error.f_str());
return; return;
} }
JsonArray array = doc.as<JsonArray>(); JsonArray array = doc.as<JsonArray>();
for (JsonObject actuator : array) for (JsonObject actuator : array)
{ {
int actuadorId = actuator["actuadorId"]; int actuadorId = actuator["actuadorId"];
int deviceId = actuator["deviceId"]; int deviceId = actuator["deviceId"];
int statuts = actuator["statuts"]; int statuts = actuator["statuts"];
long timestamp = actuator["timestamp"]; long timestamp = actuator["timestamp"];
Serial.println(("Actuador deserialized: [actuadorId: " + String(actuadorId) + Serial.println(("Actuador deserialized: [actuadorId: " + String(actuadorId) +
", deviceId: " + String(deviceId) + ", deviceId: " + String(deviceId) +
", statuts: " + String(statuts) + ", statuts: " + String(statuts) +
", timestamp: " + String(timestamp) + "]").c_str()); ", timestamp: " + String(timestamp) + "]").c_str());
} }
} }
else else
{ {
Serial.print("Error code: "); Serial.print("Error code: ");
Serial.println(httpResponseCode); Serial.println(httpResponseCode);
} }
} }
void deserializeDevice (HTTPClient &http, int httpResponseCode) void deserializeDevice (HTTPClient &http, int httpResponseCode)
{ {
if (httpResponseCode > 0) if (httpResponseCode > 0)
{ {
Serial.print("HTTP Response code: "); Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode); Serial.println(httpResponseCode);
String responseJson = http.getString(); String responseJson = http.getString();
DynamicJsonDocument doc(ESP.getMaxAllocHeap()); DynamicJsonDocument doc(ESP.getMaxAllocHeap());
DeserializationError error = deserializeJson(doc, responseJson); DeserializationError error = deserializeJson(doc, responseJson);
if (error) if (error)
{ {
Serial.print(F("deserializeJson() failed: ")); Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str()); Serial.println(error.f_str());
return; return;
} }
JsonArray array = doc.as<JsonArray>(); JsonArray array = doc.as<JsonArray>();
for (JsonObject device : array) for (JsonObject device : array)
{ {
int sensorId = device["sensorId"]; int sensorId = device["sensorId"];
int deviceId = device["deviceId"]; int deviceId = device["deviceId"];
String sensorType = device["sensorType"]; String sensorType = device["sensorType"];
long timestamp = device["timestamp"]; long timestamp = device["timestamp"];
Serial.println(("Sensor deserialized: [sensorId: " + String(sensorId) + Serial.println(("Sensor deserialized: [sensorId: " + String(sensorId) +
", deviceId: " + String(deviceId) + ", deviceId: " + String(deviceId) +
", sensorType: " + sensorType + ", sensorType: " + sensorType +
", timestamp: " + String(timestamp) + "]").c_str()); ", timestamp: " + String(timestamp) + "]").c_str());
} }
} }
else else
{ {
Serial.print("Error code: "); Serial.print("Error code: ");
Serial.println(httpResponseCode); Serial.println(httpResponseCode);
} }
} }

View File

@@ -1,27 +1,28 @@
#include "RestClient.hpp" #include "RestClient.hpp"
HTTPClient httpClient; // HTTP client object
void getRequest(HTTPClient &httpClient, const String url, String &response)
{ void getRequest(const String url, String &response)
httpClient.begin(url); {
int httpCode = httpClient.GET(); httpClient.begin(url);
if (httpCode > 0) { int httpCode = httpClient.GET();
response = httpClient.getString(); if (httpCode > 0) {
} else { response = httpClient.getString();
response = "Error: " + String(httpCode); } else {
} response = "Error: " + String(httpCode);
httpClient.end(); }
} httpClient.end();
}
void postRequest(HTTPClient &httpClient, const String url, String &payload, String &response)
{ void postRequest(const String url, String &payload, String &response)
httpClient.begin(url); {
httpClient.addHeader("Content-Type", "application/json"); httpClient.begin(url);
int httpCode = httpClient.POST(payload); httpClient.addHeader("Content-Type", "application/json");
if (httpCode > 0) { int httpCode = httpClient.POST(payload);
response = httpClient.getString(); if (httpCode > 0) {
} else { response = httpClient.getString();
response = "Error: " + String(httpCode); } else {
} response = "Error: " + String(httpCode);
httpClient.end(); }
httpClient.end();
} }

View File

@@ -1,33 +1,33 @@
#include <WifiConnection.hpp> #include <WifiConnection.hpp>
WiFiClient wifiClient; WiFiClient wifiClient;
int setupWifi() int setupWifi()
{ {
Serial.println(); Serial.println();
Serial.print("Connecting to "); Serial.print("Connecting to ");
Serial.println(SSID); Serial.println(SSID);
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWORD); WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) while (WiFi.status() != WL_CONNECTED)
{ {
delay(500); delay(500);
Serial.print("."); Serial.print(".");
} }
Serial.println(""); Serial.println("");
Serial.println("WiFi connected"); Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println("IP address: ");
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
Serial.println("Setup!"); Serial.println("Setup!");
if(WiFi.status() == WL_CONNECTED) if(WiFi.status() == WL_CONNECTED)
{ {
return 0; return 0;
} }
else else
{ {
return 1; return 1;
} }
} }

View File

@@ -0,0 +1,34 @@
#include "BME280.hpp"
BME280I2C bme;
void BME280_Init()
{
Wire.setPins(21, 22);
Wire.begin();
BME280I2C::Settings settings(
BME280I2C::OSR::OSR_X1,
BME280I2C::OSR::OSR_X1,
BME280I2C::OSR::OSR_X1,
BME280I2C::Mode::Mode_Forced, // modo forzado
BME280I2C::StandbyTime::StandbyTime_1000ms,
BME280I2C::Filter::Filter_16,
BME280I2C::SpiEnable::SpiEnable_False,
BME280I2C::I2CAddr::I2CAddr_0x76 // dirección I2C del BME280
);
bme.setSettings(settings);
while (!bme.begin());
}
bool BME280_Read(float &pressure, float &temperature, float &humidity)
{
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pressure, temperature, humidity, tempUnit, presUnit);
return (temperature != 0.0f && pressure != 0.0f);
}

View File

@@ -0,0 +1,22 @@
#include "GPS.hpp"
TinyGPSPlus gps;
void GPS_Init()
{
Serial.begin(9600);
}
void GPS_Read(float &lat, float &lon)
{
if (gps.location.isValid())
{
lat = gps.location.lat();
lon = gps.location.lng();
}
else
{
lat = 0.0f;
lon = 0.0f;
}
}

View File

@@ -1,5 +1,5 @@
#include "MQ7.hpp" #include "MQ7.hpp"
void MQ7_Init() void MQ7_Init()
{ {
pinMode(DIGITAL_MQ7, INPUT); pinMode(DIGITAL_MQ7, INPUT);

View File

@@ -2,17 +2,70 @@
const uint32_t deviceId = getChipID(); const uint32_t deviceId = getChipID();
// instances extern HTTPClient httpClient; // HTTP client object
HTTPClient httpClient; String response; // HTTP Response
float sensorVolt, sensorValue, RSAir, R0; // MQ7 vars
float temperature, pressure, humidity; // BME280 vars
float lon, lat; // GPS vars
extern MD_Parola display; // Display object
// HTTP Request void setup()
String response; {
Serial.begin(9600);
// MQ7 Serial.println("Iniciando...");
float sensorVolt, sensorValue, RSAir, R0; MQ7_Init();
Serial.println("Sensor MQ7 inicializado");
BME280_Init();
Serial.println("Sensor BME280 inicializado");
GPS_Init();
Serial.println("GPS inicializado");
MAX7219_Init();
Serial.println("Display inicializado");
// BMP280 prettyReadBME280();
float temperature, pressure, altitude; prettyReadMQ7();
testMatrix();
}
void loop()
{
}
void prettyReadMQ7()
{
Serial.println("Leyendo sensor MQ7...");
MQ7_Read(sensorVolt, RSAir, R0, sensorValue);
Serial.print("\t - Voltaje: "); Serial.print(sensorVolt); Serial.print("V\r\n");
Serial.print("\t - Valor sensor: "); Serial.print(sensorValue); Serial.print("\r\n");
Serial.print("\t - Resistencia aire: "); Serial.print(RSAir); Serial.print("kOhm\r\n");
Serial.print("\t - Resistencia aire: "); Serial.print(R0); Serial.print("kOhm\r\n");
Serial.print("\t - Concentración CO: "); Serial.print(sensorValue); Serial.print("ppm\r\n");
}
void prettyReadBME280()
{
Serial.println("Leyendo sensor BME280...");
BME280_Read(pressure, temperature, humidity);
Serial.print("\t - Presión: "); Serial.print(pressure/100); Serial.print("hPa\r\n");
Serial.print("\t - Temperatura: "); Serial.print(temperature); Serial.print("°C\r\n");
Serial.print("\t - Humedad: "); Serial.print(humidity); Serial.print("%\r\n");
}
void prettyReadGPS()
{
Serial.println("Leyendo GPS...");
GPS_Read(lat, lon);
Serial.print("\t - Latitud: "); Serial.print(lat); Serial.print("\r\n");
Serial.print("\t - Longitud: "); Serial.print(lon); Serial.print("\r\n");
}
void testMatrix()
{
Serial.println("Escribiendo en el display...");
MAX7219_DisplayText("Prueba de texto", PA_LEFT, 100, 500);
}
uint32_t getChipID() uint32_t getChipID()
{ {
@@ -22,28 +75,4 @@ uint32_t getChipID()
chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
} }
return chipId; return chipId;
} }
void setup()
{
Serial.begin(9600);
/*// WiFi Connection
if(setupWifi() != 0)
{
Serial.print("Error connecting to WiFi");
}
// test get
getRequest(httpClient, "http://172.20.10.7:8082/api/v1/sensors/1/values", response);
deserializeSensorValue(httpClient, httpClient.GET()); */
BME280_Init();
}
void loop()
{
Serial.println(temperature);
Serial.println(pressure);
}