查看: 4707|回复: 7

[项目教程] 【OBLOQ - IoT物联网模块试用】+物联网浇花控制

[复制链接]
本帖最后由 422234 于 2018-3-18 19:55 编辑

20180307_133954.jpg 20180307_134706.jpg

之前收到的物联网模块,作业来了,感谢DFrobot提供的试用,非常感谢!
看了OBLOQ - IoT物联网模块的文档后感觉到很简单啊,照着官方的例子很快就可以做出来,比其他的平台好用多了,就像其他人反应的那样,只能接受1000条消息真的不够啊,而且还不能自动清除,表示完全不实用啊,分分钟就慢了,下面做的这个物联网浇花系统是可以将土壤湿度传感器测得的土壤湿度通过OBLOQ - IoT物联网模块发送给DF的iot平台上,然后就可以远程看花当前的湿度,同时,也可以通过OBLOQ - IoT物联网模块给bluno发送串口消息,只要收到平台发来的“water”就会打开继电器,给水泵通电开始浇花。(水泵找不到了,只拿了个继电器,见谅见谅

20180317_183814.jpg
1.硬件材料:
Bluno 1
OBLOQ - IoT物联网模块 1
继电器1
土壤湿度传感器 1
杜邦线若干
2.硬件接线图:
接线图.jpg
来张凌乱的实物吧:
20180317_190635.jpg

3.代码:(这代码显示什么情况,为什么那么窄了)
[AppleScript] 纯文本查看 复制代码
/*
 Name:                OBLOQ_project.ino
 Created:        2018/3/16 22:00:41
 Author:        oscai
*/

#include <Arduino.h>
#include <SoftwareSerial.h>


#define WIFISSID "wifi名称" 
#define WIFIPWD  "wifi密码" 
#define SERVER   "iot.dfrobot.com.cn"
#define PORT     1883
#define IOTID    "rJZAoEe6df"
#define IOTPWD   "SkMAoVga_G"


#define PIN_AO 2  
#define PIN_DO 4  
#define PIN_Relay 3 



const String separator = "|";
bool pingOn = true;
bool obloqConnectMqtt = false;
bool subscribeMqttTopic = false;
static unsigned long pingInterval = 2000;
static unsigned long sendMessageInterval = 10000;
unsigned long previousPingTime = 0;
bool subscribeSuccess = false;
String receiveStringIndex[10] = {};
unsigned long previousSendMessageTime = 0;

//wifi异常断开检测变量
bool wifiConnect = false;
bool wifiAbnormalDisconnect = false;

//mqtt因为网络断开后重新连接标志
bool mqttReconnectFlag = false;

SoftwareSerial softSerial(10, 11);

enum state {
        WAIT,
        PINGOK,
        WIFIOK,
        MQTTCONNECTOK
}obloqState;


/********************************************************************************************
Function    : sendMessage
Description : 通过串口向OBLOQ发送一次消息
Params      : 无
Return      : 无
********************************************************************************************/
void sendMessage(String message)
{
        softSerial.print(message + "\r");
}

/********************************************************************************************
Function    : ping
Description : 通过串口向OBLOQ发送一次字符串"|1|1|",尝试与OBLOQ取得连接
Params      : 无
Return      : 无
********************************************************************************************/
void ping()
{
        String pingMessage = "|1|1|";
        sendMessage(pingMessage);
}

/********************************************************************************************
Function    : connectWifi
Description : 连接wifi
Params      : ssid 连接wifi的ssid;pwd 连接wifi的password
Return      : 无
********************************************************************************************/
void connectWifi(String ssid, String pwd)
{
        String wifiMessage = "|2|1|" + ssid + "," + pwd + separator;
        sendMessage(wifiMessage);
}

/********************************************************************************************
Function    : connectMqtt
Description : 连接DF-IoT
Params      : server 物联网网址;port 端口;iotid 物联网登录后分配的iotid;iotpwd 物联网登录后分配的iotpwd
Return      : 无
********************************************************************************************/
void connectMqtt(String server, String port, String iotid, String iotpwd)
{
        String mqttConnectMessage = "|4|1|1|" + server + separator + port + separator + iotid + separator + iotpwd + separator;
        sendMessage(mqttConnectMessage);
}

/********************************************************************************************
Function    : reconnectMqtt
Description : 重新连接DF-IoT
Params      : 无
Return      : 无
********************************************************************************************/
void reconnectMqtt()
{
        String mqttReconnectMessage = "|4|1|5|";
        sendMessage(mqttReconnectMessage);
}

/********************************************************************************************
Function    : publish
Description : 向DF-IoT物联网设备发送信息
Params      : topic DF-IoT物联网设备编号;message 发送的消息内容
Return      : 无
********************************************************************************************/
void publish(String topic, String message)
{
        String publishMessage = "|4|1|3|" + topic + separator + message + separator;
        sendMessage(publishMessage);
}


/********************************************************************************************
Function    : subscribe
Description : 订阅DF-IoT物联网设备
Params      : topic DF-IoT物联网设备编号
Return      : 无
********************************************************************************************/
void subscribe(String topic)
{
        String subscribeMessage = "|4|1|2|" + topic + separator;
        sendMessage(subscribeMessage);
}


/********************************************************************************************
Function    : splitString
Description : 剔除分隔符,逐一提取字符串
Params      : data[] 提取的字符串的目标储存地址;str 源字符串;delimiters 分隔符
Return      : 共提取的字符串的个数
********************************************************************************************/
int splitString(String data[], String str, const char* delimiters)
{
        char *s = (char *)(str.c_str());
        int count = 0;
        data[count] = strtok(s, delimiters);
        while (data[count]) {
                data[++count] = strtok(NULL, delimiters);
        }
        return count;
}



/********************************************************************************************
Function    : handleUart
Description : 处理串口传回的数据
Params      : 无
Return      : 无
********************************************************************************************/
void handleUart()
{
        while (softSerial.available() > 0)
        {
                String receivedata = softSerial.readStringUntil('\r');
                const char* obloqMessage = receivedata.c_str();
                if (strcmp(obloqMessage, "|1|1|") == 0)
                {
                        Serial.println("Pong");
                        pingOn = false;
                        obloqState = PINGOK;
                }
                if (strcmp(obloqMessage, "|2|1|") == 0)
                {
                        if (wifiConnect)
                        {
                                wifiConnect = false;
                                wifiAbnormalDisconnect = true;
                        }
                }
                else if (strstr(obloqMessage, "|2|3|") != NULL && strlen(obloqMessage) != 9)
                {
                        Serial.println("Wifi ready");
                        wifiConnect = true;
                        if (wifiAbnormalDisconnect)
                        {
                                wifiAbnormalDisconnect = false;
                                return;
                        }
                        obloqState = WIFIOK;
                }
                else if (strcmp(obloqMessage, "|4|1|1|1|") == 0)
                {
                        Serial.println("Mqtt ready");
                        obloqConnectMqtt = true;
                        if (mqttReconnectFlag)
                        {
                                mqttReconnectFlag = false;
                                return;
                        }
                        obloqState = MQTTCONNECTOK;
                }
                else if (strcmp(obloqMessage, "|4|1|2|1|") == 0)
                {
                        Serial.println("subscribe successed");
                        //subscribeMqttTopic = false;
                }
                //DF-IoT接收到消息,topic和message传入receiveMessageCallbak函数
                else if (strstr(obloqMessage, "|4|1|5|") != NULL)
                {
                        splitString(receiveStringIndex, receivedata, "|");
                        receiveMessageCallbak(receiveStringIndex[3], receiveStringIndex[4]);
                }
        }
}

/********************************************************************************************
Function    : sendPing
Description : 每隔pingInterval一段时间,通过串口向OBLOQ ping一次
Params      : 无
Return      : 无
********************************************************************************************/
void sendPing()
{
        if (pingOn && millis() - previousPingTime > pingInterval)
        {
                previousPingTime = millis();
                ping();
        }
}

/********************************************************************************************
Function    : execute
Description : 根据OBLOQ的状态,进行下一步相应操作。
Params      : 无
Return      : 无
********************************************************************************************/
void execute()
{
        switch (obloqState)
        {
        case PINGOK: connectWifi(WIFISSID, WIFIPWD); obloqState = WAIT; break;
        case WIFIOK: connectMqtt(SERVER, String(PORT), IOTID, IOTPWD);obloqState = WAIT; break;
        case MQTTCONNECTOK: obloqState = WAIT; break;
        default: break;
        }
}

/********************************************************************************************
Function    : subscribeSingleTopic
Description : 监听单个DF-IoT物联网设备
Params      : topic DF-IoT物联网设备编号
Return      : 无
********************************************************************************************/
void subscribeSingleTopic(String topic)
{
        if (!subscribeMqttTopic && obloqConnectMqtt)
        {
                subscribeMqttTopic = true;
                subscribe(topic);
        }
}


/********************************************************************************************
Function    : receiveMessageCallbak
Description : 接收消息的回调函数
Params      : topic 发出消息的DF-IoT物联网设备编号;message 收到的消息内容,如果收到water开始浇水
Return      : 无
********************************************************************************************/
void receiveMessageCallbak(String topic, String message)
{
        Serial.println("Message from: " + topic);
        Serial.println("Message content: " + message);
        int water;
        int cmd= Serial.find(water);
        if (cmd = 1) {
                Serial.println("start watering");
                digitalWrite(PIN_Relay, HIGH);
                delay(10000);
                digitalWrite(PIN_Relay, LOW);
        }
}



/********************************************************************************************
Function    : checkWifiState
Description : 检查wifi状态,如果检测到wifi热点断开会间隔1分钟去重新连接wifi
Params      : 无
Return      : 无
********************************************************************************************/
void checkWifiState()
{
        static unsigned long previousTime = 0;
        static bool reconnectWifi = false;
        if (wifiAbnormalDisconnect && millis() - previousTime > 60000)
        {
                previousTime = millis();
                Serial.println("Wifi abnormal disconnect");
                reconnectWifi = true;
                obloqConnectMqtt = false;
                connectWifi(WIFISSID, WIFIPWD);
        }
        if (!wifiAbnormalDisconnect && reconnectWifi)
        {
                reconnectWifi = false;
                mqttReconnectFlag = true;
                Serial.println("Reconnect mqtt");
                reconnectMqtt();
        }

}

/********************************************************************************************
Function    : getHumidity
Description : 获得测得的土壤湿度
Params      : 无
Return      : 无
********************************************************************************************/
float getHumidity()
{
        uint16_t val;
        int dat;
        val = analogRead(PIN_AO);
        return val;
}



// the setup function runs once when you press reset or power the board
void setup() {
        Serial.begin(9600);
        softSerial.begin(9600);
        pinMode(PIN_AO, INPUT);
        pinMode(PIN_DO, INPUT);

        pinMode(PIN_Relay, OUTPUT);
        digitalWrite(PIN_Relay, LOW);
}

// the loop function runs over and over again until power down or reset
void loop() {
        sendPing();
        execute();
        subscribeSingleTopic("Hy3vcrcYG");
        handleUart();
        checkWifiState();
        if (obloqConnectMqtt && millis() - previousSendMessageTime > 5000) //每隔5s,向设备发送消息
        {
                previousSendMessageTime = millis();
                //获取土壤湿度数据
                float temperature = getHumidity();
                Serial.println(temperature);
                publish("ryjA4xaOG", (String)temperature);

        }
}



效果:
截图201803172117186600.png
这两个设备,一个是接收数据的,另一个是发送消息的
截图201803172117585911.png
可以看到平台收到的数据

截图201803172119057607.png
只要在平台上发送“water”后就会打开继电器10秒,开始浇花!
视频来了!

用播放器是正常的,但传优酷上就翻车了,
再次感谢DFrobot提供的试用!

1973742214  高级技师

发表于 2018-3-18 10:20:16

投入到真正的浇花元件中再录视屏就更好了,期望房主水泵快速找到
回复 支持 反对

使用道具 举报

senghu  初级技师

发表于 2018-3-18 16:09:02

样例代码最后publish("Hy6z0Pb1G",(String)temperature); ; //向Hy6z0Pb1G设备发送温度数据部分,应该标明是topic,也要根据自己实际修改的,省得小白们调试不成功
截图201803181607038657.png
回复 支持 反对

使用道具 举报

422234  高级技师
 楼主|

发表于 2018-3-18 19:41:32

1973742214 发表于 2018-3-18 10:20
投入到真正的浇花元件中再录视屏就更好了,期望房主水泵快速找到

找到了我重新录一下
回复 支持 反对

使用道具 举报

422234  高级技师
 楼主|

发表于 2018-3-18 19:56:19

senghu 发表于 2018-3-18 16:09
样例代码最后publish("Hy6z0Pb1G",(String)temperature); ; //向Hy6z0Pb1G设备发送温度数据部分,应该标明 ...

诶嘿?我代码里设置是我自己的值啊
回复 支持 反对

使用道具 举报

senghu  初级技师

发表于 2018-3-26 19:47:33

422234 发表于 2018-3-18 19:56
诶嘿?我代码里设置是我自己的值啊

由此证明不是小白^!^
回复 支持 反对

使用道具 举报

yanqi  见习技师

发表于 2019-3-4 21:02:05

麻烦解释下获取数据部分的程序。
回复 支持 反对

使用道具 举报

laai  见习技师

发表于 2019-4-26 16:28:47

改好名直接传程序,3号口用个LED代替,在IOT上发WATER,LED能亮5秒并灭。但程序没看懂。
问题1:程序和接线图是对不上的吗?
问题2:看程序这里2号是接温湿度,3号是继电器,4号是干嘛用没理解。
#define PIN_AO 2  
#define PIN_DO 4  
#define PIN_Relay 3
@422234
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
wifi气象站

硬件清单

btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2019 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail