Удаленное снятие показаний с электросчетчика
Счетчик установлен в подъездном щите и каждый раз бегать туда для снятия показаний не вариант, к тому же все таки делаем умный дом, который сам будет отправлять показания счетчиков в управляющую компанию.
Имеем установленный электросчетчик
Чтение мануалов показало наличие импульсного выхода. На счетчике указана цена импульса — 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.