656

Удаленное снятие показаний с электросчетчика

Счетчик установлен в подъездном щите и каждый раз бегать туда для снятия показаний не вариант,  к тому же все таки делаем умный дом, который сам будет отправлять показания счетчиков в управляющую компанию.

Имеем установленный электросчетчик

blog-0826948001390146344

Чтение мануалов показало наличие импульсного выхода. На счетчике указана цена импульса — 3200 импульсов = 1 кВт*ч потребленной мощности (фото из интернета, на фото цена 1600 импульсов на 1 кВт*ч).

Подключаем импульсный выход на вход Arduin’ы и пишем программку которая будет считать импульсы и измерять время между импульсами (для перевода этих данных в текущий расход электроэнергии).

/* 
Перед загрузкой данной программы, неоходимо обнулмть eeprom, т.е. записать во все ячейки eeprom 0.
*/
#include <EEPROM.h>

volatile unsigned long counter = 746 ;  // Начальные показания
volatile unsigned long newcounter = 0;
unsigned long counter_max = 70000;  //Максимальное значения которое хранится в одном банке памяти
#define pin1 2   // 2-й цифровой пин, нулевое прерывание Электросчетчика
int counter_byte = 0; //Ячейка eeprom для хранения данных Электросчетчика
int adress_byte = 128; //Адрес хранения адреса хранения данных электросчетчика))
int adress = 0;
int impuls = 0;
unsigned long power = 0;
unsigned long old_power = 0;

unsigned long cur_tm = millis();
unsigned long pre_tm = cur_tm;
unsigned int tm_diff = 0; 
 
unsigned long cur_tmS = millis();
unsigned long pre_tmS = cur_tmS;
float diffS = 0;
float tm_diffS = 0;  


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
  void setup() {
    Serial.begin(115200);
    delay(2);
            if (EEPROM.read(150)==0){ // Если первый запуск то запишем в ячейки адреса где хранятся данные
               if (counter >= counter_max && counter<=(counter_max*2)-1){ counter_byte = 4; } if (counter>=counter_max*2 && counter<=(counter_max*3)-1){ counter_byte = 8; } if (counter>=counter_max*3 && counter<=(counter_max*4)-1){ counter_byte = 12; } EEPROM.write(adress_byte, counter_byte); EEPROMWriteInt(counter_byte, counter); //Пишем показания счетчика в eeprom из переменной EEPROM.write(150, 1); //Бит первого запуска } counter_byte = EEPROM.read(adress_byte); counter = EEPROMReadInt(counter_byte); //Настраиваем цифровой вход pinMode(13, OUTPUT); pinMode(2, INPUT); // Сюда будем подключать подтягивающий резюк digitalWrite(2, HIGH); // "Подключаем" подтягивающий резистор attachInterrupt(0, count_1, FALLING); // задаём обработчик прерывания 0 (2-й пин). // прерывание будет при изменении уровня с HIGHT на LOW // вызывать функицю count } ///////////////////////////////////ОСНОВНОЙ ЦИКЛ///////////////////////////////////////////// void loop(){ if (Serial.available() > 0) {
             if (Serial.find("Status")) { //Ищем на входе "Status" Если нашли отправляем данные 
                 for (int i=0; i <= 1; i++){ Serial.print("C"); Serial.print(counter); // выводим в консоль значение счётчика Serial.print("W"); Serial.print(power); // выводим в консоль значение счётчика Serial.print("$"); } } if (Serial.find("CHG")) { //Ищем на входе строку "CHG" Если нашли получаем данные unsigned long change_counter = Serial.parseInt(); // Парсинг числа во входящем потоке counter = change_counter; if (counter > 0){
                      if (counter >= counter_max && counter<=(counter_max*2)-1){ counter_byte = 4; } if (counter>=counter_max*2 && counter<=(counter_max*3)-1){ counter_byte = 8; } if (counter>=counter_max*3 && counter<=(counter_max*4)-1){
                        counter_byte = 12; 
                      }
                      EEPROM.write(adress_byte, counter_byte);
                      EEPROMWriteInt(counter_byte, counter);  //Пишем показания счетчика в eeprom из переменной
                    }  
                  }
           }
               if (counter != newcounter){  
                  detachInterrupt (0);
                  for (int i=0; i <= 1; i++){ Serial.print("C"); Serial.print(counter); // выводим в консоль значение счётчика Serial.print("W"); Serial.print(power); // выводим в консоль значение счётчика Serial.print("$"); newcounter = counter; } attachInterrupt(0, count_1, FALLING); } if (impuls >= 3200){ 
          detachInterrupt (0);
            impuls = 0;
            counter = counter + 1;
              if (counter>=counter_max && counter<=(counter_max*2)-1){ counter_byte = counter_byte + 4; EEPROM.write(adress_byte, counter_byte); } if (counter>=counter_max*2 && counter<=(counter_max*3)-1){ counter_byte = counter_byte + 8; EEPROM.write(adress_byte, counter_byte); } if (counter>=counter_max*3 && counter<=(counter_max*4)-1){ counter_byte = counter_byte + 12; EEPROM.write(adress_byte, counter_byte); } EEPROMWriteInt(counter_byte, counter); //Пишем данные счетчика в энергонезависимую память attachInterrupt(0, count_1, FALLING); } } //////////////////////////////////ФУНКЦИИ СЧЕТЧИКА////////////////////////////////////// void count_1(){ detachInterrupt (0); // вызывается прерыванием 0 от 2-го цифрового входа unsigned long millis_prev; if(millis()-10 > millis_prev) { //Защита от дребезга контаков
             pre_tmS = cur_tmS;
             cur_tmS = millis();
               if( cur_tmS > pre_tmS ) {
                 tm_diffS = cur_tmS - pre_tmS;
               }
             impuls++;  // Инкриментируем счетчик импульсов    

             diffS = (tm_diffS / 1000);
             power = 3600000 / (3200 * diffS);

         if (power > (old_power + 4000)){
            power = old_power;
         }
             Serial.print("C");
             Serial.print(counter);
             Serial.print("W");
             Serial.print(power);
             Serial.print("$");
             old_power = power;
             millis_prev = millis();
           }
            attachInterrupt(0, count_1, FALLING);
}
////////////////////////////////////ФУНКЦИИ ПАМЯТИ///////////////////////////////////////////
//кушаем аж 4 байта EEPROM
void EEPROMWriteInt(int p_address, unsigned long p_value){
    byte four = (p_value & 0xFF);
    byte three = ((p_value >> 8) & 0xFF);
    byte two = ((p_value >> 16) & 0xFF);
    byte one = ((p_value >> 24) & 0xFF);
    EEPROM.write(p_address, four);
    EEPROM.write(p_address + 1, three);
    EEPROM.write(p_address + 2, two);
    EEPROM.write(p_address + 3, one);
}
// считаем нашы 4 байта
unsigned long EEPROMReadInt(int p_address){
   long four = EEPROM.read(p_address);
   long three = EEPROM.read(p_address + 1);
   long two = EEPROM.read(p_address + 2);
   long one = EEPROM.read(p_address + 3);
   return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
 }

Программа считает импульсы, пишет показания в энергонезависимую память EEPROM и отдает текущий показания через UART.

Отправить ответ

Оставьте первый комментарий!

avatar
wpDiscuz