SHARP GP2Y1010AU0F

Показывайте и делитесь своими замечательными проектами здесь! Мы любим картинки!
Ответить
Berk
Сообщения: 81
Зарегистрирован: 11 окт 2017, 22:05

SHARP GP2Y1010AU0F

Сообщение 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]
Вложения
photo_2020-06-28_13-15-03.jpg
photo_2020-06-28_13-15-03.jpg (118.85 КБ) 4480 просмотров
Последний раз редактировалось Berk 06 июл 2020, 17:09, всего редактировалось 1 раз.
Berk
Сообщения: 81
Зарегистрирован: 11 окт 2017, 22:05

Re: SHARP GP2Y1010AU0F

Сообщение 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
}
Ответить