2702
- 收藏
- 点赞
- 分享
- 举报
可视化网络电表搭建攻略
标题起得比较唬人,请无视。
×友情提示,修改电路前,一定要断开电源总开关×
你想象过看着家里的电器用电的样子吗?
你知道你每月那几天交的钱都去了哪里了吗?
你知道是什么东东在偷偷的用你的电吗?
如果你感兴趣,下面的文章适合你。
电,对于很多人来说是个很神秘,很危险,很神奇的东西。现在通过下面的攻略,你也可以拥有这样神奇的超能力,看到家里的电跑到哪里去了,是不是很想要?
====小广告====
你需要:
一个测电笔
一个十字口螺丝刀
一个平口螺丝刀
一把尖嘴钳
一个电量测量模块
一个通讯底板(我用的乐联网的E-KIT),你也可以使用任何一种arduino+w5100模块来搭建。

====广告结束===
先看看效果图(据说近期会有新版的展示界面)
在线链接:
[url]http://www.lewei50.com/u/g/1979[/url]


看到下面的锯齿状图形了吗?那就是你的冰箱在努力保持西瓜的新鲜。
几个用电高峰,是空调们在为主人降温。
用电量怎么总是高于0呢?那是你的无线路由器在保持家里的网络时刻畅通。
现在分步骤来实现它:
1断电
要断开家里空气开关的总闸,如果有室外的总闸,那就拉室外的总闸,保证家里是没有电的。
操作时严禁一只手碰火线,一只手碰零线。

2接线
打开家里的配电箱,找到总的进户的火线,拆开,把电量测量模块的圈圈套在这个火线上,专业术语是“互感器”。并把火线按照原来的位置接回去。

按照接线说明图,连接好测量模块、通讯模块和arduino。
3通电
如果你的操作正确,这时候推上你家的空气开关总闸,是不会有任何反应的。如果有问题,会跳闸。
4注册网站及设置对应传感器
[url]http://www.lewei50.com/[/url]
注册及配置传感器过程不详细说明了。简单说下我的传感器的命名,你也可以有你自己的。

5刷代码
刷代码是为了从通讯模块里面把电量等数据读出来,并上传到乐联网上。
代码中使用了乐联网的类库,从这里下载:
[url]http://www.github.com/lewei50/LeWeiClient/[/url]
[code]// 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
#include
#include
#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
{
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
{
sfiterArray[x]=sfiterArray[x+1];
}
sfiterArray[FILTERLEN-1]=lowpulse;
for(x=0;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("kwh", Kwh);
lwc->append("w", Watt);
lwc->append("a", Amp);
lwc->append("v", Voltage);
lwc->append("pf", 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;
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, HEX); //Orginal
Serial.write(query); //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);Serial.print("---"); Serial.println(query);} //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 = 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 >> 8;
packet_size++;
packet[packet_size] = data & 0x00FF;
}
packet_size++;
if (send_query(packet, packet_size) > -1) {
ret = preset_response(packet);
}
else {
ret = -1;
}
return (ret);
}
[/code]
6将电量可视化、数字化之后,你可以做很多的事情,自己琢磨吧~
Enjoy it~
原帖地址
[url]http://www.geek-workshop.com/thread-5649-1-1.html[/url]
×友情提示,修改电路前,一定要断开电源总开关×
你想象过看着家里的电器用电的样子吗?
你知道你每月那几天交的钱都去了哪里了吗?
你知道是什么东东在偷偷的用你的电吗?
如果你感兴趣,下面的文章适合你。
电,对于很多人来说是个很神秘,很危险,很神奇的东西。现在通过下面的攻略,你也可以拥有这样神奇的超能力,看到家里的电跑到哪里去了,是不是很想要?
====小广告====
你需要:
一个测电笔
一个十字口螺丝刀
一个平口螺丝刀
一把尖嘴钳
一个电量测量模块
一个通讯底板(我用的乐联网的E-KIT),你也可以使用任何一种arduino+w5100模块来搭建。

====广告结束===
先看看效果图(据说近期会有新版的展示界面)
在线链接:
[url]http://www.lewei50.com/u/g/1979[/url]


看到下面的锯齿状图形了吗?那就是你的冰箱在努力保持西瓜的新鲜。
几个用电高峰,是空调们在为主人降温。
用电量怎么总是高于0呢?那是你的无线路由器在保持家里的网络时刻畅通。
现在分步骤来实现它:
1断电
要断开家里空气开关的总闸,如果有室外的总闸,那就拉室外的总闸,保证家里是没有电的。
操作时严禁一只手碰火线,一只手碰零线。

2接线
打开家里的配电箱,找到总的进户的火线,拆开,把电量测量模块的圈圈套在这个火线上,专业术语是“互感器”。并把火线按照原来的位置接回去。

按照接线说明图,连接好测量模块、通讯模块和arduino。
3通电
如果你的操作正确,这时候推上你家的空气开关总闸,是不会有任何反应的。如果有问题,会跳闸。
4注册网站及设置对应传感器
[url]http://www.lewei50.com/[/url]
注册及配置传感器过程不详细说明了。简单说下我的传感器的命名,你也可以有你自己的。

5刷代码
刷代码是为了从通讯模块里面把电量等数据读出来,并上传到乐联网上。
代码中使用了乐联网的类库,从这里下载:
[url]http://www.github.com/lewei50/LeWeiClient/[/url]
[code]// 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
#include
#include
#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
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
sfiterArray[x]=sfiterArray[x+1];
}
sfiterArray[FILTERLEN-1]=lowpulse;
for(x=0;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("kwh", Kwh);
lwc->append("w", Watt);
lwc->append("a", Amp);
lwc->append("v", Voltage);
lwc->append("pf", 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;
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, HEX); //Orginal
Serial.write(query); //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
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 = 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 >> 8;
packet_size++;
packet[packet_size] = data & 0x00FF;
}
packet_size++;
if (send_query(packet, packet_size) > -1) {
ret = preset_response(packet);
}
else {
ret = -1;
}
return (ret);
}
[/code]
6将电量可视化、数字化之后,你可以做很多的事情,自己琢磨吧~
Enjoy it~
原帖地址
[url]http://www.geek-workshop.com/thread-5649-1-1.html[/url]
我来回答
回答1个
时间排序
认可量排序
认可0
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片
相关问答
-
2018-12-06 10:30:44
-
2019-01-14 14:08:09
-
2019-01-03 15:12:27
-
2018-10-18 14:41:18
-
2019-04-22 11:47:46
-
2012-12-04 11:44:53
-
02015-09-19 17:04:06
-
2008-07-19 13:53:26
-
2008-07-19 13:55:09
-
2016-10-27 15:27:23
-
2018-03-16 10:28:55
-
2013-11-17 10:28:02
-
2019-04-26 13:34:07
-
2018-03-20 16:42:54
-
2012-12-04 11:44:18
-
2015-01-19 19:33:17
-
2019-06-26 11:23:03
-
2019-04-26 10:55:42
-
2019-04-28 11:51:40
无更多相似问答 去提问

点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认