ARDUINO MEGA2560 經過ESP8266 WIFI模塊上傳溫濕度數據到 OneNet 服務器


簡述

原來寫了一個C++的wifi庫但是發現用c++ arduino這小身板有點扛不住,代碼比較大,使用String類型數據處理速度慢,而且很容易無緣無故跑飛。而且封裝成庫后使用還需要修改arduino的串口緩存大小才能使用。
今天抽空重新用c寫了一下代碼,運行速度明顯加快,也不需要修改Arduino IDE了。本代碼主要借鑒 中移物聯-周家緒 的http頭合成的庫,和 DFRobot-Strictus 對AT指令數據處理的方法,在這里感謝兩位發布的代碼。
下面把測試成功的代碼發不出來,供后來者使用。代碼有不足之處歡迎指正。

最終效果

發布鏈接: http://open.iot.10086.cn/appview/p/aa8cb26e886d5c1238237604f155e2db

硬件概述

1.主控:ARDUINO MEGA2560開發板
特點:多個串口,IO口豐富,內存比較大,使用方便

2.WIFI模塊:使用ARDUINO MEGA2560的帶ESP8266的擴展板
特點:帶有貼片的ESP8266 WIFI模塊,DHT11溫濕度傳感器,繼電器等功能,和ARDUINO MEGA2560即插即用,擴展很多IO和電源接口方便后續擴展各種傳感器。

3.溫濕度傳感器:DHT11單總線溫濕度傳感器(擴展板帶的有這個傳感器)

軟件思路

1.使用DHT11溫濕度傳感器的庫<dht11.h>,讀取溫濕度值。
2.使用定時器<TimerOne.h>庫,監控AT指令發送和獲取返回數據的時間。
3.使用OneNet提供的<HttpPacket.h>庫,合成POST請求的HTTP頭
4.使用<ArduinoJson.h>庫,合成需要的JSON數據流
5.使用ESP8266連接路由器將數據發送到OneNet服務器

用到的庫文件下載地址:

鏈接:http://pan.baidu.com/s/1miJEIFI 密碼:y8ks

傳感器和硬件的對應接口

ESP8266 ---> Serial3(TX3/RX3) 用戶發送和讀取WIFI指令
DHT11 ---> D8 單總線讀取溫濕度數據值
DEBUG接口---> Serial(D0/D1) 1.把發送給ESP8266的數據,也在DEBUG串口輸出,觀看指令運行到哪一步,2.ESP8266接收的數據,也通過DEBUG口轉發出來,觀看反饋數據是否正確。 3.錯誤跳轉,觀看錯誤發生的位置

串口反饋數據界面

源代碼(使用ARDUINO IDE 1.06版本測試)

#include <TimerOne.h>
#include <HttpPacket.h>
#include <ArduinoJson.h>
#include <dht11.h>
dht11 DHT11;
#define DHT11PIN 8 //DHT11 連接ARDUINO 8


HttpPacketHead packet;


#define DebugSerial Serial
#define ESP8266Serail Serial3

#define Success 1U
#define Failure 0U

int L = 13;	//LED指示燈引腳

unsigned long  Time_Cont = 0;		//定時器計數器

const unsigned int esp8266RxBufferLength = 600;
char esp8266RxBuffer[esp8266RxBufferLength];
unsigned int ii = 0;
char OneNetServer[] = "api.heclouds.com";		//不需要修改

const char ssid[] = "PushPull";		//修改為自己的路由器用戶名
const char password[] = "********";	//修改為自己的路由器密碼



char device_id[] = "600911";	//修改為自己的設備ID
char API_KEY[] = "R9xO5NZm6oVI4YBHvCPKEqtwYtMA";	//修改為自己的API_KEY
char sensor_id1[] = "TEMP";
char sensor_id2[] = "HUMI";



void setup() {
	pinMode(L, OUTPUT);
	digitalWrite(L, LOW);
	DebugSerial.begin(9600);
	ESP8266Serail.begin(115200);

	Timer1.initialize(1000);
	Timer1.attachInterrupt(Timer1_handler);

	initEsp8266();


	DebugSerial.println("setup end!");
}

void loop() {
	//獲取溫濕度數據
	int chk = DHT11.read(DHT11PIN);								//讀取溫濕度值

	  //串口調試DHT11輸出信息
	  DebugSerial.print("Read sensor: ");
	  switch (chk)
	  {
	  case DHTLIB_OK:
	    DebugSerial.println("OK");
	    break;
	  case DHTLIB_ERROR_CHECKSUM:
	    DebugSerial.println("Checksum error");
	    break;
	  case DHTLIB_ERROR_TIMEOUT:
	    DebugSerial.println("Time out error");
	    break;
	  default:
	    DebugSerial.println("Unknown error");
	    break;
	  }

	  //發送數據到Onenet
	  postDataToOneNet(API_KEY,device_id,sensor_id1,DHT11.temperature);
          delay(100);		
	  postDataToOneNet(API_KEY,device_id,sensor_id2,DHT11.humidity);

	  delay(5000);
}

void postDataToOneNet(char* API_VALUE_temp,char* device_id_temp,char* sensor_id_temp,double thisData)
{
		//合成POST請求
	StaticJsonBuffer<200> jsonBuffer;



	JsonObject& value = jsonBuffer.createObject();
	value["value"] = thisData;

	JsonObject& id_datapoints = jsonBuffer.createObject();
	id_datapoints["id"] = sensor_id_temp;
	JsonArray& datapoints = id_datapoints.createNestedArray("datapoints");
	datapoints.add(value);

	JsonObject& myJson = jsonBuffer.createObject();
	JsonArray& datastreams = myJson.createNestedArray("datastreams");
	datastreams.add(id_datapoints);

	char p[200];
	int num = myJson.printTo(p, sizeof(p));


	packet.setHostAddress(OneNetServer);
	packet.setDevId(device_id_temp);   //device_id
	packet.setAccessKey(API_VALUE_temp);  //API_KEY
	// packet.setDataStreamId("<datastream_id>");    //datastream_id
	// packet.setTriggerId("<trigger_id>");
	// packet.setBinIdx("<bin_index>");

	/*create the http message about add datapoint */
	packet.createCmdPacket(POST, TYPE_DATAPOINT, p);
	// if (strlen(packet.content))
	// 	Serial.print(packet.content);
	// Serial.print(p);
	int httpLength = strlen(packet.content) + num;

	

		//連接服務器
	char cmd[400];
	memset(cmd, 0, 400);	//清空cmd
	strcpy(cmd, "AT+CIPSTART=\"TCP\",\"");
	strcat(cmd, OneNetServer);
	strcat(cmd, "\",80\r\n");
	if (sendCommand(cmd, "CONNECT", 7, 10000, 5) == Success);
	else ESP8266_ERROR(1);

	//發送數據
	memset(cmd, 0, 400);	//清空cmd
	sprintf(cmd, "AT+CIPSEND=%d\r\n", httpLength);
	if (sendCommand(cmd, ">", 1, 3000, 1) == Success);
	else ESP8266_ERROR(2);

	memset(cmd, 0, 400);	//清空cmd
	strcpy(cmd, packet.content);
	strcat(cmd, p);
	if (sendCommand(cmd, "\"succ\"}", 7, 3000, 3) == Success);
	else ESP8266_ERROR(3);

	if (sendCommand("AT+CIPCLOSE\r\n", "CLOSED", 6, 3000, 1) == Success);
	else ESP8266_ERROR(4);
}

void initEsp8266()
{
	if (sendCommand("AT\r\n", "OK", 2, 3000, 10) == Success);
	else ESP8266_ERROR(5);

	if (sendCommand("AT+RST\r\n", "ready", 5, 10000, 10) == Success);
	else ESP8266_ERROR(6);

	if (sendCommand("AT+CWMODE=1\r\n", "OK", 2, 3000, 10) == Success);
	else ESP8266_ERROR(7);

	char cmd[50];
	strcpy(cmd, "AT+CWJAP=\"");
	strcat(cmd, ssid);
	strcat(cmd, "\",\"");
	strcat(cmd, password);
	strcat(cmd, "\"\r\n");

	if (sendCommand(cmd, "OK", 2, 20000, 10) == Success);
	else ESP8266_ERROR(8);

	if (sendCommand("AT+CIPMUX=0\r\n", "OK", 2, 3000, 10) == Success);
	else ESP8266_ERROR(9);

	if (sendCommand("AT+CIFSR\r\n", "OK", 2, 20000, 10) == Success);
	else ESP8266_ERROR(10);
}

void(* resetFunc) (void) = 0; //制造重啟命令 

void ESP8266_ERROR(int num)
{
	DebugSerial.print("ERROR");
	DebugSerial.println(num);
	while (1)
	{
		digitalWrite(L, HIGH);
		delay(300);
		digitalWrite(L, LOW);
		delay(300);

		if (sendCommand("AT\r\n", "OK", 2, 100, 10) == Success)
		{
			DebugSerial.print("\r\nRESET!!!!!!\r\n");
			resetFunc();
		}
	}
}



unsigned int sendCommand(char *Command, char *Response, unsigned int Res_Length, unsigned long Timeout, unsigned char Retry)
{
	clrEsp8266RxBuffer();
	for (unsigned char n = 0; n < Retry; n++)
	{
		DebugSerial.print("\r\nsend AT Command:\r\n----------\r\n");
		DebugSerial.write(Command);

		ESP8266Serail.write(Command);

		Time_Cont = 0;
		while (Time_Cont < Timeout)
		{
			esp8266ReadBuffer();
			if ((mystrstr(esp8266RxBuffer, Response, ii, Res_Length)) != NULL)
			{
				DebugSerial.print("\r\nreceive AT Command:\r\n==========\r\n");
				DebugSerial.print(esp8266RxBuffer);	//輸出接收到的信息
				clrEsp8266RxBuffer();
				return Success;
			}
		}
		Time_Cont = 0;
	}
	DebugSerial.print("\r\nreceive AT Command:\r\n==========\r\n");
	DebugSerial.print(esp8266RxBuffer);//輸出接收到的信息
	clrEsp8266RxBuffer();
	return Failure;
}

unsigned char mystrstr(char *s, char *t, unsigned int Length_s, unsigned int Length_t)
{	char x = 0; char *p; p = t;
	int i = 0, j = 0;
	for (; i < Length_s; s++, i++)
	{
		while (*t == *s)
		{	s++; t++; i++; j++;
			if (j >= Length_t) return 1;
		}
		s -= j;
		t = p; j = 0;
	}
	return NULL;
}


void Timer1_handler(void)
{
	Time_Cont++;
}



void esp8266ReadBuffer() {
	while (ESP8266Serail.available())
	{
		esp8266RxBuffer[ii++] = ESP8266Serail.read();
		if (ii == esp8266RxBufferLength)clrEsp8266RxBuffer();
	}
}

void clrEsp8266RxBuffer(void)
{
	memset(esp8266RxBuffer, 0, esp8266RxBufferLength);		//清空
	ii = 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM