Сбор показаний электро-счётчика (для механических счётчиков)

Подключение исполнительных устройств, датчиков, контроллеров.

Модератор: immortal

Аватара пользователя
sergejey
Site Admin
Сообщения: 4284
Зарегистрирован: Пн сен 05, 2011 6:48 pm
Откуда: Минск, Беларусь
Благодарил (а): 75 раз
Поблагодарили: 1559 раз
Контактная информация:

Сбор показаний электро-счётчика (для механических счётчиков)

Сообщение sergejey » Ср авг 21, 2013 4:23 pm

Есть у меня счётчик электро-энергии. Приблизительно такой:
Изображение

По некоторым причинам у меня не получается заменить его на новый электронный с каким-либо цифровым интерфейсом. Так же не очень хотелось сооружать конструкцию из двух счётчиков. Короче, было решено попробовать собирать информацию считая количество оборотов колеса на счётчике.

Принцип такой -- с помощью ИК приёмника/передатчика и контроллера считаем количество оборотов колеса и по радио-каналу отправляем на сервер количество оборотов и время, за которое они были сделаны. Таким образом, зная скорость вращения колеса мы можем с некоторым приближением получить текущую потребляемую мощность. Ну а т.к. мы знаем точное количество оборотов, то достаточно точно будем знать суммарное потребление за более продолжительный период.

На контроллере считаем каждый импульс, но на сервер отправляем значение счётчика, если количество оборотов более 30 или если время с отправки последних данных более 10 минут. Таким образом мы не будем захламлять эфир постоянной передачей данных. Потерять данные не очень страшно -- просто время от времени надо будет сравнивать рассчётное показание на компьютере с реальным показанием на счётчике. По опыту нескольких дней использования эта разбежка если и будет, то минимальная (пока один в один).

Для рассчёта мощности нам нужно знать как сопоставить оборт счётчика с реальным потреблением. У меня на самом счётчике написано, что 1Квт/ч = 150 оборотов. Так что исходя из этого всё можно рассчитать.

Используемые компоненты для устройства:

1. Контроллер Arduino

2. Блок ИК приёмника-передатчика:
Изображение
(куплено здесь)

3. RF-передатчик на 433Mhz:
Изображение

4. Светодиод (будет дублировать прохождение тёмной полосы при вращении круга на счётчике)

По схематике всё довольно просто. В моём случае я использовал такое подключение к контроллеру:
PIN 2 -- светодиод индикации импульсов
PIN 3 -- data-выход для радио-передачика (подробнее про организацию протокола передачи я писал здесь)
PIN 4 -- data-вход от IR-модуля (в этом модуле два выхода, но нам нужен только один)
PIN 13 -- светодиод индикации отправки данных на сервер (используется встроенный светодиод)

Ниже код скетча для прошивки Arduino:

Код: Выделить всё

#include <VirtualWire.h>
#include <EasyTransferVirtualWire.h>
#include <EEPROM.h> //Needed to access the eeprom read write functions

#define PIN_LED 2
#define PIN_LED_T 13
#define PIN_TEMP 7  
#define PIN_RF 3
#define PIN_IR 4 

#define PERIOD_SEND_POWER 600 // seconds
#define PERIOD_MAX_COUNTER 30 // circles

#define COMMAND_COUNTER 15 // command code for counter

#define RF_SEND_COUNTER 3 // number of packets to send with transmission
 

unsigned int unique_device_id = 0;


int old_status=0;

long int timeSentPower=0;
long int counterPower=0;
long int timePassedPower=0;


//create object
EasyTransferVirtualWire ET; 

struct SEND_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to send
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  //Struct can'e be bigger then 26 bytes for VirtualWire version
  unsigned int device_id;
  unsigned int destination_id;    
  unsigned int packet_id;
  byte command;
  int data;
};

//give a name to the group of data
SEND_DATA_STRUCTURE mydata;

//This function will write a 2 byte integer to the eeprom at the specified address and address + 1
void EEPROMWriteInt(int p_address, unsigned int p_value)
{
  byte lowByte = ((p_value >> 0) & 0xFF);
  byte highByte = ((p_value >> 8) & 0xFF);

  EEPROM.write(p_address, lowByte);
  EEPROM.write(p_address + 1, highByte);
}

//This function will read a 2 byte integer from the eeprom at the specified address and address + 1
unsigned int EEPROMReadInt(int p_address)
{
  byte lowByte = EEPROM.read(p_address);
  byte highByte = EEPROM.read(p_address + 1);

  return ((lowByte << 0) & 0xFF) + ((highByte << 8) & 0xFF00);
}

void blinking(int count) {
 for(int i=0;i<count;i++) {
  digitalWrite(PIN_LED, HIGH); 
  delay(200);
  digitalWrite(PIN_LED, LOW);
  delay(200);
 }
}

void sendRFData() {
 Serial.print("Transmitting packets ... ");   
 for(int i=0;i<RF_SEND_COUNTER;i++) {
  if (i>0) {
   delay(200);    
  }
  digitalWrite(PIN_LED_T, HIGH); 
  ET.sendData();
  digitalWrite(PIN_LED_T, LOW);
 }  
 Serial.println("DONE");   
}

void setup()
{

  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_LED_T, OUTPUT); 
  pinMode(PIN_IR, INPUT);   
  Serial.begin(9600); 

  ET.begin(details(mydata));
  vw_set_tx_pin(PIN_RF);
  vw_setup(2000);        // Bits per sec
  randomSeed(analogRead(0));


  // Device ID
  Serial.print("Getting Device ID... "); 
  unique_device_id=EEPROMReadInt(0);
  if (unique_device_id<10000 || unique_device_id>60000) {
    Serial.print("N/A, updating... "); 
    unique_device_id=random(10000, 60000);
    EEPROMWriteInt(0, unique_device_id);
  }
  Serial.println(unique_device_id);   
  mydata.device_id = unique_device_id;
  mydata.destination_id = 0;  
  
}

void loop()
{

  
  int current_ir=digitalRead(PIN_IR);
  digitalWrite(PIN_LED,current_ir);
  if (current_ir!=old_status)  {   
    if (current_ir==0) {
     counterPower++;
     Serial.print(" Power counter: ");
     Serial.print(counterPower);
     Serial.print(" time passed: ");
     timePassedPower=millis()/1000-timeSentPower;
     Serial.println(timePassedPower);
     if ((counterPower>=PERIOD_MAX_COUNTER) || (timePassedPower>=PERIOD_SEND_POWER)) {
      timeSentPower=millis()/1000;
      mydata.packet_id = random(65535);
      mydata.command = COMMAND_COUNTER; //power counter
      Serial.print("Sending value: ");
      mydata.data = (int)counterPower*1000+(int)timePassedPower;
      Serial.println(mydata.data);
      sendRFData();
      counterPower=0;
     }
    }
    old_status=(int)current_ir;
  } 
  
  delay(100); // задержка. 
}
Блок с IR приёмником-передатчиком я закрепил пока просто скотчем напротив колёсика счётчика. Больше всего боялся, что не будут корректно считаться импульсы, но, к счастью, немного покрутив настройку чувствительности на блоке, я добился абсолютно чёткого срабатывания при прохождении тёмной полосы.

Итак, добившись работы контроллера переходим к сбору данных на сервере.

Для начала я создал класс объектов Counters со следующими свойствами:
Изображение

Так же в этот класс добавил метод onUpdate со следующим кодом:

Код: Выделить всё

$counter=$params['counter'];
$passed=$params['passed'];
$old_counter=$this->getProperty("counter");
if ($counter>0) {
 $old_counter+=$counter; 
 $this->setProperty("counter",$old_counter); // показание счётчика (в оборотах)
 $this->setProperty("power",round($old_counter/150)); // показание счётчика (в кВт/ч)
}
if ($passed>0) {
 $speed=round((($counter*60*60/$passed)/150),2); // рассчитываем текущую потребляемую мощность в кВт/ч
 $this->setProperty("speed",$speed);
}
$this->setProperty("updated",time());
$this->setProperty("updatedTime",date('H:i'));
Следующим шагом я добавил объект под названием ElectroCounter данного класса:
Изображение

Дальше нужно внести правки в сценарий, который запускается приёмником сообщений от устройств из эфира. Там надо добавить обработчик сигналов от нашего нового беспроводного модуля:
Изображение

Вот сам код с комментариями:

Код: Выделить всё

if ($device_id=='23505') { // счётчик на электро-щитке (вместо 23505 может быть любой код, совпадающий с кодом устройства)
 // радио-модуль передаёт в одном числе закодированное количество оборотов и время, за которое они были посчитаны
 // раскодируем:
 $counter=floor($data/1000); // количество оборотов
 $passed=$data-$counter*1000; // прошедшее количество секунд
 callMethod("ElectroCounter.onUpdate",array("counter"=>$counter,"passed"=>$passed)); // отправляем данные в метод объекта
}
Собственно, собирательная часть закончена. Данные исправно поступают в систему. Теперь добавим в интерфейсе (меню) вывод этих данных.
В основном меню добавляем пункт с таким названием:

Код: Выделить всё

Электро-энергия (%ElectroCounter.speed% Квт/ч)
В качестве дочерних пунктов добавляем три HTML-блока:
1. Расход:

Код: Выделить всё

Текущее потребление: %ElectroCounter.speed% Квт/ч<br/>
Показание счётчика: %ElectroCounter.power% Квт/ч
2. График суточного потребления:

Код: Выделить всё

Потребление (24h)<br>
<img src="/pChart/?p=ElectroCounter.speed&type=24h&width=280&gtype=curve&px=5&unit=kWh&%rand%">
3. График месячных показаний счётчика:

Код: Выделить всё

Показание счётчика (месяц)<br>
<img src="/pChart/?p=ElectroCounter.power&type=30d&width=280&gtype=curve&px=15&unit=kWh&%rand%">
На выходе получаем такую картинку:
Изображение

(месячный график не совсем корректный, т.к. не было истории показаний)

Сергей Джейгало, разработчик MajorDoMo
Идеи, ошибки -- за предложениями по исправлению и развитию слежу только здесь!
Профиль Connect -- информация, сотрудничество, услуги
Vip
Сообщения: 86
Зарегистрирован: Вт авг 28, 2012 5:36 pm
Откуда: Kiev, Ukraine
Благодарил (а): 4 раза
Поблагодарили: 14 раз

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение Vip » Пн сен 16, 2013 12:38 am

А для замера частоты мигания светодиода на более новых счетчиках данный пример работать будет?
Аватара пользователя
sergejey
Site Admin
Сообщения: 4284
Зарегистрирован: Пн сен 05, 2011 6:48 pm
Откуда: Минск, Беларусь
Благодарил (а): 75 раз
Поблагодарили: 1559 раз
Контактная информация:

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение sergejey » Вт сен 17, 2013 3:53 pm

Vip писал(а):А для замера частоты мигания светодиода на более новых счетчиках данный пример работать будет?
Да, принцип тот же -- считать импульсы. Так что, работать должно.

Сергей Джейгало, разработчик MajorDoMo
Идеи, ошибки -- за предложениями по исправлению и развитию слежу только здесь!
Профиль Connect -- информация, сотрудничество, услуги
RusikOk
Сообщения: 91
Зарегистрирован: Чт июл 24, 2014 1:48 am
Откуда: Украина, Сумы
Благодарил (а): 43 раза
Поблагодарили: 6 раз

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение RusikOk » Чт авг 07, 2014 4:54 pm

кстати а при большей скорости вращения диска не замечалось неправильного определения количества оборотов?
Аватара пользователя
sergejey
Site Admin
Сообщения: 4284
Зарегистрирован: Пн сен 05, 2011 6:48 pm
Откуда: Минск, Беларусь
Благодарил (а): 75 раз
Поблагодарили: 1559 раз
Контактная информация:

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение sergejey » Чт авг 07, 2014 5:46 pm

RusikOk писал(а):кстати а при большей скорости вращения диска не замечалось неправильного определения количества оборотов?
Нет. Но это зависит от качества установки датчика -- если установлен не очень хорошо, то может пропускать импульсы или выдавать ложное срабатывание.

Сергей Джейгало, разработчик MajorDoMo
Идеи, ошибки -- за предложениями по исправлению и развитию слежу только здесь!
Профиль Connect -- информация, сотрудничество, услуги
RusikOk
Сообщения: 91
Зарегистрирован: Чт июл 24, 2014 1:48 am
Откуда: Украина, Сумы
Благодарил (а): 43 раза
Поблагодарили: 6 раз

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение RusikOk » Вс окт 19, 2014 12:57 pm

чтоб не потерять http://habrahabr.ru/post/234679/
Skull
Сообщения: 38
Зарегистрирован: Вт фев 17, 2015 1:52 pm
Благодарил (а): 11 раз
Поблагодарили: 0

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение Skull » Пт фев 27, 2015 7:58 pm

У кого-нибудь счетчик прикручен через ESP8266 ? Поделитесь примером пожалуйста
visitor2100
Сообщения: 19
Зарегистрирован: Пт фев 20, 2015 5:24 pm
Благодарил (а): 5 раз
Поблагодарили: 1 раз

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение visitor2100 » Пн мар 23, 2015 7:19 pm

sergejey писал(а):
Vip писал(а):А для замера частоты мигания светодиода на более новых счетчиках данный пример работать будет?
Да, принцип тот же -- считать импульсы. Так что, работать должно.
Сергей, если не трудно, можете убрать часть кода отвечающую за передачу по RF. Сам пробовал, не работает, что то делаю не так.
Приобрел такое устройство: DDS238-4 http://ru.aliexpress.com/item/din-rail- ... dVersion=1.
Хочу его к ардуинке прикрутить и отправлять данные по езернету на мажордом.
В счетчике удвоил частоту импульсов, теперь 1600imp/1кВт (по заводу 800), кому будет интересно как, спрашивайте.
Буду рад любому совету.
Спасибо.
Pop
Сообщения: 9
Зарегистрирован: Пн фев 11, 2013 9:46 am
Откуда: Ростов-на-Дону
Благодарил (а): 0
Поблагодарили: 0

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение Pop » Вт мар 31, 2015 6:33 pm

Skull писал(а):У кого-нибудь счетчик прикручен через ESP8266 ? Поделитесь примером пожалуйста
Еще не делал, но планирую так:
http://homes-smart.ru/index.php/compone ... mitstart=0
visitor2100
Сообщения: 19
Зарегистрирован: Пт фев 20, 2015 5:24 pm
Благодарил (а): 5 раз
Поблагодарили: 1 раз

Re: Сбор показаний электро-счётчика (для механических счётчи

Сообщение visitor2100 » Ср апр 01, 2015 1:36 am

visitor2100 писал(а):
sergejey писал(а):
Vip писал(а):А для замера частоты мигания светодиода на более новых счетчиках данный пример работать будет?
Да, принцип тот же -- считать импульсы. Так что, работать должно.
Сергей, если не трудно, можете убрать часть кода отвечающую за передачу по RF. Сам пробовал, не работает, что то делаю не так.
Приобрел такое устройство: DDS238-4 http://ru.aliexpress.com/item/din-rail- ... dVersion=1.
Хочу его к ардуинке прикрутить и отправлять данные по езернету на мажордом.
В счетчике удвоил частоту импульсов, теперь 1600imp/1кВт (по заводу 800), кому будет интересно как, спрашивайте.
Буду рад любому совету.
Спасибо.

Решено.
Ответить