Наскоро се сдобих с панел който измерва напрежение, ток, мощност и енергия – http://www.aliexpress.com/item/PEACEFAIR-AC-100A-Digital-LCD-power-meter-power-energy-Volt-Ammeter-with-shell-4-led-panel/32320321777.html?s=p
Производство е на фирмата Pui Ching (Peacefair), модел PZEM-004 (v3.0). Модулът предлага възможност за включване към компютър (или друг контролер) и възможност за четене на данните от панела в реално време. За комуникация, панела разчита на серийна комуникация от типа RS232 (TTL) с интерфейс който е галванично разделен (чрез оптрони) от мрежовото напрежение.
Поглеждаме отвътре:
Следните по-интересни елементи се забелязват от пръв поглед:
- SD3004 – Energy Measurement SOC – http://www.sdicmicro.com/DataSheet/SD3004%20datasheet%20v0.2c.pdf
- Atmel 24C02 – Two-wire Serial EEPROM 2K (256 x 8) – http://www.atmel.com/Images/doc5126.pdf
- Opto-Coupler Sharp PC817 – http://pdf.datasheetcatalog.com/datasheet/Sharp/mXuwuqq.pdf
- THX208 – Switching power supply controller IC – http://www.datasheet-pdf.com/datasheet-download.php?id=846231
- 78L05 – стабилизатор на 5V
Разбира се, целта бе модулът да се свържи към компютър за да могат данните да се записват някъде. След няколко-дневни, безуспешни опити в комуникация с китайците, да науча детайли относно параметрите на връзката (скорост и др.настройки) реших да поровя в Нет-а и открих, че комуникацията се извършва на 9600, 8-N-1. От китайците, намерих линк от къде може да се изтегли софтуера който предлага възможности да показва индикациите (https://mega.nz/#!WoxGgCSS!A9pDXDXrv8nwUgJmhXBl-dhFt-JzOwuBg_JGq5qsD0o), но за съжаление всичко е на йероглифи и нищо не се разбира.
Следвайки указанията в документацията видях, че трябва да се изпращят заявки (команди) след което модула ще отговори подобаващо. Табличката показва възможните команди и примерни отговори от страна на модула:
NO. | function | Head | Data1- Data5 | Sum |
1 | voltage | B0 | C0 A8 01 01 00 (Computer sends a request to read the voltage value) | 1A |
A0 | 00 E6 02 00 00 (Meter reply the voltage value is 230.2V) | 88 | ||
2 | current | B1 | C0 A8 01 01 00 (Computer sends a request to read the current value) | 1B |
A1 | 00 11 20 00 00 (Meter reply the current value is 17.32A) | D2 | ||
3 | Active power | B2 | C0 A8 01 01 00 (Computer sends a request to read the active power value) | 1C |
A2 | 08 98 00 00 00 (Meter reply the active power value is 2200w) | 42 | ||
4 | Read energy | B3 | C0 A8 01 01 00 (Computer sends a request to read the energy value) | 1D |
A3 | 01 86 9f 00 00 (Meter reply the energy value is 99999wh) | C9 | ||
5 | Set the module address | B4 | C0 A8 01 01 00 (Computer sends a request to set the address, the address is 192.168.1.1) | 1E |
A4 | 00 00 00 00 00 (Meter reply the address was successfully set) | A4 | ||
6 | Set the power alarm threshold | B5 | C0 A8 01 01 14 (computer sends a request to set a power alarm threshold) | 33 |
A5 | 00 00 00 00 00 (Meter reply the power alarm threshold was successfully set) | A5 |
Или накратко:
B0 C0 A8 01 01 00 1A - sends a request to read the voltage value B1 C0 A8 01 01 00 1B - sends a request to read the current value B2 C0 A8 01 01 00 1C - sends a request to read the active power value B3 C0 A8 01 01 00 1D - sends a request to read the energy value B4 C0 A8 01 01 00 1E - sends a request to set the address to 192.168.1.1 B5 C0 A8 01 01 14 33 - sends a request to set a power alarm threshold
Остана да се свърже подходящо кабелче към компютъра (USB-RS232/TTL) и да закачите жиците (цветовете може да се различават за различните типове кабели).
За писането на софтуера използвах Borland C++ Builder който е доста стар, но пък удобен за такива малки проекти. След няколко часово експериментиране се получи следната програма с която може да се четат данните:
Частта от кода която обслужва самата комуникация с модула е следната:
HANDLE hComm; DWORD dwMask; OVERLAPPED ovr; DCB dcb; unsigned char setvalue1[7] = { 0xB4, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1E }; // Set the address to 192.168.1.1 unsigned char setvalue2[7] = { 0xB0, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1A }; // Read the voltage value unsigned char setvalue3[7] = { 0xB1, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1B }; // Read the current value unsigned char setvalue4[7] = { 0xB2, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1C }; // Read the active power value unsigned char setvalue5[7] = { 0xB3, 0xC0, 0xA8, 0x01, 0x01, 0x00, 0x1D }; // Read the energy value unsigned char getvalue[7] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // initialize a serial connection hComm = CreateFile(ком-порта, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hComm == INVALID_HANDLE_VALUE) { обработка на грешки } // setup comm params: 9600-8-N-1 GetCommState(hComm, &dcb); dcb.BaudRate = 9600; dcb.fOutX = false; dcb.fInX = false; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; SetCommState(hComm, &dcb); // Read one char at a time. GetCommMask(hComm, &dwMask); dwMask |= EV_RXCHAR; SetCommMask(hComm, dwMask); ... //----------------- // sent query about voltage for (int i=0; i<7; i++) { WriteFile(hComm, &setvalue2[i], 1, &dwMask, NULL); } Sleep(10); // read voltage for (int k=0; k<7; k++) { ReadFile(hComm, &getvalue[k], 1, &dwMask, NULL); } // Display Voltage Memo1->Lines->Add("Voltage: " + IntToStr(getvalue[2]) + "." + IntToStr(getvalue[3]) + " /V/"); //----------------- // sent query about Amperage/Current for (int i=0; i<7; i++) { WriteFile(hComm, &setvalue3[i], 1, &dwMask, NULL); } Sleep(10); memset(getvalue, 0x0, 7); // read current for (int k=0; k<7; k++) { ReadFile(hComm, &getvalue[k], 1, &dwMask, NULL); } // Display Amperage/Current Memo1->Lines->Add("Current: " + IntToStr(getvalue[2]) + "." + IntToStr(getvalue[3]) + " /A/"); //----------------- // sent query about active power for (int i=0; i<7; i++) { WriteFile(hComm, &setvalue4[i], 1, &dwMask, NULL); } Sleep(10); memset(getvalue, 0x0, 7); // read active power value for (int k=0; k<7; k++) { ReadFile(hComm, &getvalue[k], 1, &dwMask, NULL); } // Display Active Power value Memo1->Lines->Add("Power: " + IntToHex(getvalue[1],2) + " " + IntToHex(getvalue[2],2) + " " + IntToHex(getvalue[3],2) + " /W/"); //----------------- // sent query about Energy for (int i=0; i<7; i++) { WriteFile(hComm, &setvalue5[i], 1, &dwMask, NULL); } Sleep(10); memset(getvalue, 0x0, 7); // read energy value for (int k=0; k<7; k++) { ReadFile(hComm, &getvalue[k], 1, &dwMask, NULL); } // Display Energy value Memo1->Lines->Add("Energy: " + IntToHex(getvalue[1],2) + " " + IntToHex(getvalue[2],2) + " " + IntToHex(getvalue[3],2) + " /Wh/"); //----------------- CloseHandle(hComm);
Оригиналния китайски софтуер може да бъде изтеглен от тук или тук, като преди това е необходимо да се инсталира драйвер за USB<->RS232 конвертора. Паролата която изисква програмата е admin.
Налична е библиотека за Arduino: https://github.com/olehs/PZEM004T
Подробно ревю на руски има на следния адрес: https://mysku.ru/blog/china-stores/38717.html
Още примери (с Raspberry Pi, Arduino, ESP8266) има на следните линкове:
https://mysku.ru/blog/china-stores/43331.html
https://wiki.cuvoodoo.info/doku.php?id=spark_counter
http://zftlab.org/pages/2016050700.html
И накрая, като малка забележка, искам да добавя, че при всяка заявка към модула той издава звук от малък зумер (вижда се на картинката горе) което е доста дразнещо и е по-добре да се разпой от платката.