|
题记:感谢乐为物联技术群里的小沈(QQ:371212494)赠送我这个电量模块,感谢乐为提供平台资源。迟到的任务今天总算可以校稿了。 话说自从搬到了这个便宜的房子后,总感觉房租便宜了,但是每个月的电费确实成倍的增加了,一直就琢磨着如何查看每个月的真实用电量。想过换电表,可是房东把电箱锁住了换不了,还想过自己在房间里加装一块电表,可惜房东又不给,一直找不到方法解决这个问题,直到乐为物联群里出的这个套件。 1. 前言乐联网简介乐联网(https://www.lewei50.com/)阿里云托管,服务稳定且全国CDN加速节点速度快,WEB2.0的UI将用户体验发挥到了极致。我们可通过提供的API接口,您轻松的将各类传感器、测量设备或工业仪器仪表接入该平台,并可以通过开发应用来监管和控制它们。并且该平台提供传感器云服务,让您无需繁琐的编程,便可以将自己的各类测量或控制设备实现网络功能,快速开启物联网应用。同时强大的数据存储、查询和分析能力可以帮助一些传统行业快速部署自己的物联网应用,实现传统企业向物联网企业转型。同时该平台官方QQ群(59162154)有大量从事嵌入式工作的大大牛级人物在里面。可以让你迅速了解该平台的使用及问题求助。 2.活动介绍基于互感器电量模块,433无线数传连接ARDUINO(485版本扩展支持)的家庭能源消耗管理,是指能够即时查看电力消耗数据,而且能够通过历史数据图表,实现能源消耗的可视化管理。国外的电力公司,一般都为用户提供丰富的可视化能源管理数据,但是,国内这方面一直还是空白,一般都是传统的电表,稍微先进一点的电力公司的抄表数据只是收费用途,并不能为用户提供具体的家庭能源消耗的数据,因此很多家庭既浪费电能资源,又产生了额外的开支费用。所以本次活动的目的就是为了清楚的掌握家庭中每一天的具体电能消耗情况,从而为节约用电提供直观的依据。 3.活动材料1. 数据采集器底板一个(用来固定各个传感器模块模块)2. arduino pro mini一个(解析433模块发送过来的数据)3. 433Mhz透传模块一对(数据无线传输用)4. 开口互感器一个(采集实时电流大小)5. 电量采集模块一个(采集电压、功率因素及电量统计)6. W5500模块一个(上传到物联网平台的网络通信模块) 4、安装过程偷用别人的一张图,大致就是这样的,433无线数传版本比这个要简单,只要把开口互感器套进火线里后,然后给电量采集模块供电就完成了数据发射端的安装。这里我大致提供一下我的现场施工图(由于原始图片丢失,只能重新拆机再拍个大概,加之一个人带电作业还是有点点危险,所就只能大致说一下):接下来,云端平台的配置,这里注册的过程就不做过多的介绍,大家自行注册。接下来就是在这个页面添加设备,也就是网关(https://www.lewei50.com/user/gatewayadd)。这里有网络电量表V1和V2两个版本,他们的区别就是在于有没有温湿度和气压统计。
然后再在这个页面查看对应的传感器有没有添加成功(https://www.lewei50.com/user/sensorlist),如果这个页面有数据列表的话就说明传感器也添加完成了,接下来就是把程序代码下载到arduino pro mini主机中,程序代码如下,请自行修改设备ID和Userkey,Userkey可以在乐为物联的(https://www.lewei50.com/user/setting )这个页面获取。代码如下:
- // LeWei AC Power Meter trail success2013.06.25
- // LeWei AC Power Meter (ZongBiao60A)trail syccess 2013.06.30 18:50pm
- // 4 Parameter: watt / kwh / Amp / Voltage / Pf
-
- /* FIXME: not yet being used */
- unsigned long interframe_delay = 2; /* Modbus t3.5 = 2 ms */
-
- /*
- * preset_multiple_registers: Modbus function 16. Write the data from an
- * array into the holding registers of a slave.
- * INPUTS
- * slave: modbus slave id number
- * start_addr: address of the slave's first register (+1)
- * reg_count: number of consecutive registers to preset
- * data: array of words (ints) with the data to write into the slave
- * RETURNS: the number of bytes received as response on success, or
- * 0 if no bytes received (i.e. response timeout)
- * -1 to -4 (modbus exception code)
- * -5 for other errors (port error, etc.).
- */
-
- int preset_multiple_registers(int slave, int start_addr,
- int reg_count, int *data);
-
- /*
- * read_holding_registers: Modbus function 3. Read the holding registers
- * in a slave and put the data into an array
- * INPUTS
- * slave: modbus slave id number
- * start_addr: address of the slave's first register (+1)
- * count: number of consecutive registers to read
- * dest: array of words (ints) on which the read data is to be stored
- * dest_size: size of the array, which should be at least 'count'
- * RETURNS: the number of bytes received as response on success, or
- * 0 if no valid response received (i.e. response timeout, bad crc)
- * -1 to -4 (modbus exception code)
- * -5 for other errors (port error, etc.).
- */
-
- int read_holding_registers(int slave, int start_addr, int count,
- int *dest, int dest_size);
-
-
- /*
- open.lewei50.com sensor client
- */
-
-
-
- #include <SPI.h>
- #include <Ethernet.h>
- #include <LeweiClient.h>
-
- #define USERKEY "Your API Key" // replace your key here
- #define LW_GATEWAY "Your Gateway No."
-
- LeWeiClient *lwc;
-
-
- unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
- boolean lastConnected = false; // state of the connection last time through the main loop
- const unsigned long postingInterval = 30*1000; //delay between updates to cosm.com
-
-
- int pin = 8;
- unsigned long duration;
- unsigned long starttime;
- unsigned long sampletime_ms = 30000;
- unsigned long lowpulseoccupancy = 0;
- float ratio = 0;
- double concentration = 0;
-
- void setup() {
-
- // start serial port:
- Serial.begin(4800);
- pinMode(8,INPUT);
-
- delay(10000);
-
- lwc = new LeWeiClient(USERKEY, LW_GATEWAY);
-
- starttime = millis();
- }
- /* filter program : 20130521 */
- #define FILTERLEN 10
-
- unsigned long Array_Average( unsigned long* Array,int length)
- {
- int x;
- unsigned long returnVal;
- unsigned long result=0;
- for(x=0;x<length;x++)
- {
- result+=Array[x];
- Serial.print("result=");
- Serial.println(result);
- }
- returnVal=result/length;
- return returnVal;
- }
-
- unsigned long Filter1(unsigned long lowpulse)
- {
- static unsigned long sfiterArray[FILTERLEN];
- static int sindex=0;
- int x;
- Serial.println("filter1 begin:");
- if(FILTERLEN>sindex)
- {
- sindex++;
- Serial.println(sindex);
- sfiterArray[sindex]=lowpulse;
- Serial.println("filter1 END");
- return lowpulse;
- }
- else
- {
- for(x=0;x<FILTERLEN-1;x++)
- {
- sfiterArray[x]=sfiterArray[x+1];
- }
- sfiterArray[FILTERLEN-1]=lowpulse;
- for(x=0;x<FILTERLEN;x++)
- {
- Serial.println(sfiterArray[x]);
- }
- Serial.println("Aver:");
- Serial.println(Array_Average(sfiterArray,FILTERLEN));
- Serial.println("filter1 END");
- return(Array_Average(sfiterArray,FILTERLEN));
-
- }
-
-
- }
- /*END: filter program : 20130521 */
-
- int x=0; //simulated sensor output
- int sampling=1;
- int transfering=0;
-
- /* Modbus para */
- int retval;
- int data[10];
- int tt[30]; //int changed to unsigned int
-
- void loop() {
-
- int i;
- /* example, this will write some data in the first 10 registers of slave 1 */
- // retval = preset_multiple_registers(1,1,10, data);
-
- // data[0] = retval;
- // data[1]++;
- // data[8]=0xdead;
- // data[9] = 0xbeaf;
- // delay(500);
- //int read_holding_registers(int slave, int start_addr, int count,int *dest, int dest_size);
- // retval = read_holding_registers(2,1, 1,tt,6);
- retval = read_holding_registers(1, 0x49, 6, tt, 1); // 1:5,2:7,3:9
- // delay(1000);
- // Serial.print("receve flag=");
- // Serial.println(retval);
-
-
- int Voltage = tt[0];
- Voltage = Voltage / 100;
- float Amp = tt[1];
- Amp = Amp / 1000;
- int Watt = tt[2];
- //long y=x0*65536+x1;
- unsigned int Kwhh = (unsigned int)tt[3];
- //unsigned int Kwhh = (unsigned int)65535; //test maximum
- unsigned int Kwhl = (unsigned int)tt[4];
- unsigned long kwhA = (unsigned long) Kwhh *65536 + Kwhl;
- // unsigned long kwhA = Kwhh <<16 + Kwhl;
- float Kwh = kwhA;
- Kwh = Kwh / 3200;
- // double Kwh = kwhA / 3200; //Kwh = kwh / 32;
- // int Kwh = tt[4];
- float Pf = tt[5];
- Pf = Pf / 1000;
- float Cabon = tt[5];
- Cabon = Cabon / 1000;
-
-
- Serial.print(Voltage);
- Serial.print(Amp);
- Serial.print(Watt);
- Serial.print(Kwh);
- Serial.print(Pf);
- Serial.print(Cabon);
-
-
- // 4 Parameter: watt / kwh / Amp / Voltage / Pf
-
- lwc->append("T21", Kwh);
- lwc->append("T22", Watt);
- lwc->append("T23", Amp);
- lwc->append("T24", Voltage);
- lwc->append("T25", Pf);
- // lwc->append("06", Cabon);
-
-
- lwc->send();
- delay(15000);
- }
-
- // this method makes a HTTP connection to the server:
-
-
- /****************************************************************************
- * BEGIN MODBUS RTU MASTER FUNCTIONS
- ****************************************************************************/
-
- //#define TIMEOUT 1000 /* 1 second */
- #define TIMEOUT 10000 /* 10 second */
- #define MAX_READ_REGS 125
- #define MAX_WRITE_REGS 125
- #define MAX_RESPONSE_LENGTH 256
- #define PRESET_QUERY_SIZE 256
- /* errors */
- #define PORT_ERROR -5
-
- /*
- CRC
-
- INPUTS:
- buf -> Array containing message to be sent to controller.
- start -> Start of loop in crc counter, usually 0.
- cnt -> Amount of bytes in message being sent to controller/
- OUTPUTS:
- temp -> Returns crc byte for message.
- COMMENTS:
- This routine calculates the crc high and low byte of a message.
- Note that this crc is only used for Modbus, not Modbus+ etc.
- ****************************************************************************/
-
- unsigned int crc(unsigned char *buf, int start, int cnt)
- {
- int i, j;
- unsigned temp, temp2, flag;
-
- temp = 0xFFFF;
-
- for (i = start; i < cnt; i++) {
- temp = temp ^ buf[i];
-
- for (j = 1; j <= 8; j++) {
- flag = temp & 0x0001;
- temp = temp >> 1;
- if (flag)
- temp = temp ^ 0xA001;
- }
- }
-
- /* Reverse byte order. */
-
- temp2 = temp >> 8;
- temp = (temp << 8) | temp2;
- temp &= 0xFFFF;
-
- return (temp);
- }
-
-
- /***********************************************************************
- *
- * The following functions construct the required query into
- * a modbus query packet.
- *
- ***********************************************************************/
-
- #define REQUEST_QUERY_SIZE 6 /* the following packets require */
- #define CHECKSUM_SIZE 2 /* 6 unsigned chars for the packet plus */
- /* 2 for the checksum. */
-
- void build_request_packet(int slave, int function, int start_addr,
- int count, unsigned char *packet)
- {
- packet[0] = slave;
- packet[1] = function;
- start_addr -= 1;
- packet[2] = start_addr >> 8;
- packet[3] = start_addr & 0x00ff;
- packet[4] = count >> 8;
- packet[5] = count & 0x00ff;
-
- //below test only
- // packet[0] =0x01;
- // packet[1] = 0x03;
- // packet[2] = 0;
- // packet[3] = 0x48;
- // packet[4] = 0;
- // packet[5] = 0x02;
- }
-
- /*************************************************************************
- *
- * modbus_query( packet, length)
- *
- * Function to add a checksum to the end of a packet.
- * Please note that the packet array must be at least 2 fields longer than
- * string_length.
- **************************************************************************/
-
- void modbus_query(unsigned char *packet, size_t string_length)
- {
- int temp_crc;
-
- temp_crc = crc(packet, 0, string_length);
-
- packet[string_length++] = temp_crc >> 8;
- packet[string_length++] = temp_crc & 0x00FF;
- packet[string_length] = 0;
- }
-
-
-
- /***********************************************************************
- *
- * send_query(query_string, query_length )
- *
- * Function to send a query out to a modbus slave.
- ************************************************************************/
-
- int send_query(unsigned char *query, size_t string_length)
- {
-
- int i;
-
- modbus_query(query, string_length);
- string_length += 2;
-
- for (i = 0; i < string_length; i++) {
- // Serial.print(query[i], HEX); //Orginal
- Serial.write(query[i]); //JingLi
-
- }
- /* without the following delay, the reading of the response might be wrong
- * apparently, */
- delay(200); /* FIXME: value to use? */
-
- return i; /* it does not mean that the write was succesful, though */
- }
-
-
- /***********************************************************************
- *
- * receive_response( array_for_data )
- *
- * Function to monitor for the reply from the modbus slave.
- * This function blocks for timeout seconds if there is no reply.
- *
- * Returns: Total number of characters received.
- ***********************************************************************/
-
- int receive_response(unsigned char *received_string)
- {
-
- int bytes_received = 0;
- int i = 0;
- /* wait for a response; this will block! */
- while(Serial.available() == 0) {
- delay(1);
- if (i++ > TIMEOUT)
- return bytes_received;
- }
- delay(200);
- /* FIXME: does Serial.available wait 1.5T or 3.5T before exiting the loop? */
- while(Serial.available()) {
- received_string[bytes_received] = Serial.read();
- // Serial.print(bytes_received); //only test
- // Serial.print("-"); //only test
- // Serial.println(received_string[bytes_received]); //only test
- bytes_received++;
- if (bytes_received >= MAX_RESPONSE_LENGTH)
- return PORT_ERROR;
- }
- //Serial.print("bytes_received=");
- //Serial.println(bytes_received);
- return (bytes_received);
- }
-
-
- /*********************************************************************
- *
- * modbus_response( response_data_array, query_array )
- *
- * Function to the correct response is returned and that the checksum
- * is correct.
- *
- * Returns: string_length if OK
- * 0 if failed
- * Less than 0 for exception errors
- *
- * Note: All functions used for sending or receiving data via
- * modbus return these return values.
- *
- **********************************************************************/
-
- int modbus_response(unsigned char *data, unsigned char *query)
- {
- int response_length;
- int i;
- unsigned int crc_calc = 0;
- unsigned int crc_received = 0;
- unsigned char recv_crc_hi;
- unsigned char recv_crc_lo;
-
- do { // repeat if unexpected slave replied
- response_length = receive_response(data);
- }
- while ((response_length > 0) && (data[0] != query[0]));
- // for (i = 0; i <response_length; i++) { Serial.print(data[i]);Serial.print("---"); Serial.println(query[i]);} //only test
-
- if (response_length) {
-
-
- crc_calc = crc(data, 0, response_length - 2);
-
- recv_crc_hi = (unsigned) data[response_length - 2];
- recv_crc_lo = (unsigned) data[response_length - 1];
-
- crc_received = data[response_length - 2];
- crc_received = (unsigned) crc_received << 8;
- crc_received =
- crc_received | (unsigned) data[response_length - 1];
-
-
- /*********** check CRC of response ************/
-
- if (crc_calc != crc_received) {
- response_length = 0;
- // Serial.println("CRC erro"); //only test
- }
-
-
-
- /********** check for exception response *****/
-
- if (response_length && data[1] != query[1]) {
- response_length = 0 - data[2];
- }
- }
- return (response_length);
- }
-
-
- /************************************************************************
- *
- * read_reg_response
- *
- * reads the response data from a slave and puts the data into an
- * array.
- *
- ************************************************************************/
-
- int read_reg_response(int *dest, int dest_size, unsigned char *query)
- {
-
- unsigned char data[MAX_RESPONSE_LENGTH];
- int raw_response_length;
- int temp, i;
-
- raw_response_length = modbus_response(data, query);
- if (raw_response_length > 0)
- raw_response_length -= 2;
-
- if (raw_response_length > 0) {
- /* FIXME: data[2] * 2 ???!!! data[2] isn't already the byte count (number of registers * 2)?! */
- for (i = 0;
- i < (data[2] * 2) && i < (raw_response_length / 2);
- i++) {
-
- /* shift reg hi_byte to temp */
- temp = data[3 + i * 2] << 8;
- /* OR with lo_byte */
- temp = temp | data[4 + i * 2];
-
- dest[i] = temp;
- }
- }
- return (raw_response_length);
- }
-
-
- /***********************************************************************
- *
- * preset_response
- *
- * Gets the raw data from the input stream.
- *
- ***********************************************************************/
-
- int preset_response(unsigned char *query)
- {
- unsigned char data[MAX_RESPONSE_LENGTH];
- int raw_response_length;
-
- raw_response_length = modbus_response(data, query);
-
- return (raw_response_length);
- }
-
-
- /************************************************************************
- *
- * read_holding_registers
- *
- * Read the holding registers in a slave and put the data into
- * an array.
- *
- *************************************************************************/
-
- int read_holding_registers(int slave, int start_addr, int count,
- int *dest, int dest_size)
- {
- int function = 0x03; /* Function: Read Holding Registers */
- int ret;
-
- unsigned char packet[REQUEST_QUERY_SIZE + CHECKSUM_SIZE];
-
- if (count > MAX_READ_REGS) {
- count = MAX_READ_REGS;
- }
-
- build_request_packet(slave, function, start_addr, count, packet);
-
- if (send_query(packet, REQUEST_QUERY_SIZE) > -1) {
- ret = read_reg_response(dest, dest_size, packet);
- }
- else {
-
- ret = -1;
- }
-
- return (ret);
- }
-
-
- /************************************************************************
- *
- * preset_multiple_registers
- *
- * Write the data from an array into the holding registers of a
- * slave.
- *
- *************************************************************************/
-
- int preset_multiple_registers(int slave, int start_addr,
- int reg_count, int *data)
- {
- int function = 0x10; /* Function 16: Write Multiple Registers */
- int byte_count, i, packet_size = 6;
- int ret;
-
- unsigned char packet[PRESET_QUERY_SIZE];
-
- if (reg_count > MAX_WRITE_REGS) {
- reg_count = MAX_WRITE_REGS;
- }
-
- build_request_packet(slave, function, start_addr, reg_count, packet);
- byte_count = reg_count * 2;
- packet[6] = (unsigned char)byte_count;
-
- for (i = 0; i < reg_count; i++) {
- packet_size++;
- packet[packet_size] = data[i] >> 8;
- packet_size++;
- packet[packet_size] = data[i] & 0x00FF;
- }
-
- packet_size++;
- if (send_query(packet, packet_size) > -1) {
- ret = preset_response(packet);
- }
- else {
- ret = -1;
- }
-
- return (ret);
- }
当然了上面还需要两个库文件,一个是以太网的网络模块W5500库,和乐为的上传库,这里自行到文章后面下载。大致就是这样的,然后设备接入网络,通电就可以了。由于我的路由上上有USB输出,所以我直接通过USB给arduino主机供电。如下图:等几分钟后台就会看见上传的数据了。 我的电量表https://www.lewei50.com/u/g/6884。这里可以看见你实时的用电功率和每天的用电量,要是会点开发知识的话,可以根据API接口算出你每月要交多少大洋的电费。这样每个月的消费就一目了然了。 文章转载于:http://www.zishuo.net/with-it-is-not-afraid-of-the-landlord-overcharged-electricity.html [ 此帖被darkit在2014-10-03 23:44重新编辑 ]
|