klew wrote: Tue Feb 25, 2025 12:39 pm
malarz wrote: Mon Feb 24, 2025 6:43 pm
Zasadnicze pytanie (a właściwie trzy odpowiedzi do wyboru)
1. w konstruktorze klasy SensorSupla wywołać dokładnie to co wyżej
2. Definicję seriala zostawić do zrobienia przed utworzeniem elementu klasy SensorSupla i przekazać do niej tylko wskaźnik na seriala
3. w konstruktorze klasy SensorSupla utworzyć nowy element klasy Stream (nie wykorzystywać SerialX) i użyć go do utworzenia obiektu klasy PM1006K?
Który z wariantów jest najbardziej w zgodzie z założeniami z SuplaDevice?
Klasa będzie też sterowała wiatraczkiem. Ale to dopiero plan na za kilka dni. Być może będę miał kolejne pytania z tym związane.
Na pewno nie nazywaj jej "SensorSupla"
Szkoda. Taka ładna nazwa.
klew wrote: Tue Feb 25, 2025 12:39 pm
Możesz dać przekazywanie wskaźnika na serial do konstruktora tej klasy.
A w kostruktorze sprawdzać czy jest nullptr i jeśli jest nullptr, to inicjować domyślnymi wartościami, j/w.
Ewentualnei możesz dać dwa konstruktory: jeden z serialem, drugi z gpio tx i rx. Wtedy albo bierzesz serial zrobiony wcześniej w kodzie, albo generujesz go dla konkretnych gpio.
To na razie wykorzystuję zmienną Serial1 i konfiguruję ją parametrami wewnątrz konstruktora. Ale nie wiem czy mogę je tak bezkarnie używać. W małym projekcie się to sprawdza (ESP+PM1006K). Nie wiem jak by działało w czymś większym, gdzie potrzeba paru seriali.
klew wrote: Tue Feb 25, 2025 12:39 pm
Stream do czego?
Nie Stream, Jakąś kolejną instancję klasy Serial (ale nie wiem jaki to konkretnie typ powinien być). "Stream" bo tak jest nazwany typ zmiennej w konstruktorze PM1006K w bibliotece czujnika.
W międzyczasie już to wczoraj w nocy napisałem. Jak na razie działa. Muszę jeszcze doświadczalnie sprawdzić na jaki czas włączać wiatrak przed odczytem (albo znaleźć informację na ten temat). W tym kodzie jest sztywno ustalony na 15 sekund.
Code: Select all
/*
Copyright (C) malarz
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// Dependencies:
// https://github.com/kevinlutzer/Arduino-PM1006K
#ifndef SRC_SUPLA_SENSOR_PM1006K_H_
#define SRC_SUPLA_SENSOR_PM1006K_H_
#include <supla/sensor/general_purpose_measurement.h>
#include <PM1006K.h>
namespace Supla {
namespace Sensor {
class pm1006k : public GeneralPurposeMeasurement {
public:
// rx_pin, tx_pin: pins to which the sensor is connected
// refresh: time between readings (in minutes: 1-1440)
explicit pm1006k(int rx_pin, int tx_pin, int fan_pin = 0, int refresh = 10)
: GeneralPurposeMeasurement(nullptr, false) {
if (refresh < 1) {
refresh = 10;
} else if (refresh > 1440) {
refresh = 10;
}
// FAN setup
fanPin = fan_pin;
if (fanPin) {
pinMode(fanPin, OUTPUT);
fanOff = false;
digitalWrite(fanPin, HIGH);
SUPLA_LOG_DEBUG("PM1006K FAN: started & on");
}
// Setup and create instance of the PM1006K driver
// The baud rate for the serial connection must be PM1006K::BAUD_RATE.
Serial1.begin(PM1006K::BAUD_RATE, SERIAL_8N1, rx_pin, tx_pin);
sensor = new PM1006K(&Serial1);
refreshIntervalMs = refresh * 60 * 1000;
setDefaultUnitAfterValue("μg/m³");
setInitialCaption("PM 2.5");
getChannel()->setDefaultIcon(8);
}
void onInit() override {
iterateAlways();
}
void iterateAlways() override {
// 15 sec befor reading sensor
if (millis() - lastReadTime > refreshIntervalMs-15000) {
if (fanPin && fanOff) {
fanOff = false;
digitalWrite(fanPin, HIGH);
SUPLA_LOG_DEBUG("PM1006K FAN: on");
}
}
if (millis() - lastReadTime > refreshIntervalMs) {
int32_t value = NAN;
if(!sensor->takeMeasurement()) {
SUPLA_LOG_DEBUG("PM1006K: failed to take measurement");
} else {
value = sensor->getPM2_5();
SUPLA_LOG_DEBUG("PM1006K: read: %d", value);
}
if (fanPin) {
fanOff = true;
digitalWrite(fanPin, LOW);
SUPLA_LOG_DEBUG("PM1006K FAN: off");
}
if (isnan(value) || value <= 0) {
if (invalidCounter < 3) {
invalidCounter++;
} else {
lastValue = NAN;
}
} else {
invalidCounter = 0;
lastValue = value;
}
channel.setNewValue((double)lastValue);
lastReadTime = millis();
}
}
protected:
::PM1006K* sensor;
uint32_t refreshIntervalMs = 600000;
uint32_t lastReadTime = 0;
uint32_t lastValue = NAN;
int fanPin = 0;
bool fanOff = false;
int invalidCounter = 0;
};
} // namespace Sensor
} // namespace Supla
#endif // SRC_SUPLA_SENSOR_PM1006K_H_
Jakbyś ogólnie stwierdził czy nie ma jakiś poważnych głupot to dopracuję szczegóły i wrzucam na githuba. Zasadniczo to są chyba dwie kwestie:
1. czy rozbić to na plik .cpp i .h, czy może zostać wszystko w .h
2. czy takie użycie seriala jest w porządku, czy lepiej tego tak nie zostawiać, bo ktoś w głównym programie może go użyć do innych zadań
Próbuję przerobić pomysły na działające projekty w ArduinoIDE.