今天又给大家带来了一篇开源帖子了,这是我们团队上次参加one net创新赛荣获二等奖的项目作品,原创发于one net 官网论坛http://open.iot.10086.cn/bbs/thread-1154-1-1.html,在这次比赛中收获很多,发于本论坛希望有更多的人来一起学习研究!
一、简介:
针对目前我国水产养殖规模越来越大,种类越来越丰富,传统养殖方式已不能满足要求的现状,“互联网+”必将带动农业的升级。本作品将物联网技术相结合应用到水产养殖领域,设计了水产养殖智能化系统的架构及应用实施方案。分为现场管理单元、远程管理单元、云平台(OneNET)三个部分。
二、主要功能:
1、通过PH传感器、溶解氧传感器、温度传感器、光照传感器,(还可以增加对水体检测的各种传感器,因为价格太高目前楼主只用了这几个传感器)。在任何终端(登录OneNET云平台)上都可以查看水体的实时数据。
2、有对水产,实时的视频监控(无线传输,随处访问)。
3、能自动对水体的PH调节,供氧,补充光亮,投饵。
三:作品整体效果:
1、所用到的传感器:(除光照传感器外,其他三种传感器输出的是4~20mA的电流信号,而我们需要取5v电压信号作为输出。因此需要用到电压转换器LM324,将电流转换为电压,大家在选传感器时可以直接选用输出为电压信号的。)
2、执行部分:
3、核心芯片:Arduino Uno+ESP8266
4、硬件连接方法:
5、程序如下:(程序以调试完成,可直接运行)https://www.arduino.cc/en/Main/Software(Arduino IDE环境地址);
[kenrobot_code]/*
采用外接电源单独供电,2 3口作为软串口接PC机作为调试端
1 0为串口,连接WIFI模块
*/
#include <Wire.h>
#include <math.h>
#include <SoftwareSerial.h>
#include "edp.c"
//#define YAN_DEBUG_CTRL
// GY-30
// BH1750FVI 光照传感器
// in ADDR 'L' mode 7bit addr
#define ADDR 0b0100011
#define KEY "mTQiviJTfGb48Qv2=gibocgOCEU=" //APIkey(改为自己的API)
#define ID "4049843" //设备ID(改为自己的ID)
//#define PUSH_ID "680788"
#define PUSH_ID NULL
// 串口
#define _baudrate 115200
#define _rxpin 3
#define _txpin 2
#define WIFI_UART Serial
#define DBG_UART dbgSerial //调试打印串口
//
int potpiA =A1; //酸碱度
int valla=0;
int potpiB =A2; //溶解氧
int vallb=0;
int potpiC =A3; //温度
int vallc=0;
int potpiD =A4; //光照
int valld=0;
//
SoftwareSerial dbgSerial( _rxpin, _txpin ); // 软串口,调试打印
edp_pkt *pkt;
/*
* doCmdOk
* 发送命令至模块,从回复中获取期待的关键字
* keyword: 所期待的关键字
* 成功找到关键字返回true,否则返回false
*/
bool doCmdOk(String data, char *keyword)
{
bool result = false;
if (data != "") //对于tcp连接命令,直接等待第二次回复
{
if(data=="+++")
{
WIFI_UART.print("+++");
}
else
{
WIFI_UART.println(data); //发送AT指令
DBG_UART.print("SEND: ");
DBG_UART.println(data);
}
}
delay(500);
if (data == "AT" || data == "+++") //检查模块存在
delay(2000);
else
while (!WIFI_UART.available()); // 等待模块回复
delay(500);
if (WIFI_UART.find(keyword)) //返回值判断
{
DBG_UART.println("do cmd OK");
result = true;
}
else
{
DBG_UART.println("do cmd ERROR");
result = false;
}
while (WIFI_UART.available()) WIFI_UART.read(); //清空串口接收缓存
delay(500); //指令时间间隔
return result;
}
void setup()
{
char buf[100] = {0};
int tmp;
pinMode(13, OUTPUT); //WIFI模块指示灯
//
pinMode(8, OUTPUT); //光照开关
pinMode(9, OUTPUT); //PH氧阀门
pinMode(10, OUTPUT); //增氧阀门
pinMode(11, OUTPUT); //投饵机阀门
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
digitalWrite(10, HIGH);
digitalWrite(11, HIGH);
//
digitalWrite(13, HIGH); // 使Led亮
WIFI_UART.begin( _baudrate );
DBG_UART.begin( _baudrate );
WIFI_UART.setTimeout(3000); //设置find超时时间
delay(3000);
DBG_UART.println("hello world!");
// 光照传感器初始化
Wire.begin();
Wire.beginTransmission(ADDR);
Wire.write(0b00000001);
Wire.endTransmission();
delay(2000);
//while (!doCmdOk("AT", "OK"));
//可能模块重新启动了
while(1)
{
if(doCmdOk("AT", "OK"))break;
delay(2000);
doCmdOk("+++", "OK");
}
while (!doCmdOk("AT+CWMODE=3", "OK")); //工作模式digitalWrite(13, LOW); // 使Led灭
while (!doCmdOk("AT+CWJAP=\"123\",\"1234567890\"", "OK"));//将“123”和“1234567890”改为你自己的wifi用户名和密码
delay(10);
// doCmdOk("AT+CIPCLOSE", "OK");delay(10);
while (!doCmdOk("AT+CIPSTART=\"TCP\",\"183.230.40.39\",876", "CONNECT"));//CONNECT,Linked
while (!doCmdOk("AT+CIPMODE=1", "OK")); //透传模式
while (!doCmdOk("AT+CIPSEND", ">")); //开始发送
digitalWrite(13, LOW); // 使Led灭
}
void loop()
{
static int edp_connect = 0;
bool trigger = false;
//
bool tra= false; //待定
bool trb= false;
bool trc= false;
//
edp_pkt rcv_pkt;
unsigned char pkt_type;
int i, tmp;
char num[10]; //光照
//
char shuanjiand[10]; //酸碱度字符
char rongjiey[10]; //溶解氧字符
char wendu[10]; //温度字符
//
/* EDP 连接 */
if (!edp_connect)
{
while (WIFI_UART.available()) WIFI_UART.read(); //清空串口接收缓存
packetSend(packetConnect(ID, KEY)); //发送EPD连接包
while (!WIFI_UART.available()); //等待EDP连接应答
if ((tmp = WIFI_UART.readBytes(rcv_pkt.data, sizeof(rcv_pkt.data))) > 0 )
{
rcvDebug(rcv_pkt.data, tmp);
if (rcv_pkt.data[0] == 0x20 && rcv_pkt.data[2] == 0x00 && rcv_pkt.data[3] == 0x00)
{
edp_connect = 1;
DBG_UART.println("EDP connected.");
}
else
DBG_UART.println("EDP connect error.");
}
packetClear(&rcv_pkt);
}
// 酸碱度上传
tra = SJD(shuanjiand);//模拟心跳包,如果没有数据要传送,则需要心跳包
if (edp_connect && tra)
{
DBG_UART.print("SJD: ");
DBG_UART.println(shuanjiand);
packetSend(packetDataSaveTrans(PUSH_ID, "suan", shuanjiand)); //发送数据存储包
}
// 溶解氧数据上传
trb = RJY(rongjiey);//模拟心跳包,如果没有数据要传送,则需要心跳包
if (edp_connect && rongjiey)
{
DBG_UART.print("RJY: ");
DBG_UART.println(rongjiey);
packetSend(packetDataSaveTrans(PUSH_ID, "rong", rongjiey)); //发送数据存储包
}
// 温度数据上传
trc = WD(wendu);//模拟心跳包,如果没有数据要传送,则需要心跳包
if (edp_connect && trc)
{
DBG_UART.print("WD: ");
DBG_UART.println(wendu);
packetSend(packetDataSaveTrans(PUSH_ID, "wen", wendu)); //发送数据存储包
}
// 光照数据上传
trigger = readGY_30(num);//模拟心跳包,如果没有数据要传送,则需要心跳包
if (edp_connect && trigger)
{
DBG_UART.print("GY_30: ");
DBG_UART.println(num);
packetSend(packetDataSaveTrans(PUSH_ID, "guang", num)); //发送数据存储包
//当PUSH_ID不为NULL时转发至PUSH_ID
}
while (WIFI_UART.available())
{
readE**kt(&rcv_pkt);
if (isE**kt(&rcv_pkt))
{
pkt_type = rcv_pkt.data[0];
switch (pkt_type)
{
case CMDREQ:
char edp_command[50];
char edp_cmd_id[40];
long id_len, cmd_len, rm_len;
char datastr[20];
char val[10];
memset(edp_command, 0, sizeof(edp_command));
memset(edp_cmd_id, 0, sizeof(edp_cmd_id));
edpCommandReqParse(&rcv_pkt, edp_cmd_id, edp_command, &rm_len, &id_len, &cmd_len);
DBG_UART.print("rm_len: ");
DBG_UART.println(rm_len, DEC);
delay(10);
DBG_UART.print("id_len: ");
DBG_UART.println(id_len, DEC);
delay(10);
DBG_UART.print("cmd_len: ");
DBG_UART.println(cmd_len, DEC);
delay(10);
DBG_UART.print("id: ");
DBG_UART.println(edp_cmd_id);
delay(10);
DBG_UART.print("cmd: ");
DBG_UART.println(edp_command);
//数据处理与应用中EDP命令内容对应
//本例中格式为 datastream:[1/0]
//sscanf(edp_command, "%[^:]:%s",val);
sscanf(edp_command, "%[^:]:%s", datastr, val);
// sscanf(edp_command, val);
if (atoi(val) == 1)//光照开关
digitalWrite(8, LOW);
if (atoi(val) == 3)
digitalWrite(8, HIGH);
if(atoi(val) == 2) //PH阀门
digitalWrite(9, LOW);
if (atoi(val) == 5)
digitalWrite(9, HIGH);
if(atoi(val) == 14) //增氧阀门
digitalWrite(10, LOW);
if (atoi(val) == 7)
digitalWrite(10,HIGH);
if(atoi(val) == 4) //投饵机阀门
digitalWrite(11, LOW);
if (atoi(val) == 9)
digitalWrite(11, HIGH);
packetSend(packetDataSaveTrans(NULL, datastr, val)); //将新数据值上传至数据流
break;
default:
DBG_UART.print("unknown type: ");
DBG_UART.println(pkt_type, HEX);
break;
}
}
//delay(4);
}
if (rcv_pkt.len > 0)
packetClear(&rcv_pkt);
delay(150);
}
/*
* readE**kt
* 从串口缓存中读数据到接收缓存
*/
bool readE**kt(edp_pkt *p)
{
int tmp;
if ((tmp = WIFI_UART.readBytes(p->data + p->len, sizeof(p->data))) > 0 )
{
rcvDebug(p->data + p->len, tmp);
p->len += tmp;
}
return true;
}
/*
* packetSend
* 将待发数据发送至串口,并释放到动态分配的内存
*/
void packetSend(edp_pkt* pkt)
{
if (pkt != NULL)
{
WIFI_UART.write(pkt->data, pkt->len); //串口发送
WIFI_UART.flush();
free(pkt); //回收内存
}
}
void rcvDebug(unsigned char *rcv, int len)
{
int i;
DBG_UART.print("rcv len: ");
DBG_UART.println(len, DEC);
for (i = 0; i < len; i++)
{
DBG_UART.print(rcv, HEX);
DBG_UART.print(" ");
}
DBG_UART.println("");
}
/*
bool readGY_30(char *num) //光照传感器
{
static int val = 0, count = 10;;
int tmp;
// reset
Wire.beginTransmission(ADDR);
Wire.write(0b00000111);
Wire.endTransmission();
delay(100);
Wire.beginTransmission(ADDR);
Wire.write(0b00100000);
Wire.endTransmission();
// typical read delay 120ms
delay(120);
Wire.requestFrom(ADDR, 2); // 2byte every time
while (Wire.available())
{
char c = Wire.read();
//DBG_UART.println(c, HEX);
tmp = (tmp << 8) + (c & 0xFF);
}
tmp = tmp / 1.2;
sprintf(num, "%d", tmp);
if (--count == 0)
{
count = 10;
return true;
}
return false;
}
*/
//
bool SJD(char *shuanjiand) //酸碱度
{
float a=0;
a=analogRead(potpiA);
valla=a/17.53;
delay(2000);
sprintf(shuanjiand,"%d",valla);
}
bool RJY(char *rongjiey) //溶解氧
{
int b=0;
b=analogRead(potpiB);
vallb=b/52.42;
delay(2000);
sprintf(rongjiey,"%d",vallb);
}
bool WD(char *wendu) //温度
{
double Temp,c;
c=analogRead(potpiC);
Temp = log(((10240000/c) - 10000));
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
Temp = Temp - 273.15;
vallc=Temp;
delay(2000);
sprintf(wendu,"%d",vallc);
}
//
bool readGY_30(char *num) //光照
{
valld=analogRead(potpiD);
delay(2000);
sprintf(num,"%d",valld);
#ifdef YAN_DEBUG_CTRL
return false;
#else
return true;
#endif
}
[/kenrobot_code]
6、OneNET管理平台:http://open.iot.10086.cn/appview/p/97f195b16f3536d6556c308b64610e79
8、视频查看地址:http://v.youku.com/v_show/id_XMTgzNDk1NTM0NA==.html(视频效果比较明显,大家可以访问地址观看)
这就是整个作品的流程,欢迎大家浏览。如果在作品中没有描述清楚的,请大家批评指正。
|