Projekt přítomnost

www
Odpovědět
Uživatelský avatar
Pete30
Moderátor
Moderátor
Příspěvky: 3332
Registrován: 30. září 2020, 20:33
Dal poděkování: 172 poděkování
Dostal poděkování: 364 poděkování

Projekt přítomnost

Příspěvek od Pete30 »

Zatím zde uložím rozpracovaný projekt senzoru přítomnosti a budu v rámci času aktualizovat pro případné zájemce ;)
Část první
Použité díly:
D1 mini
Senzor LD2410 (rozměr 7x35 mm 5 pinů , VCC, GND, TX, RX, OUT napájení 5V)
Konfigurační deska ( vzal jsem ji z důvodu že senzor má rozteč pinů 1,7 mm a to se mi fakt nechtělo pájet
dily senzor cil.jpg
UART:

Kód: Vybrat vše

#include "esphome.h"

#define CHECK_BIT(var, pos) (((var) >> (pos)) & 1)

class LD2410 : public PollingComponent, public UARTDevice
{
public:
  LD2410(UARTComponent *parent) : UARTDevice(parent) {}

  BinarySensor *hasTarget = new BinarySensor();
  BinarySensor *hasMovingTarget = new BinarySensor();
  BinarySensor *hasStillTarget = new BinarySensor();
  BinarySensor *lastCommandSuccess = new BinarySensor();
  Sensor *movingTargetDistance = new Sensor();
  Sensor *movingTargetEnergy = new Sensor();
  Sensor *stillTargetDistance = new Sensor();
  Sensor *stillTargetEnergy = new Sensor();
  Sensor *detectDistance = new Sensor();

  Number *maxMovingDistanceRange;
  Number *maxStillDistanceRange;
  int movingSensitivities[9] = {0};
  int stillSensitivities[9] = {0};
  Number *noneDuration;

  long lastPeriodicMillis = millis();

  void setNumbers(Number *maxMovingDistanceRange_, Number *maxStillDistanceRange_, Number *noneDuration_){
    maxMovingDistanceRange = maxMovingDistanceRange_;
    maxStillDistanceRange = maxStillDistanceRange_;
    noneDuration = noneDuration_;
  }

  void sendCommand(char *commandStr, char *commandValue, int commandValueLen)
  {
    lastCommandSuccess->publish_state(false);
    // frame start bytes
    write_byte(0xFD);
    write_byte(0xFC);
    write_byte(0xFB);
    write_byte(0xFA);
    // length bytes
    int len = 2;
    if (commandValue != nullptr)
      len += commandValueLen;
    write_byte(lowByte(len));
    write_byte(highByte(len));
    // command string bytes
    write_byte(commandStr[0]);
    write_byte(commandStr[1]);
    // command value bytes
    if (commandValue != nullptr)
    {
      for (int i = 0; i < commandValueLen; i++)
      {
        write_byte(commandValue[i]);
      }
    }
    // frame end bytes
    write_byte(0x04);
    write_byte(0x03);
    write_byte(0x02);
    write_byte(0x01);
    delay(50);
  }

  int twoByteToInt(char firstByte, char secondByte)
  {
    return (int16_t)(secondByte << 8) + firstByte;
  }

  void handlePeriodicData(char *buffer, int len)
  {
    if (len < 12)
      return; // 4 frame start bytes + 2 length bytes + 1 data end byte + 1 crc byte + 4 frame end bytes
    if (buffer[0] != 0xF4 || buffer[1] != 0xF3 || buffer[2] != 0xF2 || buffer[3] != 0xF1)
      return; // check 4 frame start bytes
    if (buffer[7] != 0xAA || buffer[len - 6] != 0x55 || buffer[len - 5] != 0x00)
      return; // data head=0xAA, data end=0x55, crc=0x00
    /*
      Data Type: 6th byte
      0x01: Engineering mode
      0x02: Normal mode
    */
    char dataType = buffer[5];
    /*
      Target states: 9th byte
      0x00 = No target
      0x01 = Moving targets
      0x02 = Still targets
      0x03 = Moving+Still targets
    */
    char stateByte = buffer[8];
    hasTarget->publish_state(stateByte != 0x00);
    /*
      Reduce data update rate to prevent home assistant database size glow fast
    */
    long currentMillis = millis();
    if (currentMillis - lastPeriodicMillis < 1000)
      return;
    lastPeriodicMillis = currentMillis;

    hasMovingTarget->publish_state(CHECK_BIT(stateByte, 0));
    hasStillTarget->publish_state(CHECK_BIT(stateByte, 1));

    /*
      Moving target distance: 10~11th bytes
      Moving target energy: 12th byte
      Still target distance: 13~14th bytes
      Still target energy: 15th byte
      Detect distance: 16~17th bytes
    */
    int newMovingTargetDistance = twoByteToInt(buffer[9], buffer[10]);
    if (movingTargetDistance->get_state() != newMovingTargetDistance)
      movingTargetDistance->publish_state(newMovingTargetDistance);
    int newMovingTargetEnergy = buffer[11];
    if (movingTargetEnergy->get_state() != newMovingTargetEnergy)
      movingTargetEnergy->publish_state(newMovingTargetEnergy);
    int newStillTargetDistance = twoByteToInt(buffer[12], buffer[13]);
    if (stillTargetDistance->get_state() != newStillTargetDistance)
      stillTargetDistance->publish_state(newStillTargetDistance);
    int newStillTargetEnergy = buffer[14];
    if (stillTargetEnergy->get_state() != newStillTargetEnergy)
      stillTargetEnergy->publish_state(buffer[14]);
    int newDetectDistance = twoByteToInt(buffer[15], buffer[16]);
    if (detectDistance->get_state() != newDetectDistance)
      detectDistance->publish_state(newDetectDistance);
    if (dataType == 0x01)
    { // engineering mode
      // todo: support engineering mode data
    }
  }

  void handleACKData(char *buffer, int len)
  {
    if (len < 10)
      return;
    if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA)
      return; // check 4 frame start bytes
    if (buffer[7] != 0x01)
      return;
    if (twoByteToInt(buffer[8], buffer[9]) != 0x00)
    {
      lastCommandSuccess->publish_state(false);
      return;
    }
    lastCommandSuccess->publish_state(true);
    switch (buffer[6])
    {
    case 0x61: // Query parameters response
    {
      if (buffer[10] != 0xAA)
        return; // value head=0xAA
      /*
        Moving distance range: 13th byte
        Still distance range: 14th byte
      */
      maxMovingDistanceRange->publish_state(buffer[12]);
      maxStillDistanceRange->publish_state(buffer[13]);
      /*
        Moving Sensitivities: 15~23th bytes
        Still Sensitivities: 24~32th bytes
      */
      for (int i = 0; i < 9; i++)
      {
        movingSensitivities[i] = buffer[14 + i];
      }
      for (int i = 0; i < 9; i++)
      {
        stillSensitivities[i] = buffer[23 + i];
      }
      /*
        None Duration: 33~34th bytes
      */
      noneDuration->publish_state(twoByteToInt(buffer[32], buffer[33]));
    }
    break;
    default:
      break;
    }
  }

  void readline(int readch, char *buffer, int len)
  {
    static int pos = 0;

    if (readch >= 0)
    {
      if (pos < len - 1)
      {
        buffer[pos++] = readch;
        buffer[pos] = 0;
      }
      else
      {
        pos = 0;
      }
      if (pos >= 4)
      {
        if (buffer[pos - 4] == 0xF8 && buffer[pos - 3] == 0xF7 && buffer[pos - 2] == 0xF6 && buffer[pos - 1] == 0xF5)
        {
          handlePeriodicData(buffer, pos);
          pos = 0; // Reset position index ready for next time
        }
        else if (buffer[pos - 4] == 0x04 && buffer[pos - 3] == 0x03 && buffer[pos - 2] == 0x02 && buffer[pos - 1] == 0x01)
        {
          handleACKData(buffer, pos);
          pos = 0; // Reset position index ready for next time
        }
      }
    }
    return;
  }

  void setConfigMode(bool enable)
  {
    char cmd[2] = {enable ? 0xFF : 0xFE, 0x00};
    char value[2] = {0x01, 0x00};
    sendCommand(cmd, enable ? value : nullptr, 2);
  }

  void queryParameters()
  {
    char cmd_query[2] = {0x61, 0x00};
    sendCommand(cmd_query, nullptr, 0);
  }

  void setup() override
  {
    set_update_interval(15000);
  }

  void loop() override
  {
    const int max_line_length = 80;
    static char buffer[max_line_length];
    while (available())
    {
      readline(read(), buffer, max_line_length);
    }
  }

  void setEngineeringMode(bool enable)
  {
    char cmd[2] = {enable ? 0x62 : 0x63, 0x00};
    sendCommand(cmd, nullptr, 0);
  }

  void setMaxDistancesAndNoneDuration(int maxMovingDistanceRange, int maxStillDistanceRange, int noneDuration)
  {
    char cmd[2] = {0x60, 0x00};
    char value[18] = {0x00, 0x00, lowByte(maxMovingDistanceRange), highByte(maxMovingDistanceRange), 0x00, 0x00, 0x01, 0x00, lowByte(maxStillDistanceRange), highByte(maxStillDistanceRange), 0x00, 0x00, 0x02, 0x00, lowByte(noneDuration), highByte(noneDuration), 0x00, 0x00};
    sendCommand(cmd, value, 18);
    queryParameters();
  }

  void factoryReset()
  {
    char cmd[2] = {0xA2, 0x00};
    sendCommand(cmd, nullptr, 0);
  }

  void reboot()
  {
    char cmd[2] = {0xA3, 0x00};
    sendCommand(cmd, nullptr, 0);
    // not need to exit config mode because the ld2410 will reboot automatically
  }

  void setBaudrate(int index)
  {
    char cmd[2] = {0xA1, 0x00};
    char value[2] = {index, 0x00};
    sendCommand(cmd, value, 2);
  }

  void update()
  {
  }
};
konfigurace yaml:

Kód: Vybrat vše

esphome:
  name: ld2410
  includes:
    - components/senzor_pritomnost/ld2410_uart.h
  on_boot:
    priority: 600
    # ...
    then:
      - lambda: |-
          auto uart_component = static_cast<LD2410 *>(ld2410);
          uart_component->setNumbers(maxMovingDistanceRange, maxStillDistanceRange, noneDuration);

esp8266:
  board: d1_mini

logger:
  baud_rate: 0

api:

ota:

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  ap:
    ssid: "LD2410 Fallback Hotspot"

captive_portal:

uart:
  id: uart1
  tx_pin: TX
  rx_pin: RX
  baud_rate: 256000 # Změňit podle sebe v nastavení
  parity: NONE
  stop_bits: 1
  debug:
    direction: BOTH
    dummy_receiver: false
    after:
      delimiter: [0xF8,0xF7,0xF6,0xF5]
      
custom_component:
  - lambda: |-
      return {new LD2410(id(uart1))};
    components:
      - id: ld2410
      
binary_sensor:
  - platform: custom
    lambda: |-
      auto uart_component = static_cast<LD2410 *>(ld2410);
      return {uart_component->hasTarget,uart_component->hasMovingTarget,uart_component->hasStillTarget,uart_component->lastCommandSuccess};
    binary_sensors:
      - name: "Cíl"
      - name: "Pohyb cíl"
      - name: "Stále cíl"
      - name: "Úspěch příkazu"
  
sensor:
  - platform: custom
    lambda: |-
      auto uart_component = static_cast<LD2410 *>(ld2410);
      return {uart_component->movingTargetDistance,uart_component->movingTargetEnergy,uart_component->stillTargetDistance,uart_component->stillTargetEnergy,uart_component->detectDistance};
    sensors:
      - name: "Pohyb cíl vzdálenost"
        unit_of_measurement: "cm"
        accuracy_decimals: 0
      - name: "Pohyb cíl energie"
        unit_of_measurement: "%"
        accuracy_decimals: 0
      - name: "Stále cíl vzdálenost"
        unit_of_measurement: "cm"
        accuracy_decimals: 0
      - name: "Stále cíl energie"
        unit_of_measurement: "%"
        accuracy_decimals: 0
      - name: "Detekce vzdálenosti"
        unit_of_measurement: "cm"
        accuracy_decimals: 0

number:        
  - platform: template
    name: "Max rozsah pohyb vzdálenost"
    id: maxMovingDistanceRange
    min_value: 1
    max_value: 8
    step: 1
    update_interval: never
    optimistic: true
    set_action:
      - lambda: |-
          auto uart_component = static_cast<LD2410 *>(ld2410);
          uart_component->setMaxDistancesAndNoneDuration(x,id(maxStillDistanceRange).state,id(noneDuration).state);
  - platform: template
    name: "Max rozsah stále vzdálenost"
    id: maxStillDistanceRange
    min_value: 1
    max_value: 8
    step: 1
    update_interval: never
    optimistic: true
    set_action:
      - lambda: |-
          auto uart_component = static_cast<LD2410 *>(ld2410);
          uart_component->setMaxDistancesAndNoneDuration(id(maxMovingDistanceRange).state,x,id(noneDuration).state);
  - platform: template
    name: "Doba trvání"
    id: noneDuration
    min_value: 0
    max_value: 32767
    step: 1
    mode: box
    update_interval: never
    optimistic: true
    set_action:
      - lambda: |-
          auto uart_component = static_cast<LD2410 *>(ld2410);
          uart_component->setMaxDistancesAndNoneDuration(id(maxMovingDistanceRange).state,id(maxStillDistanceRange).state,x);
      

button:
  - platform: template
    name: "Reboot LD2410"
    on_press:
      lambda: 'static_cast<LD2410 *>(ld2410)->reboot();'
  - platform: template
    name: "Zapnout režim konfigurace"
    on_press:
      - lambda: 'static_cast<LD2410 *>(ld2410)->setConfigMode(true);'
  - platform: template
    name: "Vypnout režim konfigurace"
    on_press:
      - lambda: 'static_cast<LD2410 *>(ld2410)->setConfigMode(false);'
  - platform: template
    name: "Stáhnout konfiguraci"
    on_press:
      - lambda: 'static_cast<LD2410 *>(ld2410)->queryParameters();'
  - platform: template
    name: "Nastav rychlost na 256000"
    on_press:
      - lambda: 'static_cast<LD2410 *>(ld2410)->setBaudrate(7);'
  - platform: template
    name: "Nastav rychlost na 115200"
    on_press:
      - lambda: 'static_cast<LD2410 *>(ld2410)->setBaudrate(5);'
  - platform: template
    name: "Nastav rychlost na 9600"
    on_press:
      - lambda: 'static_cast<LD2410 *>(ld2410)->setBaudrate(1);'
náhledy:
senzory 2410.png
ovladaci prvky 2410.png
zaznam 2410.png
Senzor pracuje na 24Ghz a má tu možnost že detekuje jako binární senzor a současně jako přítomnost a to i bez pohybu na vzdálenost cca 5m.
Prozatím jsem ho jen rozjel a nejsou žádné testy.
Zatím funguje bez problému, ale uvidíme jak se bude chovat při různých nastavení vzdálenosti a úhlu.
Zatím jen takový bastl na stole :lol:
bastl na stole.jpg
Led červená že je pod napětím a zelená, detekuje mě jako přítomnost
Pokud nejsem přítomen tak jsem na rybách ;)

Uživatelský avatar
Pete30
Moderátor
Moderátor
Příspěvky: 3332
Registrován: 30. září 2020, 20:33
Dal poděkování: 172 poděkování
Dostal poděkování: 364 poděkování

Re: Projekt přítomnost

Příspěvek od Pete30 »

Část 2
V prví části jsem zmínil uart a yaml kde jsem zjistil že kódování není moc dobré a to proto že při konfiguraci senzoru docházelo ke zhroucení komunikace přes uart a senzory hlásí neznámé.
Po dalších experimentech u senzorů zůstal trvalý stav neznámé a nic nejde vrátit zpět ani použitím jiné desky esp D1 mini.
Jediné co fungovalo byl out senzoru který se dal použít jako binární senzor, ale bez možnosti jiných nastavení.
Použil jsem další kódování z vlákna en fóra, který byl vytvořen pro esp32, nicméně jsem ho vyzkoušel s tím že jsem upravil yaml pro použití s deskou D1 mini a tím se dostal zpátky do hry
schema radar.png
schema radar on.png
Po dalších testech bude doplněno o všechny nezbytné soubory a nastavení včetně dalších informací, jen to bude nějaký čas trvat ;)
Ještě budu objednávat další senzory LD2410 nebo LD2410B protože se mi zdají jako skvělá náhrada klasických pohybových senzorů.
Další testy budou ještě se senzorem LD1115H které mi zde leží jen u nich tuším nejde nastavit citlivost nebo vzdálenost.
Pokud nejsem přítomen tak jsem na rybách ;)

Uživatelský avatar
Pete30
Moderátor
Moderátor
Příspěvky: 3332
Registrován: 30. září 2020, 20:33
Dal poděkování: 172 poděkování
Dostal poděkování: 364 poděkování

Re: Projekt přítomnost

Příspěvek od Pete30 »

Senzory LD2410 jsem prozatím odložil a čekám na dodávku vlastně stejných jen s tím rozdílem že mají označení LD2410B.
Jsou to stejné senzory jen je jejich výhodou nastavení přes BT v aplikaci telefonu. Uvidíme až dorazí.
Prozatím jsem rozběhl senzory LD1115H které se dají docela dobře konfigurovat přes UART.
Po několika dnech testování vše vypadá slibně. Prozatím jeden senzor funguje v kuchyni kde ovládá led pásky pod linkou a nedochází k vypnutí senzoru když jsem přítomen v kterékoliv části místnosti a nepohybuji se.
Hodně záleží na nastavení citlivosti a správné nasměrování senzoru (mám ho v rohu místnosti ve výšce 2,3 m) potom je účinnost 100%.
Senzor zabírá v úhlu cca 57 stupňů do vzdálenosti asi 5 m (maximální vzdálenost zatím netestována).
Senzor je zatím stále v testovacím režimu, ale za pár dnů bude přesunut na jiné esp kde bude nastaven pouze jednoduchý binární senzor protože nastavení v senzoru zůstává.
Pro případné zájemce až budu mít 100% jistotu doplním vlastní komponentu UART a yaml pro esp32, příklady nastavení s vysvětlením na čem záleží.
Zde je přibližná účinnost senzoru:
LD1115H diagram1.png
LD1115H diagram2.png
Náhled nastavení v testu
Nastavení LD1115H.png
Toto je jen rychlá informace a pokračování bude v části 4.
Pokud nejsem přítomen tak jsem na rybách ;)

Uživatelský avatar
Pete30
Moderátor
Moderátor
Příspěvky: 3332
Registrován: 30. září 2020, 20:33
Dal poděkování: 172 poděkování
Dostal poděkování: 364 poděkování

Re: Projekt přítomnost

Příspěvek od Pete30 »

Projekt přítomnost se senzorem LD1115H dokončen.
Do projektu je potřeba zahrnout soubor uart_read_line_sensor_ld1115h.h
zde:

Kód: Vybrat vše

#include "esphome.h"
#include <string>

class hilink : public Component, public UARTDevice {
 public:
  hilink(UARTComponent *parent) : UARTDevice(parent) {}
  Sensor *mov_SNR = new Sensor();
  Sensor *occ_SNR = new Sensor();
  void setup() override {
    //
  }

  void getmmwConf(std::string mmwparam) {
    mmwparam = mmwparam + "\n";
    write_array(std::vector<unsigned char>(mmwparam.begin(), mmwparam.end()));
  }

  int readline(int readch, char *buffer, int len)
  {
    static int pos = 0;
    int rpos;

    if (readch > 0) {
      switch (readch) {
        case '\n': // Ignore new-lines
          break;
        case '\r': // Return on new-lines
          rpos = pos;
          pos = 0;  // Reset position index ready for next time
          return rpos;
        default:
          if (pos < len-1) {
            buffer[pos++] = readch;
            buffer[pos] = 0;
          }
      }
    }
    // No end of line has been found, so return -1.
    return -1;
  }

  void loop() override {
    const int max_line_length = 80;
    static char buffer[max_line_length];

    while (available()) {
      if(readline(read(), buffer, max_line_length) > 0) {
        std::string line = buffer;

        //ESP_LOGD("custom", "Line is: %s", line.c_str());
        if (line.substr(0,3) == "th1") {
          ESP_LOGD("custom", "Found th1: %s", line.c_str());
          id(mov_SNR_target).publish_state(parse_number<int>(line.substr(7)).value());
        }
        else if (line.substr(0,3) == "th2") {
          ESP_LOGD("custom", "Found th2: %s", line.c_str());
          id(occ_SNR_target).publish_state(parse_number<int>(line.substr(7)).value());
        }
        else if (line.substr(0,3) == "th3") {
          ESP_LOGD("custom", "Found th3: %s", line.c_str());
          id(th3_SNR_target).publish_state(parse_number<int>(line.substr(7)).value());
        }
        else if (line.substr(0,7) == "ind_min") {
          ESP_LOGD("custom", "Found ind_min: %s", line.c_str());
          id(ind_min).publish_state(parse_number<int>(line.substr(11)).value());
        }
        else if (line.substr(0,7) == "ind_max") {
          ESP_LOGD("custom", "Found ind_max: %s", line.c_str());
          id(ind_max).publish_state(parse_number<int>(line.substr(11)).value());
        }
        else if (line.substr(0,6) == "mov_sn") {
          ESP_LOGD("custom", "Found mov_sn: %s", line.c_str());
          id(mov_sn).publish_state(parse_number<int>(line.substr(10)).value());
        }
        else if (line.substr(0,6) == "occ_sn") {
          ESP_LOGD("custom", "Found occ_sn: %s", line.c_str());
          id(occ_sn).publish_state(parse_number<int>(line.substr(10)).value());
        }
        else if (line.substr(0,5) == "dtime") {
          ESP_LOGD("custom", "Found dtime: '%s'", line.c_str());
          std::string dtime_str = line.substr(9,(line.length() - 12));
          int dtime_ms = parse_number<int>(dtime_str).value();
          ESP_LOGD("custom", "Found dtime_ms: %i", dtime_ms);
          id(dtime).publish_state(dtime_ms/1000);
        }
        if (line.substr(0,4) == "mov," && id(show_SNR).state) {
          // ESP_LOGD("custom", "Found occ_sn: %s", line.c_str());
          mov_SNR->publish_state(parse_number<int>(line.substr(7)).value());
        }
        else if (line.substr(0,4) == "occ," && id(show_SNR).state) {
          // ESP_LOGD("custom", "Found occ_sn: %s", line.c_str());
          occ_SNR->publish_state(parse_number<int>(line.substr(7)).value());
        }
      }
    }
  }
};
Potom je zde konfigurace uzlu esp která v HA odhalí 1 zařízení a 11 entit kde se dá vše pohodlně nastavit.
Přidal jsem ledku pro kontrolu on/off snímače.
zde:

Kód: Vybrat vše

esphome:
  name: xxxxxxxx
  platform: ESP32
  board: esp32dev
  includes:
    - components/radar_senzor/uart_read_line_sensor_ld1115h.h

# Enable logging
logger:
  level: INFO

# Povolit Home Assistant API
api:
  reboot_timeout: 6h
  services:
      # Služba pro odeslání příkazu přímo na displej. Užitečné pro testování
    - service: send_command
      variables:
        cmd: string
      then:
        - uart.write: !lambda
            std::string command = to_string(cmd) +"\n";
            return std::vector<uint8_t>(command.begin(), command.end());

ota:
  password: xxxxxxxx

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Povolit záložní hotspot (captive portál) pro případ, že selže připojení wifi
  ap:
    password: xxxxxxxxx

substitutions:
  device_name: xxxxxxxxxx

captive_portal:

uart:
  id: uart_bus
  tx_pin: GPIO5
  rx_pin: GPIO18
  baud_rate: 115200

binary_sensor:
  - platform: gpio
    name: xxxxxxxxx
    id: radar_kuchyne_ld1115h
    device_class: motion
    pin:
      number: GPIO33
      mode: INPUT_PULLDOWN
    on_state:
      then:
        - if:
            condition:
              - binary_sensor.is_off: radar_kuchyne_ld1115h
            then:
              - lambda: |-
                  id(mov_SNR).publish_state(0.0);
                  id(occ_SNR).publish_state(0.0);

interval:
  - interval: 2s
    then:
      if:
        condition:
          binary_sensor.is_on: radar_kuchyne_ld1115h
        then:
          - switch.turn_on: led_radar
          - delay: 1s
          - switch.turn_off: led_radar
        else:
          - switch.turn_off: led_radar

text_sensor:
  - platform: template
    name: Doba provozu
    id: uptime_human_readable
    icon: mdi:clock-start
    update_interval: 60s

sensor:
  - platform: uptime
    name: Provoz sensoru
    id: uptime_sensor
    update_interval: 60s
    internal: true
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human_readable
            state: !lambda |-
                      int seconds = round(id(uptime_sensor).raw_state);
                      int days = seconds / (24 * 3600);
                      seconds = seconds % (24 * 3600);
                      int hours = seconds / 3600;
                      seconds = seconds % 3600;
                      int minutes = seconds /  60;
                      seconds = seconds % 60;
                      return (
                        (days ? to_string(days)+":" : "00:") +
                        (hours ? to_string(hours)+":" : "00:") +
                        (minutes ? to_string(minutes)+":" : "00:") +
                        (to_string(seconds))
                      ).c_str();

  - platform: custom
    lambda: |-
      auto s = new hilink(id(uart_bus));
      App.register_component(s);
      //return {};
      return {s->mov_SNR, s->occ_SNR};
    sensors:
      - name: mov_SNR
        id: mov_SNR
        internal: true
      
      - name: occ_SNR
        id: occ_SNR
        internal: true

switch:
  - platform: template
    name: Zobrazit SNR
    id: show_SNR
    internal: true
    optimistic: true
    turn_off_action:
      - lambda: |-
          id(mov_SNR).publish_state(0.0);
          id(occ_SNR).publish_state(0.0);
  - platform: gpio
    pin: GPIO21
    id: 'led_radar'
    name: Led radar
    internal: true

number:
  - platform: template
    name: dtime
    id: dtime # neměňit
    entity_category: config
    min_value: 1
    max_value: 600
    lambda: |-
      hilink(id(uart_bus)).getmmwConf("get_all");
      return {};
    step: 1
    unit_of_measurement: s
    mode: box
    set_action:
      - uart.write: !lambda
          std::string setdtime = "dtime=" + to_string((int)x);
          return std::vector<unsigned char>(setdtime.begin(), setdtime.end());
      - delay: 250ms
      - uart.write: "save\n"

  - platform: template
    name: mov_SNR_cílová
    id: mov_SNR_target # neměňit
    entity_category: config
    min_value: 0
    max_value: 65536
    mode: box
    optimistic: true
    step: 1
    set_action:
      - uart.write: !lambda
          std::string setth1 = "th1=" + to_string((int)x);
          return std::vector<unsigned char>(setth1.begin(), setth1.end());
      - delay: 250ms
      - uart.write: "save\n"

  - platform: template
    name: th3_SNR_cíl dlouhá vzdálenost
    id: th3_SNR_target # neměnit
    entity_category: config
    min_value: 0
    max_value: 65536
    mode: box
    optimistic: true
    step: 1
    set_action:
      - uart.write: !lambda
          std::string setth3 = "th3=" + to_string((int)x);
          return std::vector<unsigned char>(setth3.begin(), setth3.end());
      - delay: 250ms
      - uart.write: "save\n"

  - platform: template
    name: occ_SNR_cílová
    id: occ_SNR_target # neměnit
    entity_category: config
    min_value: 0
    max_value: 65536
    mode: box
    optimistic: true
    step: 1
    set_action:
      - uart.write: !lambda
          std::string setth2 = "th2=" + to_string((int)x);
          return std::vector<unsigned char>(setth2.begin(), setth2.end());
      - delay: 250ms
      - uart.write: "save\n"
      
  - platform: template
    name: ind_min
    id: ind_min # neměnit
    entity_category: config
    min_value: 0
    max_value: 32
    mode: box 
    optimistic: true
    step: 1
    set_action:
      - uart.write: !lambda
          std::string setind_min = "ind_min=" + to_string((int)x);
          return std::vector<unsigned char>(setind_min.begin(), setind_min.end());
      - delay: 250ms
      - uart.write: "save\n"

  - platform: template
    name: ind_max
    id: ind_max # neměnit
    entity_category: config
    min_value: 0
    max_value: 32
    mode: box 
    optimistic: true
    step: 1
    set_action:
      - uart.write: !lambda
          std::string setind_max = "ind_max=" + to_string((int)x);
          return std::vector<unsigned char>(setind_max.begin(), setind_max.end());
      - delay: 250ms
      - uart.write: "save\n"

  - platform: template
    name: mov_sn
    id: mov_sn # neměnit
    entity_category: config
    min_value: 0
    max_value: 4
    mode: box 
    optimistic: true
    step: 1
    set_action:
      - uart.write: !lambda
          std::string setmov_sn = "mov_sn=" + to_string((int)x);
          return std::vector<unsigned char>(setmov_sn.begin(), setmov_sn.end());
      - delay: 250ms
      - uart.write: "save\n"

  - platform: template
    name: occ_sn
    id: occ_sn # neměnit
    entity_category: config
    min_value: 0
    max_value: 16
    mode: box 
    optimistic: true
    step: 1
    set_action:
      - uart.write: !lambda
          std::string setocc_sn = "occ_sn=" + to_string((int)x);
          return std::vector<unsigned char>(setocc_sn.begin(), setocc_sn.end());
      - delay: 250ms
      - uart.write: "save\n"

button:
  - platform: restart
    name: Restart $device_name
    entity_category: diagnostic 
Na čem nejvíce záleží je hodnota occ_SNR_cílová a occ_sn čímž se nastaví citlivost snímače pro přítomnost.
Zjistil jsem že nižší hodnota znamená vyšší citlivost.
Hodnoty mov_SNR_cílová a mov_sn je nastavení binárního snímače pro pohyb.
Hodnota th3_SNR_cíl dlouhá vzdálenost ovlivňuje na jakou vzdálenost vás snímač vidí je lepší použít nižší hodnotu jinak vás zaznamená až na vzdálenost 16 m.
Hodnoty ind_max a ind_min jsem zkoušel různá nastavení, ale bohužel jsem nepřišel co ovlivňují (nepozoroval jsem žádnou změnu ).
Poslední hodnota je dtime a to je čas po který počká pokud vyhodnotí že v dosahu není nikdo přítomen a to trvá cca 10 s.

Specifikace převzata z netu:
Frekvence 24G-24,5GHz
Modulační metoda CW
Detekční vzdálenost > 4 m statická detekce lidské přítomnosti, > 16 m detekce pohybu
Dosah výška umístění 3 m, poloměr pokrytí statické detekce těla 2 m, poloměr mobilní detekce > 5 m
Napájení 3,6-5V
Proud 70mA
Výstupní sériová úroveň 3,3V
Adaptivní detekční cyklus
Úhel polovičního výkonu antény horizontální ±57°, vertikální ±24°
Formát dat Sériový port ASCII výstup/vysoká a nízká úroveň
Doba spouštění cca 15 sekund

Upozornění:
Nastavení senzoru je individuální pro každé prostředí proto neberte tabulku nastaveni výše jako finální pro svoje prostředí.
Je nutné si to nastavit tam kde bude snímač umístěn, jak parametry tak vertikální i horizontální úhel.
Nemusí být umístěn na stropě, ale i na stěně jako klasický pir senzor ( mám ho ve výšce více jak 2m a nakloněn v úhlu 20° ).

Hodnocení:
Po cca měsíčním testování mohu hodnotit zatím jako nejlepší senzor přítomnosti.
Po vyladění nastavení 100% záchytů přítomnosti i aktivní doba pokud je osoba přítomna v místnosti, po 10-12s přechází do stavu nečinnosti a automatizace zapíná a vypíná světlo pod kuchyňskou linkou.
Pokrývám s ním kuchyni cca 4x3 m.
Pro dnešek zatím vše jen ještě náhled do čeho jsem to nacpal :lol:
LD1115H krabicka.jpg
V další části budeme pokračovat se senzorem LD2410B a jeho nastavení pomocí BT ;)
Pokud nejsem přítomen tak jsem na rybách ;)

Uživatelský avatar
Pete30
Moderátor
Moderátor
Příspěvky: 3332
Registrován: 30. září 2020, 20:33
Dal poděkování: 172 poděkování
Dostal poděkování: 364 poděkování

Re: Projekt přítomnost

Příspěvek od Pete30 »

Blížíme se k závěru a to seznámením se s app Android HLKradar pro nastavení senzoru LD2410B.
Zde je náhled app, je čínsky, ale pro případné zájemce mám udělány screny a přeloženy do cz.
app HLKradar 1_a.jpg
app HLKradar 2_a.jpg
app HLKradar 3_a.jpg
Ve své podstatě má app 3 stránky, na úvodní při spuštění začne vyhledávat přes BT senzory v dosahu.
Operační vzdálenost je cca 4 m.
Po načtení uvidíte nalezený senzor a jeho MAC adresu, pokud ho vyberete dostáváte se na další stranu kde je přehled o vzdálenosti, přítomnosti, čas nepřítomnost a pohyb včetně grafů průběhu jednotlivých událostí.
Pro zobrazení grafu pohyb a přítomnost v reálném čase je třeba zapnout přepínač v horní části obrazovky.
Spodní graf zobrazuje vzdálenost.
V horní části je také tlačítko na přesun do nastavení, nastavit a uložit lze pouze při vypnutém ing. režimu.
Na poslední straně je přehled nastavení verze fw, heslo, přenosová rychlost (pokud nastavujete přes sériovou linku),
počet zón a tabulka nastavení pro jednotlivé zóny, citlivost, pohyb, přítomnost.
Senzor má 8 aktivních zón a každá se dá konfigurovat samostatně. Vzdálenost(rozsah v m) zóny je na výběr 0,2 nebo 0,75m
Ve spodní části je nastavení celkové citlivosti na pohyb a přítomnost.
Vyzkoušel jsem nějaká nastavení a ano funguje to. Až bude čas umístím ho do nějaké krabičky abych mohl testovat v další místnosti. Jen pro zajímavost, senzor LD2410B je rychlejší než LD1115H, dokáže vyhodnotit stav on(okamžitě)/off do 2-3s které jsem nastavil v konfiguraci. Oba senzory se pohodlně integrují přes modul esp do HA protože mají napájení 5V, TX, RX a out 3,3V.

Ještě doplním že se jedná o senzory na principu radaru proto dejte pozor do jakého prostředí je instalujete protože dokáží zaznamenat pohybující záclonu v průvanu, běžící ventilátor atd, ale to se dá odladit nastavením zón..
Pokud nejsem přítomen tak jsem na rybách ;)

Uživatelský avatar
Pete30
Moderátor
Moderátor
Příspěvky: 3332
Registrován: 30. září 2020, 20:33
Dal poděkování: 172 poděkování
Dostal poděkování: 364 poděkování

Re: Projekt přítomnost

Příspěvek od Pete30 »

Až budou výsledky testů senzoru LD2410B zveřejním je zde.
Pokud nejsem přítomen tak jsem na rybách ;)

Uživatelský avatar
Pete30
Moderátor
Moderátor
Příspěvky: 3332
Registrován: 30. září 2020, 20:33
Dal poděkování: 172 poděkování
Dostal poděkování: 364 poděkování

Re: Projekt přítomnost

Příspěvek od Pete30 »

V poslední verzi HA tu máme novinku a to integraci LD2410BT.
Ze senzoru je možné vyčítat informace přes BT a jsou vytvořeny entity přítomnost a pohyb senzor, k celému provozu stačí pouze 2 vodiče napájení senzoru 5V viz náhled:
LD2410BT.png
Pokud nejsem přítomen tak jsem na rybách ;)

Uživatelský avatar
Pete30
Moderátor
Moderátor
Příspěvky: 3332
Registrován: 30. září 2020, 20:33
Dal poděkování: 172 poděkování
Dostal poděkování: 364 poděkování

Re: Projekt přítomnost

Příspěvek od Pete30 »

Máme tu další překvapení v podobě aktualizace ESPhome, která přinesla nativní podpozu senzoru LD2410.
Mám ho zde připraven k sestavení na D1 mini a po zprovoznění podám report :link:
https://esphome.io/components/sensor/ld2410.html
Pokud nejsem přítomen tak jsem na rybách ;)

Uživatelský avatar
okoun
Dárce - Donátor
Dárce - Donátor
Příspěvky: 509
Registrován: 30. prosinec 2022, 21:19
Dal poděkování: 20 poděkování
Dostal poděkování: 7 poděkování

Re: Projekt přítomnost

Příspěvek od okoun »

detekcí správné přítomnosti se už nějaký čas zabývám, používám pohybová čidla shelly, je to sice drahotka, ale nějak to funguje, nicméně chtěl jsem se zeptat jestli je nějaké čidlo, které řeší pasivní přítomnost, například sedím u PC v kanceláři a nehýbu se, bohužel tyhle obyč čidla jsou bez šance a dokud se pořádně nepohnu tak jsem v háji.
nějaké nápady jak tohle vyřešit prosím?

Děkuji

modern
Aktivní autor
Aktivní autor
Příspěvky: 54
Registrován: 20. říjen 2020, 13:46
Dal poděkování: 5 poděkování
Dostal poděkování: 4 poděkování

Re: Projekt přítomnost

Příspěvek od modern »

Já jsem velmi spokojen s tímto sensorem přítomnosti Tuya zigbee . .. https://www.aliexpress.com/item/1005004 ... 8021M4rLz

Odpovědět

Zpět na „ESPHome“