Парсер показаний умных розеток и выключателей на BL0942

Fisher15

✩✩✩✩✩✩✩
13 Фев 2023
4
3
Парсер позволяет получать данные напряжения, тока, мощности, потребленной энергии с умных розеток и выключателей для использования этих данных и стандартного функционала розеток (включение выключение через типовые приложения со смартфона) в своих проектах. Работоспособность и управляемость умной розетки при этом полностью сохраняется. Розетка используется помимо своей основной функции в качестве измерительного датчика. Парсер подходит для умных розеток с мониторингом мощности, собранных на связке BL0942 и CS2B (почти все розетки и выключатели с мониторингом мощности выпущенные в 2022-2024 годах нижнего ценового диапазона (Mini Smart Switch, Ausess Power Monitor Switch, проходные розетки с кнопкой и т.д. - платы у них разные, но схемы у них идентичны). Готовой библиотеки для BL0942 в интернетах не нашлось. Парсер работает на ардуино и ESP32 без изменений в коде, библиотеки не нужны. Парсятся пакеты, отправляемые BL0942 в ответ на запрос управляющего модуля розетки. Если не нужна гальваническая развязка, ардуину или ESP32 можно питать от 5 вольт внутреннего источника розетки, и соединить RX ардуины с RX CS2B розетки (он соединен с TX BL0942). Я подключал через гальваническую развязку - оптопару PS2501 и ключ с открытым коллектором на транзисторе. На фото издевательство над Mini Smart Switch.20240730_192105.jpg20240803_171736.jpg20240804_154100.jpg1505695300_1649892667.png9075417700_1649892657.pngopto.png
 

Вложения

Fisher15

✩✩✩✩✩✩✩
13 Фев 2023
4
3
@Эдуард Анисимов, например для логгирования параметров питающей сети, потребляемой мощности .... есть конечно готовые устройства, вроде https://aliexpress.ru/item/33043137964.html , но это нужно заказывать, ждать, а умные розетки легко купить онлайн, или они просто уже есть
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,947
620
44
но это нужно заказывать, ждать
А "умные" розетки не нужно заказывать, ждать?
Уж лучше купить готовое устройство, которое подходит например для Home Assistant, чем с нуля писать оболочку к самодельному.
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,353
963
58
Марий-Эл
@Fisher15, Какая то херь включена в розетку.
Мы имеем статистику с указанием её потребления.
Но мы не можем ничего сделать с этой херью. Поэтому она жрёт как обычно не взирая на статистику.
И мы платим за то, что она жрёт.
Теперь глупый вопрос - зачем собирать статистику, если эта херь будет продолжать жрать и зачем нужна статистика, если платить всё равно придётся????????????????????
 

Fisher15

✩✩✩✩✩✩✩
13 Фев 2023
4
3
Господа, если вам это не нужно, или вы не понимаете, зачем это нужно - просто пройдите мимо. На данный момент это единственная в интернете практически готовая библиотека под ардуино для BL0942. Кому нужен самый дешевый и доступный вариант повер монитора под проект - тот возьмет, допилит или перепилит под свои нужды... Зачем попусту трясти воздух?
 

Bruzzer

★★★✩✩✩✩
23 Май 2020
412
126
@Fisher15,
Я не в теме умных розеток, но потребление периодически измеряю "обычным" ваттметром.
Несколько замечаний с учетом этого.
На мой взгляд не хватает начального описания,
  • Для чего это нужно. Возможно считывание через WiFi приложение имеет сложности, возможно другие причины.
  • Принцип работы. Из текста понятно, что читается отправка сообщений от BL0942, но непонятно всегда ли розетка запрашивает у него эти данные, и с какой частотой.

В алгоритме парсера есть непонятные моменты. И на мой взгляд если это возможный пример, то это плохой пример.

  • int rlen = Serial.readBytesUntil('\n', buf, BUFFER_SIZE); Результат rlen негде не используется, хотя "по хорошему" должна проверяться.
  • Зачем Serial.readBytesUntil('\n', buf, BUFFER_SIZE); читается до '\n' В даташите не указано, что в пакетах есть '\n'
  • не понятно за счет чего происходит синхронизация. Ведь у BL0942 могут запрашивать не все параметры одним пакетом 23 Байт, а по отдельности пакетами по 4 Байт. Возможно это достигается за счет длительных пауз между пакетами. Было бы полезно описать этот момент. Так же в пакете 23 Байт есть заголовок 0x55 и нулевые байты в STATUS, которые можно использовать для определения начала пакета.
  • Если какой то параметр недостоверен, то на мой взгляд логично считать и остальные параметры не достоверными
Parser_BL0924.ino:
// Парсер BL0942
// Подходит для проектов на ардуино и ESP32 (без изменений в коде) с использованием данных умных розеток и выключателей с измерением мощности, собранных на BL0942 и CB2S
// (почти все розетки и выключатели нижнего ценового диапазона выпущенные в 2022-2024г)
// Mini Smart Switch, Ausess Power Monitor Switch, проходные розетки с кнопкой и т.д. Работоспособность розетки полностью сохраняется. Удобнее всего использовать Mini Smart Switch, в нем оптопара легко размещается под крышкой
// корпуса розетки, и корпус розетки с установленной оптопарой штатно закрывается.
// Парсер получает из данных обмена между BL0942 и CB2S напряжение сети, ток, мощность, потребленную энергию.
// Для гальванической развязки необходимо использовать оптопару (использовалась первая попавшаяся NEC PS2501).
// Светодиод оптопары подключается выходу TX BL0942 (входу RX CB2S, они соединены), другая нога светодиода на +3.3 розетки через резистор 470 Ом.
// К выводам оптотранзистора оптопары припаиваются два провода, тщательно изолируются и выводятся из корпуса розетки. У меня работало с длинной этих проводов 15 см до ключа, но желательно их делать как можно короче.
// Оптотранзистор управляет ключем (открытым коллектором), собранным на любом транзисторе. Выход с коллектора ключа подключаем к RX ардуино или ESP32. На время прошивки это подключение от ардуино нужно отключать.
//--------------------------------------------------------------------------------------------
const int BUFFER_SIZE = 23; //  Число байт в пакете, получаемом от BL0942
char buf[BUFFER_SIZE]; // Создаем массив для хранения пакета побайтово
uint32_t raw_unscaled_voltage;
uint32_t raw_unscaled_tok;
uint32_t raw_unscaled_power;
uint32_t raw_unscaled_energy;
float newVoltage;
float newTok;
float newPower;
float newEnergy;
float goodVoltage = 0;
float goodTok = 0;
float goodPower = 0;
float goodEnergy = 0;
float BL0942_PREF = 646; //598   Подобрать офсет  чтобы мощность в приложении на смартфоне  и в мониторе порта совпадали
float BL0942_UREF = 16170; //15188   Подобрать офсет  чтобы напряжение  в приложении на смартфоне и в мониторе порта совпадали
float BL0942_IREF = 267417; //251210   Подобрать офсет  чтобы ток в приложении на смартфоне и в мониторе порта совпадали
float BL0942_WREF = 3333; //11111   Подобрать офсет  чтобы киловатт часы  в приложении на смартфоне и в мониторе порта совпадали
void setup() {
  Serial.begin(4800); // BL0942 как правило обменивается данными на скорости 4800, монитор порта в Arduino IDE во время отладки необходимо так жк переключить на эту скорость
  Serial.setTimeout(100);
}
void loop() {
    if (Serial.available() > 0) {
        int rlen = Serial.readBytesUntil('\n', buf, BUFFER_SIZE);
        // Расчет и проверка контрольной суммы пакета
        unsigned char cs = 0x58;
        unsigned char realCS = buf[22]; // берем значение контрольной суммы из пакета - оно в конце пакета
        for(int j = 0; j < 22; j++) { // считаем контрольную сумму данных в пакете
        cs+=buf[ j ]; }
        cs ^= 0xFF;
        if(cs == realCS){  // сравниваем рассчитанную и полученную контрольные суммы, если все впорядке - погнали
            Serial.print("Packet from BL9042 test Ok\n"); // пакет целый
            //Извлечение из пакета напряжения, тока, мощности
            raw_unscaled_voltage = ((uint32_t)buf[6] << 16) | ((uint32_t)buf[5] << 8) | ((uint32_t)buf[4]); // извлекаем напряжение по мнению BL0942
            newVoltage = (raw_unscaled_voltage / BL0942_UREF); // приводим напряжение к Вольтам
            if ( newVoltage < 1000) { goodVoltage = newVoltage; } // проверяем на валидность, если напряжение в разумных пределах - запоминаем (невалидное значение больше реального в тысячи раз)
            raw_unscaled_tok = ((uint32_t)buf[3] << 16) | ((uint32_t)buf[2] << 8) | ((uint32_t)buf[1]); ; // извлекаем средневзвешенный ток по мнению BL0942
            newTok = (raw_unscaled_tok / BL0942_IREF);  // приводим ток к Амперам
            if ( newTok < 16) { goodTok = newTok; } // проверяем на валидность, если ток в разумных пределах - запоминаем (невалидное значение больше реального в тысячи раз)
            raw_unscaled_power = ((uint32_t)buf[12] << 16) | ((uint32_t)buf[11] << 8) | ((uint32_t)buf[10]);; // извлекаем средневзвешенную мощность по мнению BL0942
            newPower = (raw_unscaled_power / BL0942_PREF);  // приводим мощность к Ваттам
            if ( newPower < 16000) { goodPower = newPower; } // проверяем на валидность, если мощность в разумных пределах - запоминаем (невалидное значение больше реального в тысячи раз)
            raw_unscaled_energy = ((uint32_t)buf[15] << 16) | ((uint32_t)buf[14] << 8) | ((uint32_t)buf[13]);; // извлекаем потребленную энергию по мнению BL0942
            newEnergy = (raw_unscaled_energy / BL0942_WREF); // приводим потребленную эергию к киловатт часам
            if ( newEnergy < 16000) { goodEnergy = newEnergy; } // проверяем на валидность, если энергия в разумных пределах - запоминаем (невалидное значение больше реального в тысячи раз)
            // вывод данных в монитор порта
            Serial.print("V = "); Serial.println(goodVoltage);
            Serial.print("I = "); Serial.println(goodTok);
            Serial.print("P = "); Serial.println(goodPower);
            Serial.print("kW.h = "); Serial.println(goodEnergy);
            }
          else {
            Serial.print("Packet from BL9042 not ok\n");  } // Пакет битый
  }
}
 
Изменено: