Страница 1 из 1
SHARP GP2Y1010AU0F
Добавлено: 28 июн 2020, 21:07
Berk
Код: Выделить всё
// ############################################## SHARP GP2Y1010AU0F ##################################################### //
// //
// @filename : DustSensor_V3.ino //
// @brief en : Measurement of the level of dust and suspended particles in the air. //
// Approximate measurement of PPM 2.5 //
// @brief ru : Измерение уровня пыли, взвешенных частиц в воздухе. Приближенное измерение PPM 2.5 //
// @author : Andrew Lamchenko aka Berk //
// //
// Copyright (C) EFEKTALAB 2018 //
// //
// ######################################################################################################################## //
#define MY_DEBUG
#define SEND_HEARTBEAT
#define MY_RADIO_RF24
#include <MySensors.h>
#define CHILD_ID_DUST 0
static const uint8_t ledPower = 8; // Пин включение IR LED сенсора воздуха
static const uint8_t sensApin = 5; // Пин чтения данных сенсора воздуха
bool firstLoop;
unsigned int samplingTime = 290;
unsigned int deltaTime = 30;
unsigned int sleepTime = 9680;
float ready_dustDensity;
float old_ready_dustDensity = -999.0;
float t_dustDensity = 1.0;
float filterCoof = 0.9;
//float coof; // для старых датчиков
static uint8_t CALC_N_READS = 20; // рекомендуется 50 чтений, (миним.10, но можно и одно :)), больше чтений, выше точность .....готовые данные 10мс-500мс
uint32_t previousMillis = 0; // здесь будет храниться время последнего запуска функции работы сенсора
uint32_t interval1 = 10; // интервал в секундах
#ifdef SEND_HEARTBEAT
uint32_t previousMillis2 = 0; // здесь будет храниться время последней отправки пульса
uint32_t interval2 = 600; // интервал в секундах
#endif
MyMessage dustMsg(CHILD_ID_DUST, V_LEVEL);
void before() {
pinMode(ledPower, OUTPUT);
digitalWrite(ledPower, HIGH);
wait(50);
if (CALC_N_READS < 1) {
CALC_N_READS = 1;
}
/*
// для старых датчиков, которые использовали больше года, приведено для примера, со временем падвет чувствительность нижнего уровня
if (CALC_N_READS < 10) {
CALC_N_READS = 10;
}
if (CALC_N_READS >= 50) {
coof = 0.005;
} else if (CALC_N_READS >= 40) {
coof = 0.00625;
} else if (CALC_N_READS >= 30) {
coof = 0.0075;
} else if (CALC_N_READS >= 20) {
coof = 0.01;
} else if (CALC_N_READS >= 10) {
coof = 0.015;
} else if (CALC_N_READS > 0) {
coof = 0.0175;
}
*/
}
void presentation()
{
sendSketchInfo("Dust Sensor GP2Y10", "3.0");
present(CHILD_ID_DUST, S_DUST);
}
void setup() {
dustwork();
sendHeartbeat();
}
void loop() {
if (millis() - previousMillis > interval1 * 1000) {
previousMillis = millis(); // запоминаем текущее время
dustwork();
}
#ifdef SEND_HEARTBEAT
if (millis() - previousMillis2 > interval2 * 1000) {
previousMillis2 = millis(); // запоминаем текущее время
sendHeartbeat();
}
#endif
}
void dustwork() {
float voMeasured = 0;
float voMeasuredTemp = 0;
float calcVoltage = 0;
float dustDensity = 0;
//float filtered_dustDensity = 0;
for (uint8_t i = 0; i < CALC_N_READS; i++) {
digitalWrite(ledPower, LOW);
delayMicroseconds(samplingTime);
voMeasuredTemp = analogRead(sensApin);//
delayMicroseconds(deltaTime);
digitalWrite(ledPower, HIGH);
if (CALC_N_READS > 1) {
delayMicroseconds(sleepTime);
}
voMeasured = voMeasured + voMeasuredTemp;
}
voMeasured = voMeasured / CALC_N_READS;
calcVoltage = voMeasured * (5.0 / 1024.0);
dustDensity = (0.17 * calcVoltage - (0.1)) * 1000;
//dustDensity = (0.17 * calcVoltage - (0.1 + coof)) * 1000; // для старых датчиков
if (firstLoop == false) { // Присвоение переменной значения для фильтрации начальныхданных
firstLoop = true;
ready_dustDensity = dustDensity;
}
ready_dustDensity += (dustDensity - ready_dustDensity) * filterCoof;
if (ready_dustDensity < 0)
{
ready_dustDensity = 0.00;
}
#ifdef MY_DEBUG
Serial.print("Data: ");
Serial.print(dustDensity, 2);
Serial.print(" µg/m^3");
Serial.print(" | filtration: ");
Serial.println(filterCoof);
Serial.print("Filtered data: ");
Serial.print(ready_dustDensity, 2);
Serial.print(" µg/m^3");
Serial.print(" | filtration: ");
Serial.println(filterCoof);
#endif
if (abs(ready_dustDensity - old_ready_dustDensity) >= t_dustDensity) {
send(dustMsg.set(ready_dustDensity, 1));
old_ready_dustDensity = ready_dustDensity;
}
}
[attachment=0]photo_2020-06-28_13-15-03.jpg[/attachment]
Re: SHARP GP2Y1010AU0F
Добавлено: 28 июн 2020, 23:22
Berk
Эксперементальное:
Код: Выделить всё
// ############################################## SHARP GP2Y1010AU0F ##################################################### //
// //
// @filename : DustSensor_V3_1.ino //
// @brief en : Measurement of the level of dust and suspended particles in the air. //
// Approximate measurement of PPM 2.5 //
// @brief ru : Измерение уровня пыли, взвешенных частиц в воздухе. Приближенное измерение PPM 2.5 //
// @author : Andrew Lamchenko aka Berk //
// //
// Copyright (C) EFEKTALAB 2018 //
// //
// ######################################################################################################################## //
#include <avr/wdt.h>
#define MY_DEBUG
#define SEND_HEARTBEAT
#define MY_RADIO_RF24
int16_t mtwr;
#define MY_TRANSPORT_WAIT_READY_MS (mtwr)
#define MY_RF24_PA_LEVEL (RF24_PA_MAX)
#define SN "Dust Sensor GP2Y10"
#define SV "3.1"
#include <MySensors.h>
#define CHILD_ID_DUST 0
static const uint8_t ledPower = 8; // Пин включение IR LED сенсора воздуха
static const uint8_t sensApin = 5; // Пин чтения данных сенсора воздуха
bool firstLoop;
bool check;
unsigned int samplingTime = 290;
unsigned int deltaTime = 30;
unsigned int sleepTime = 9680;
bool Ack_FP;
bool flag_update_transport_param;
bool flag_sendRoute_parent;
bool flag_nogateway_mode;
bool flag_find_parent_process;
int16_t myid;
int16_t mypar;
int16_t old_mypar = -1;
uint8_t err_delivery_beat;
float ready_dustDensity;
float old_ready_dustDensity = -999.0;
float t_dustDensity = 1.0;
float filterCoof = 0.5;
//float coof; // для старых датчиков
static uint8_t CALC_N_READS = 0; // рекомендуется 50 чтений, (миним.10, но можно и одно :)), больше чтений, выше точность .....готовые данные 100мс-500мс
uint32_t previousMillis = 0; // здесь будет храниться время последнего запуска функции работы сенсора
uint32_t interval1 = 10; // интервал в секундах
#ifdef SEND_HEARTBEAT
uint32_t previousMillis2 = 0; // здесь будет храниться время последней отправки пульса
uint32_t interval2 = 3600; // интервал в секундах
#endif
MyMessage dustMsg(CHILD_ID_DUST, V_LEVEL);
void before() {
wdt_disable();
pinMode(ledPower, OUTPUT);
digitalWrite(ledPower, HIGH);
wait(50);
if (CALC_N_READS < 1) {
CALC_N_READS = 1;
}
happy_init();
/*
// для старых датчиков, которые использовали больше года, приведено для примера, со временем падвет чувствительность нижнего уровня
if (CALC_N_READS < 10) {
CALC_N_READS = 10;
}
if (CALC_N_READS >= 50) {
coof = 0.005;
} else if (CALC_N_READS >= 40) {
coof = 0.00625;
} else if (CALC_N_READS >= 30) {
coof = 0.0075;
} else if (CALC_N_READS >= 20) {
coof = 0.01;
} else if (CALC_N_READS >= 10) {
coof = 0.015;
} else if (CALC_N_READS > 0) {
coof = 0.0175;
}
*/
}
void presentation()
{
check = sendSketchInfo(SN, SV);
if (!check) {
_transportSM.failedUplinkTransmissions = 0;
wait(50);
check = sendSketchInfo(SN, SV);
wait(50);
_transportSM.failedUplinkTransmissions = 0;
}
check = present(CHILD_ID_DUST, S_DUST);
if (!check) {
_transportSM.failedUplinkTransmissions = 0;
wait(100);
check = present(CHILD_ID_DUST, S_DUST);
wait(100);
_transportSM.failedUplinkTransmissions = 0;
}
}
void setup() {
wdt_enable(WDTO_8S);
config_Happy_node();
dustwork();
sendHeartbeat();
}
void loop() {
wdt_reset();
if (flag_update_transport_param == true) {
update_Happy_transport();
}
if (flag_sendRoute_parent == true) {
present_only_parent();
}
if (isTransportReady() == true) {
if (flag_nogateway_mode == false) {
if (flag_find_parent_process == true) {
find_parent_process();
}
if (millis() - previousMillis > interval1 * 1000) {
previousMillis = millis(); // запоминаем текущее время
dustwork();
}
#ifdef SEND_HEARTBEAT
if (millis() - previousMillis2 > interval2 * 1000) {
previousMillis2 = millis(); // запоминаем текущее время
sendHeartbeat();
}
#endif
} else {
if (millis() - previousMillis > interval1 * 1000) {
previousMillis = millis(); // запоминаем текущее время
check_parent();
}
}
}
if (_transportSM.failureCounter > 0)
{
_transportConfig.parentNodeId = loadState(101);
_transportConfig.nodeId = myid;
_transportConfig.distanceGW = loadState(103);
mypar = _transportConfig.parentNodeId;
err_delivery_beat = 5;
happy_node_mode();
gateway_fail();
}
}
void dustwork() {
float voMeasured = 0;
float voMeasuredTemp = 0;
float calcVoltage = 0;
float dustDensity = 0;
//float filtered_dustDensity = 0;
for (uint8_t i = 0; i < CALC_N_READS; i++) {
digitalWrite(ledPower, LOW);
delayMicroseconds(samplingTime);
voMeasuredTemp = analogRead(sensApin);//
delayMicroseconds(deltaTime);
digitalWrite(ledPower, HIGH);
if (CALC_N_READS > 1) {
delayMicroseconds(sleepTime);
}
voMeasured = voMeasured + voMeasuredTemp;
}
voMeasured = voMeasured / CALC_N_READS;
calcVoltage = voMeasured * (5.0 / 1024.0);
dustDensity = (0.17 * calcVoltage - (0.1)) * 1000;
//dustDensity = (0.17 * calcVoltage - (0.1 + coof)) * 1000; // для старых датчиков
if (firstLoop == false) { // Присвоение переменной значения для фильтрации начальныхданных
firstLoop = true;
ready_dustDensity = dustDensity;
}
ready_dustDensity += (dustDensity - ready_dustDensity) * filterCoof;
if (ready_dustDensity < 0)
{
ready_dustDensity = 0.00;
}
#ifdef MY_DEBUG
Serial.print("Data: ");
Serial.print(dustDensity, 2);
Serial.print(" µg/m^3");
Serial.print(" | filtration: ");
Serial.println(filterCoof);
Serial.print("Filtered data: ");
Serial.print(ready_dustDensity, 2);
Serial.print(" µg/m^3");
Serial.print(" | filtration: ");
Serial.println(filterCoof);
#endif
if (abs(ready_dustDensity - old_ready_dustDensity) >= t_dustDensity) {
check = send(dustMsg.set(ready_dustDensity, 1));
if (!check) {
_transportSM.failedUplinkTransmissions = 0;
wait(50);
check = send(dustMsg.set(ready_dustDensity, 1));
wait(50);
if (!check) {
_transportSM.failedUplinkTransmissions = 0;
wait(150);
check = send(dustMsg.set(ready_dustDensity, 1));
wait(150);
}
}
if (check) {
err_delivery_beat = 0;
if (flag_nogateway_mode == 1) {
flag_nogateway_mode = 0;
CORE_DEBUG(PSTR("MyS: NORMAL GATEWAY MODE\n"));
err_delivery_beat = 0;
}
} else {
_transportSM.failedUplinkTransmissions = 0;
if (err_delivery_beat < 5) {
err_delivery_beat++;
}
if (err_delivery_beat == 4) {
if (flag_nogateway_mode == 0) {
happy_node_mode();
gateway_fail();
CORE_DEBUG(PSTR("MyS: LOST GATEWAY MODE\n"));
}
}
}
old_ready_dustDensity = ready_dustDensity;
}
}
// ############################################ HAPPY NODE ###############################################
void happy_init() {
if (hwReadConfig(EEPROM_NODE_ID_ADDRESS) == 0) {
hwWriteConfig(EEPROM_NODE_ID_ADDRESS, 255);
}
if (loadState(100) == 0) {
saveState(100, 255);
}
CORE_DEBUG(PSTR("EEPROM NODE ID: %d\n"), hwReadConfig(EEPROM_NODE_ID_ADDRESS));
CORE_DEBUG(PSTR("USER MEMORY SECTOR NODE ID: %d\n"), loadState(100));
if (hwReadConfig(EEPROM_NODE_ID_ADDRESS) == 255) {
mtwr = 0;
} else {
mtwr = 10000;
}
CORE_DEBUG(PSTR("MY_TRANSPORT_WAIT_MS: %d\n"), mtwr);
}
void config_Happy_node() {
if (mtwr == 0) {
myid = getNodeId();
saveState(100, myid);
mypar = _transportConfig.parentNodeId;
old_mypar = mypar;
saveState(101, mypar);
saveState(102, _transportConfig.distanceGW);
}
if (mtwr != 0) {
myid = getNodeId();
if (myid != loadState(100)) {
saveState(100, myid);
}
if (isTransportReady() == true) {
mypar = _transportConfig.parentNodeId;
if (mypar != loadState(101)) {
saveState(101, mypar);
}
if (_transportConfig.distanceGW != loadState(102)) {
saveState(102, _transportConfig.distanceGW);
}
}
if (isTransportReady() == false)
{
no_present();
err_delivery_beat = 5;
_transportConfig.nodeId = myid;
_transportConfig.parentNodeId = loadState(101);
_transportConfig.distanceGW = loadState(102);
mypar = _transportConfig.parentNodeId;
happy_node_mode();
gateway_fail();
}
}
}
void no_present() {
_coreConfig.presentationSent = true;
_coreConfig.nodeRegistered = true;
}
void update_Happy_transport() {
CORE_DEBUG(PSTR("MyS: UPDATE TRANSPORT CONFIGURATION\n"));
mypar = _transportConfig.parentNodeId;
if (mypar != loadState(101))
{
saveState(101, mypar);
}
if (_transportConfig.distanceGW != loadState(102))
{
saveState(102, _transportConfig.distanceGW);
}
present_only_parent();
wait(150);
flag_update_transport_param = false;
}
void present_only_parent() {
if (old_mypar != mypar) {
CORE_DEBUG(PSTR("MyS: SEND LITTLE PRESENT:) WITH PARENT ID\n"));
if (_sendRoute(build(_msgTmp, 0, NODE_SENSOR_ID, C_INTERNAL, 6).set(mypar))) {
flag_sendRoute_parent = false;
old_mypar = mypar;
} else {
flag_sendRoute_parent = true;
}
}
}
void happy_node_mode() {
_transportSM.findingParentNode = false;
_transportSM.transportActive = true;
_transportSM.uplinkOk = true;
_transportSM.pingActive = false;
_transportSM.failureCounter = 0;
_transportSM.uplinkOk = true;
_transportSM.failureCounter = 0u;
_transportSM.failedUplinkTransmissions = 0u;
transportSwitchSM(stReady);
CORE_DEBUG(PSTR("TRANSPORT: %d\n"), isTransportReady());
}
void gateway_fail() {
flag_nogateway_mode = true;
flag_update_transport_param = false;
interval1 = interval1 * 10;
}
void check_parent() {
_transportSM.findingParentNode = true;
CORE_DEBUG(PSTR("MyS: SEND FIND PARENT REQUEST, WAIT RESPONSE\n"));
_sendRoute(build(_msg, 255, NODE_SENSOR_ID, C_INTERNAL, 7).set(""));
wait(2500, C_INTERNAL, 8);
if (_msg.sensor == 255) {
if (mGetCommand(_msg) == C_INTERNAL) {
if (_msg.type == 8) {
Ack_FP = true;
CORE_DEBUG(PSTR("MyS: PARENT RESPONSE FOUND\n"));
}
}
}
if (Ack_FP == true) {
CORE_DEBUG(PSTR("MyS: FIND PARENT PROCESS\n"));
Ack_FP = false;
transportSwitchSM(stParent);
flag_nogateway_mode = false;
flag_find_parent_process = true;
} else {
_transportSM.findingParentNode = false;
CORE_DEBUG(PSTR("MyS: PARENT RESPONSE NOT FOUND\n"));
_transportSM.failedUplinkTransmissions = 0;
CORE_DEBUG(PSTR("TRANSPORT: %d\n"), isTransportReady());
}
}
void find_parent_process() {
flag_update_transport_param = true;
flag_find_parent_process = false;
CORE_DEBUG(PSTR("MyS: STANDART TRANSPORT MODE IS RESTORED\n"));
err_delivery_beat = 0;
interval1 = interval1 / 10; // return back to the measurement interval
}