2024-09-2705

This commit is contained in:
hans-jurgen 2024-09-27 12:53:21 +02:00
parent 335b619cd1
commit 226a697fea
7 changed files with 414 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

10
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

39
include/README Normal file
View File

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
lib/README Normal file
View File

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

29
platformio.ini Normal file
View File

@ -0,0 +1,29 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:d1]
platform = espressif8266
board = d1
framework = arduino
monitor_filters = time
lib_deps =
knolleary/PubSubClient @ 2.8
# RECOMMENDED
# Accept new functionality in a backwards compatible manner and patches
adafruit/Adafruit NeoPixel @ ^1.12.3
# Accept only backwards compatible bug fixes
# (any version with the same major and minor versions, and an equal or greater patch version)
adafruit/Adafruit NeoPixel @ ~1.12.3
# The exact version
adafruit/Adafruit NeoPixel @ 1.12.3

274
src/main.cpp Normal file
View File

@ -0,0 +1,274 @@
#include <Arduino.h>
#include <FS.h> //this needs to be first, or it all crashes and burns...
#include <ESP8266WiFi.h>
#include "SoftwareSerial.h"
#include <Adafruit_NeoPixel.h>
#define CO2Min 400
//#define CO2_WARN_1 650
//#define CO2_WARN_2 950
#define CO2_WARN_3 1250
#define AUF_CO2_WARN_3 95 // CO2_WARN_3 - CO2Min 400 / 9
#define CO2_WARN_4 1500
#define AUF_CO2_WARN_4 28 // CO2_WARN_4 - CO2_WARN_3 / 9
#define CO2_CRITICAL_PPM 1850
#define AUF_CO2_WARN_5 39 // CO2_CRITICAL_PPM - CO2_WARN_4 / 9
#define KORR 2500000 -610 -48 // Für Zeitschleife.
#define BUILTIN_LED D4
#define WLAN_ON
#define HF_PIN D2
#define TEST
#define MaxErrCount 30
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <PubSubClient.h>
void reconnect();
void setup_wifi();
WiFiClient espClient;
PubSubClient client(espClient);
SoftwareSerial swSer1;
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN D7 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 12 // Popular NeoPixel ring size
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ800);
const unsigned long interval = (1 * 60000000) + KORR; // Minuten * Mikrosekunden für Sleep Mode
const unsigned long stoerung = 2 * 60000000; // Minuten * Mikrosekunden für Sleep Mode
int CO2Wert; // CO2 Messwert in ppm
int HF_Flag = 0;
const char* mqtt_server = "192.168.127.193";
long deviceId;
char sID[16];
char clientName[30];
unsigned long startTime;
unsigned long endTime;
char topic[100];
char topicWert[20];
char msg[20];
#ifdef TEST
const char* ssid = "St.-Peters-Gasse";
const char* password = "1952994784599317";
IPAddress ip( 192, 168, 127, 213 );
IPAddress gateway( 192, 168, 127, 1 );
IPAddress subnet( 255, 255, 255, 0 );
IPAddress dns(192, 168, 127, 1); // DNS-Server
#else
const char* ssid = "WLAN-7QHHAK";
const char* password = "3557919930817586";
IPAddress ip( 192, 168, 127, 212 );
IPAddress gateway( 192, 168, 127, 1 );
IPAddress subnet( 255, 255, 255, 0 );
IPAddress dns(192, 168, 127, 1); // DNS-Server
#endif
void reconnect() {
unsigned long Pause = 0;
unsigned long ErrLoop = 0;
sprintf(clientName, "%s%s", "ESP8266Client", sID );
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
// If you do not want to use a username and password, change next line to
// if (client.connect("ESP8266Client")) {
//if (client.connect(clientName, mqtt_user, mqtt_pass)) {
if (client.connect(clientName)) {
Serial.println("connected");
// blink.detach();
digitalWrite(LED_BUILTIN, HIGH);
sprintf(topic, "%s%d%s", "hjk/devices/", deviceId, "/telemetry/ID" );
client.publish(topic, sID);
} else {
ErrLoop ++;
// blink.attach(0.8, flip);
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
if (ErrLoop >= 10){
// ---------------------------------
// Status ändern !!! -3
//datenSave(-3);
// ---------------------------------
pixels.setPixelColor(0, pixels.Color(0, 0, 31)); // blue
pixels.show();
endTime = millis();
Pause = stoerung -((endTime - startTime) * 1000); // Pause ca. 2 Minuten
Serial.print("Ich gehe für "); Serial.print(Pause); Serial.println( " µs schlafen.");
ESP.deepSleep(Pause, WAKE_RF_DISABLED); // Pause
delay(500);
}
}
}
}
void setup_wifi() {
long ErrCount = 0;
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.print(ssid);
Serial.print(" ");
WiFi.forceSleepWake();
delay( 1 );
WiFi.persistent( false );
WiFi.mode( WIFI_STA );
WiFi.config( ip, dns, gateway, subnet );
//WiFi.begin( WLAN_SSID, WLAN_PASSWD );
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
ErrCount ++;
if (ErrCount >= MaxErrCount){
// ---------------------------------
// Status ändern !!! -1
//datenSave(-1);
// ---------------------------------
pixels.clear();
pixels.setPixelColor(0, pixels.Color(0, 0, 31)); // blue
pixels.setPixelColor(1, pixels.Color(0, 0, 31)); // blue
pixels.setPixelColor(11, pixels.Color(0, 0, 31)); // blue
pixels.show();
endTime = millis();
unsigned long Pause = stoerung -((endTime - startTime) * 1000); // Pause
ESP.deepSleep(Pause); // Pause
delay(100);
}
}
Serial.println(" WiFi connected");
Serial.print("IP address: \t");
Serial.println(WiFi.localIP());
}
int readCO2() {
byte cmd[9] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
char antwort[9];
swSer1.write(cmd,9);
if(swSer1.available()) {
swSer1.readBytes(antwort, 9);
}
if (antwort[0] != 0xFF) return -1;
if (antwort[1] != 0x86) return -2;
int antwortHigh = (int) antwort[2]; // CO2 High Byte
int antwortLow = (int) antwort[3]; // CO2 Low Byte
int ppm = (256 * antwortHigh) + antwortLow;
return ppm;
}
void setup() {
startTime = millis();
WiFi.mode( WIFI_OFF );
WiFi.forceSleepBegin();
delay( 10 );
pinMode(HF_PIN, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("\n\n\nCO2 Tester");
swSer1.begin(9600, SWSERIAL_8N1, D5, D6, false, 256);
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.setBrightness(31);
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
digitalWrite(BUILTIN_LED, LOW);
HF_Flag = digitalRead(HF_PIN);
Serial.println(); Serial.println(); Serial.println();
Serial.print("HF_Flag = "); Serial.println(HF_Flag);
#ifdef WLAN_ON
if (HF_Flag == 1){
setup_wifi();
}
#endif
digitalWrite(BUILTIN_LED, HIGH);
deviceId = ESP.getChipId();
sprintf(sID, "%010d", deviceId);
Serial.print("ID: \t\t"); Serial.println(deviceId);
client.setServer(mqtt_server, 1883);
}
void loop(){
unsigned long Pause = 0;
CO2Wert = -1;
int Wert1;
#ifdef WLAN_ON
if (HF_Flag == 1){
if (!client.connected()) {
reconnect();
}
client.loop();
}
#endif
while (CO2Wert < 0) {
CO2Wert = readCO2(); // MH-Z19 CO2 Sensor lesen
delay(100);
}
Serial.print(CO2Wert); Serial.print(" ppm");
pixels.clear();
if (CO2Wert < CO2_WARN_3){
Wert1 = (CO2Wert - CO2Min) / AUF_CO2_WARN_3;
if (Wert1 < 1){
Wert1 = 0;
}
Serial.print("\tStufe 1\n ");
Serial.print("Wert1 "); Serial.print(Wert1); Serial.println(" ");
for(int i = 2; i < (11 - Wert1); i++){
pixels.setPixelColor(i, pixels.Color(63, 0, 0)); // grün
}
}
else if (CO2Wert < CO2_WARN_4){
Wert1 = (CO2Wert - CO2_WARN_3) / AUF_CO2_WARN_4;
if (Wert1 < 1){
Wert1 = 0;
}
Serial.print("\tStufe 2\n ");
Serial.print("Wert1 "); Serial.print(Wert1); Serial.println(" ");
for(int i = 2; i < (11 - Wert1); i++){
pixels.setPixelColor(i, pixels.Color(27, 63, 0)); // gelb
}
}
else if (CO2Wert < CO2_CRITICAL_PPM){
Wert1 = (CO2Wert - CO2_WARN_4) / AUF_CO2_WARN_5;
if (Wert1 < 1){
Wert1 = 0;
}
Serial.print("\tStufe 3\n ");
Serial.print("Wert1 "); Serial.print(Wert1); Serial.println(" ");
for(int i=(2+Wert1); i > 1; i--){ // ANZEIGE von Minium nach Max
pixels.setPixelColor(i, pixels.Color(0, 63, 0)); // rot
}
}
else {
Serial.print("\tStufe 4\n ");
for(int i = 0; i < 13; i++){ // Alle LEDs ansteuern
pixels.setPixelColor(i, pixels.Color(0, 255, 0)); // rot
}
}
pixels.show();
itoa(CO2Wert, msg, 10);
sprintf(topic, "%s%d%s", "hjk/devices/", deviceId, "/telemetry/co2" );
client.publish(topic, msg, true);
delay(500);
endTime = millis();
Pause = interval -((endTime - startTime) * 1000); // Pause
ESP.deepSleep(Pause, WAKE_RF_DISABLED); // Pause
delay(500);
}

11
test/README Normal file
View File

@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html