Ключевое ?лово

vk

Добро пожаловать, Гость
Логин: Пароль: Запомнить меня
Железо для умного дома

ТЕМА: Сбор и передача показаний счетчиков воды газа и электричеств

Сбор и передача показаний счетчиков воды газа и электричеств 05 Май 2017 10:35 #18600

  • gis
  • gis аватар
  • Не в сети
  • Захожу иногда
  • Сообщений: 58
  • Спасибо получено: 1
  • Репутация: 0
Спасибо за код. Не могли бы вы еще выложить схему аппаратного подавления дребезга или всего устройства в целом.
Администратор запретил публиковать записи гостям.

Сбор и передача показаний счетчиков воды газа и электричеств 05 Май 2017 12:52 #18601

  • SolarW
  • SolarW аватар
  • Не в сети
  • Давно я тут
  • Сообщений: 156
  • Спасибо получено: 3
  • Репутация: 1
Дык на 12 и 14 страницах этой темы лежит схема.
Администратор запретил публиковать записи гостям.

Сбор и передача показаний счетчиков воды газа и электричеств 16 Июль 2017 16:07 #19245

  • rapid
  • rapid аватар
  • Не в сети
  • Давно я тут
  • Сообщений: 109
  • Спасибо получено: 36
  • Репутация: 5
Как известно, микросхема PCF8583 умеет считать внешние импульсы до 999 999, что очень мало (например, типовой счетчик электроэнергии выдает 3200 импульсов на кВт*ч, что позволило бы нам посчитать всего только 312 кВт до переполнения регистров PCF8583).
Для расширения счетных возможностей измерительной системы предлагается использовать дополнительный регистр, увеличивающий свое значение на единицу при каждом переполнении PCF8583. Затем можно значение данного регистра учитывать при подсчете итогового показания.
Второй не менее важной задачей является сохранение показаний при отключении электропитания и решается она запитыванием самого счетчика PCF8583 от батарейки (см. фото):



Для хранения переменных для промежуточных вычислений и контроля переполнения счетных регистров воспользуемся внутренними регистрами микросхемы, доступными для чтения/записи:



Прилагаю исходный код для конструктора кода:
uint32_t current_value; 	       	// Инициализация  текущего значения счетчика
uint32_t previous_value;	       	// Инициализация предыдущего значения счетчика
uint32_t counter_overflows;   		// Инициализация счетчика переполнений
uint32_t division_ratio;	      	// Инициализация коэффициента деления
uint32_t initial_indication;       	// Инициализация начального показания счетчика
uint32_t div1;	                	// Инициализация коэффициента деления
uint32_t init1;             		// Инициализация начального показания счетчика
uint32_t counter1_print; 	       	// Значение показаний счетчика 1
uint32_t counter2_print; 	       	// Значение показаний счетчика 2
uint8_t value_1,value_2, value_3;	// Переменные value_1,value_2, value_3

void ICACHE_FLASH_ATTR
startfunc()
{  
// выполняется один раз при старте модуля
 }

PCF8583_read_my(uint8_t adr)
 {
i2c_start();				   		// Устанавливаем на шине Start состояние
i2c_writeByte(adr*2);		   		// отправляем байт  0b101000yх (отклик любой RTC)
     if(i2c_getAck()){return(-1);}  // slave не откликнулся
i2c_writeByte(01);		           	// устанавливаем регистр для чтения
     if(i2c_getAck()){return(-1);}  // slave not ack
i2c_stop();			           		// Формируем на шине Stop состояние
// ------------ читаем текущее значение (current_value) ----------------
i2c_start(); 							// Устанавливаем на шине Start состояние 
i2c_writeByte(adr*2+1);
     if(i2c_getAck()){return(-1);} 		// slave не откликнулся
uint8_t Val=0;							// Инициализация вспомогательной переменной
Val= i2c_readByte(); 					// ACK
current_value=(Val&15) + (Val/16)*10; 	// Поразрядное логическое "И" +
value_1=Val;
i2c_setAck(0);
Val= i2c_readByte(); 					//ACK
current_value=current_value+ (Val&15)*100 + (Val/16)*1000;
value_2=Val;
i2c_setAck(0);
Val= i2c_readByte(); 					//ACK
current_value=current_value+ (Val&15)*10000 + (Val/16)*100000;
value_3=Val;
i2c_setAck(0);

// -------- читаем предыдущее значение (previous_value) ------------
Val= i2c_readByte(); 					//ACK
previous_value=(Val&15) + (Val/16)*10; 
i2c_setAck(0);
Val= i2c_readByte(); 					//ACK
previous_value=previous_value+ (Val&15)*100 + (Val/16)*1000;
i2c_setAck(0);
Val= i2c_readByte(); 					//ACK
previous_value=previous_value+ (Val&15)*10000 + (Val/16)*100000;
i2c_setAck(0);

//---- читаем содержимое счетчика переполнений (counter_overflows)----
Val = i2c_readByte(); 					//ACK
counter_overflows = Val;
i2c_setAck(0);
//---------------------------------------------------------------------------
i2c_setAck(1);
i2c_stop();
//return current_value;
}

// ------- Функция обновления предыдущего значения -------------------
PCF8583_upd_previous(uint8_t adr)
{
i2c_start();			        	// Устанавливаем на шине Start состояние
i2c_writeByte(adr*2);	        	// отправляем байт 0b101000yх (откл любой RTC)
  if(i2c_getAck()){return;} 		// slave не откликнулся
i2c_writeByte(04);		        	// устанавливаем адрес регистра 0x00 для чтения
  if(i2c_getAck()){return;}         // slave не откликнулся
i2c_writeByte(value_1);	        	// записываем по адресу 0x00 байт 0x20
	if(i2c_getAck()){return;}   	// slave не откликнулся
i2c_writeByte(value_2);	        	// записываем по адресу 0x00 байт 0x20
	if(i2c_getAck()){return;}   	// slave не откликнулся
i2c_writeByte(value_3);	        	// записываем по адресу 0x00 байт 0x20
  if(i2c_getAck()){} 	           	// slave не откликнулся
i2c_stop();			        		// Формируем на шине Stop состояние
}

PCF8583_upd_counter_overflows(uint8_t adr)
{
i2c_start();			     		// Устанавливаем на шине Start состояние
i2c_writeByte(adr*2);	     		// отправл байт на шину 0b101000yх (отк любой RTC)
  if(i2c_getAck()){return;}      	// slave не откликнулся
i2c_writeByte(07);		     		// устанавливаем адрес регистра 0x00 для чтения
  if(i2c_getAck()){return;}      	// slave не откликнулся
i2c_writeByte(counter_overflows);	// записываем по адресу 0x00 байт 0x20
  if(i2c_getAck()){} 			 	// slave не откликнулся
i2c_stop();							// Формируем на шине Stop состояние
}

void ICACHE_FLASH_ATTR
 timerfunc(uint32_t  timersrc)
 {
      if(timersrc%10==0)  				// выполнение кода каждые 10 секунд
            { 
			
// ---------------- Логика работы счетчика  A -------------------
				PCF8583_read_my (0x50);
				
      if (current_value>previous_value)
            {       
				PCF8583_upd_previous(0x50);				// Перезапись предыдущего значения счетчика текущим 
            }
      else 
            { 
				if(current_value!=previous_value)
					{
						counter_overflows++;
						PCF8583_upd_previous(0x50);				// Перезапись предыдущего значения счетчика текущим 
						PCF8583_upd_counter_overflows(0x50);	// Перезапись счетчика переполнений counter_overflows
					}
			}
               init1=sensors_param.cfgdes[0];		// Читаем начальное значение из flash памяти esp
               div1=sensors_param.cfgdes[1];		// Читаем значение коэффициента деления из flash памяти esp
		if (div1==0) div1=1;   						// исключение деления на ноль
		counter1_print= init1+((current_value*10+999999*10*counter_overflows)/div1); 
		valdes[0] = counter1_print;
// ------ Счетчик B ----------------------------------------
				current_value=0;					// Обнуляем переменные
				previous_value=0;					// Обнуляем переменные
				counter_overflows=0;				// Обнуляем переменные
				
				PCF8583_read_my (0x51);
				
	if (current_value>previous_value)
            {       
				PCF8583_upd_previous(0x51);				// Перезапись предыдущего значения счетчика текущим 
            }
      else 
            { 
				if(current_value!=previous_value)
					{
						counter_overflows++;
						PCF8583_upd_previous(0x51);				// Перезапись предыдущего значения счетчика текущим 
						PCF8583_upd_counter_overflows(0x51);	// Перезапись счетчика переполнений counter_overflows
					}
			}
               init1=sensors_param.cfgdes[2];		// Читаем начальное значение из flash памяти esp
               div1=sensors_param.cfgdes[3];		// Читаем значение коэффициента деления из flash памяти esp
		if (div1==0) div1=1;   						// исключение деления на ноль
		counter2_print= init1+((current_value*10+999999*10*counter_overflows)/div1); 
			valdes[1] = counter2_print;
			}
}

void webfunc(char *pbuf) {
os_sprintf(HTTPBUFF,"Показания счетчика A: <b>%s</b> ,", fltostr(counter1_print));
os_sprintf(HTTPBUFF,"<br><hr>Показания счетчика B: <b>%s</b> ,", fltostr(counter2_print));
os_sprintf(HTTPBUFF,"<br><hr><form action='/i2cgo'><input type='hidden' name='adr'   value='50' /><input type='hidden' name='set' value='002000000000000000' /><button type='submit'>Сброс счетчика A</button></form>");
os_sprintf(HTTPBUFF,"<br><hr><form action='/i2cgo'><input type='hidden' name='adr'   value='51' /><input type='hidden' name='set' value='002000000000000000' /><button type='submit'>Сброс счетчика B</button></form>");
}
Также необходимо сделать дополнительные настройки, определив глобальные переменные и переменные для хранения пользовательских данных во flash памяти ESP:



Так выглядит окно главной страницы модуля



Как пользоваться таким счетчиком:
1. Во вкладке Designer code options в поле «Показания счетчика А:» вводим текущее значение Вашего счетчика (например электроэнергии), умноженное на 10. Например, для 1237,4кВт*ч, надо записать 12374).
2. В поле «Делитель счетчика А:» указываете число имп. на 1кВт*ч (типовое значение – 3200, ничего домножать не надо!).
3. Нажимаем Set и настройки сохранятся



4. В окне главной страницы модуля нажимаем кнопку «Сброс счетчика A». Будет выполнен GET-запрос вида IP адрес/i2cgo?adr=50&set=002000000000000000, микросхема перейдет в режим счетчика событий и регистры обнулятся.

Показания (переменные valuedes0, valuedes1) отправляются на сервера MQTT и MajorDomo.
Пример вывода IP адрес/sensors

hostname:ESPCounter;pcfcnt1:146;pcfcnt2:145;valuedes0:1214;valuedes1:645;
Администратор запретил публиковать записи гостям.
Спасибо сказали: MSapogov, Maker39, Dmitry77, olegr70, Roofcat, OEMBSOD, SolarW, IvanKurtti, gis

Сбор и передача показаний счетчиков воды газа и электричеств 16 Июль 2017 18:51 #19247

  • Maker39
  • Maker39 аватар
  • Не в сети
  • Завсегдатай
  • Сообщений: 223
  • Спасибо получено: 12
  • Репутация: 0
Фундаментальный труд !
Последнее редактирование: 16 Июль 2017 18:53 от Maker39.
Администратор запретил публиковать записи гостям.

Сбор и передача показаний счетчиков воды газа и электричеств 09 Авг 2017 21:50 #19401

  • olegr70
  • olegr70 аватар
  • Не в сети
  • Завсегдатай
  • Сообщений: 189
  • Спасибо получено: 16
  • Репутация: 2
Спасибо rapid за проделанную работу и за исходный код для конструктора кода. Может кто нибудь доработает данный код для считывания показаний с двухтарифного счетчика? Пусть будет две PCF8583 с объединенными входами на которые одновременно поступают импульсы со счетчика электроэнергии. А ESPшка в соответствии с расписанием будет включать или выключать PCF8583. Что бы один счетчик считал ночной тариф и выходные дни, а другой - дневной тариф.
Время переключения и выходные дни наверное можно прописать в конструкторе кода, но было бы идеально если бы они прописывались аналогично первоначальным показаниям счетчика (через переменные). Только вот думаю что возникнет проблема с указанием праздничных дней.
Последнее редактирование: 09 Авг 2017 21:58 от olegr70.
Администратор запретил публиковать записи гостям.

Сбор и передача показаний счетчиков воды газа и электричеств 09 Авг 2017 22:11 #19402

  • olegr70
  • olegr70 аватар
  • Не в сети
  • Завсегдатай
  • Сообщений: 189
  • Спасибо получено: 16
  • Репутация: 2
Если не объединять входы счетчиков то наверное можно с помощью шедулера и схемы переключения входов управляемой по GPIO реализовать съем показаний двухтарифного счетчика. Но вопрос праздничных дней остается открытым. Сможет ли ESPшка отследить конкретные даты?
Администратор запретил публиковать записи гостям.
Модераторы: FlyRouter
Время создания страницы: 0.173 секунд

Home`s Smart © 2013-2016. г.Киров.
Цитирование материалов возможно только со ссылкой на сайт. Использование фотоматериалов только с разрешения авторов.