使用Arduino开发板和ESP8266从互联网读取数据

ESP8266-01是一款很强大的模块,可以满足我们任何IOT项目的需求。自发布以来,它已经形成了一个很强大的群体,并演变成一个易于使用、价格低廉且功能强大的Wi-Fi模块。另一个更受欢迎的开源平台是Arduino开发板,围绕该平台,已经建立起大量的项目。将这两个平台相结合将为许多创新项目打开大门,因此在本教程中,我们将学习如何将ESP8266-01模块与Arduino进行连接。这样就可以在Arduino开发板和互联网之间发送或接收数据。

为了实现目标,我们将使用ESP8266-01通过一个API接口从互联网中读取时间、日期、温度和湿度。然后将这些值发送到Arduino板,并将它们显示在LCD显示屏1602上。听起来是不是很酷!那么让我们开始吧。

所需的材料

●    Arduino开发板

●    ESP8266-01模块

●    带有3.3V选项的FTDI编程电路板

●    液晶显示屏1602

●    电位器

●    按钮

●    连接导线

●    面包板

如何工作的?

在我们深入研究之前,了解这件事情的实际情况非常重要。我们需要从ESP8266-01模块的基础开始。使用Arduino IDE对ESP8266编程,并将编写代码以使用API​​通过http请求读取JSON文件。然后将解析这个JSON文件,从完整的JSON文件中只提取所需的信息。

一旦信息解析完成,我们将使用串行通信将其打印出来。这些串口线连接到Arduino,以便Arduino可以读取ESP8266发送的信息。一旦信息被读取和处理,我们将在LCD液晶屏上进行显示。

如果你还没有完全理解,没关系,我们将在本文的其余部分进行介绍。

编程ESP8266-01

本教程假定您有一些ESP8266模块的使用经验。如果没有的话,建议阅读以下三个教程以更好地理解。

●    开始使用ESP8266-01

●    使用AT命令编程ESP8266-01

●    使用Arduino IDE编程ESP8266-01并进行烧写程序

在这里,我们将使用Arduino IDE编程ESP8266-01模块。硬件方面,我们使用3.3V的FTDI板编程ESP8266,因为它可以使硬件变得非常简单。下图显示了将ESP8266与FTDI板连接的电路图。

确保满足以下条件

1.  ESP8266-01模块只支持3.3V,不要使用5V。所以只能在3.3V模式下设置FTDI。

2.  编程模式下,GPIO_0必须接地

3.  复位引脚应通过按钮连接到接地引脚。上传代码之前应该按下该按钮。每次按下该按钮时,ESP8266-01模块上的蓝色LED指示灯将变为高电平,表示模块已复位。

连接完成后,打开Arduino IDE并检查是否可以成功上传示例程序。如果您不确定如何使用Arduino IDE将程序上传至ESP8266,请阅读Arduino编程ESP8266进行学习。

现在让我们进入实际的程序,我们将从互联网获取数据并将其发送给Arduino。完整的程序在本文末尾处给出,我将其分开对其进行解释。该程序编译时还需要Arduino JSON库,所以如果您尚未将该库添加到Arduino IDE中,则可以通过从Github的Arduino JSON库下载并进行添加。

ESP8266必须连接互联网才能获得有关日期、时间、温度和湿度的数据。所以你在下面的代码中必须提供SSID和密码,允许它来连接到你的Wi-Fi。

const char* ssid = "JIO-Fi"; //Enter your Wi-Fi SSID
const char* password = "Pas123"; //Enter you Wi-Fi Password

setup()函数中,我们检查ESP是否能够连接到Wi-Fi,如果没有,只需在串行监视器上打印“Connecting ..”,它将一直等待。

while (WiFi.status() != WL_CONNECTED) { //Wait till Wi-Fi is connected
    delay(1000);
    Serial.print("Connecting.."); //Print Connecting.. till connection is established
  }


下一步是非常重要的一步。如果Wi-Fi连接成功,我们必须调用http get请求从互联网读取JSON文件。在本教程中,我使用wunderground.com提供的API。因此,如果您打算使用相同的API,则可以进入链接并注册免费API密钥或使用您选择的任何API。一旦你完成了你的API,你将最终得到一个如下所示的链接

http://api.wunderground.com/api/abcd124578qwert/conditions/q/IN/Chennai.json

注意:我已更改此链接的API密钥,因此这不会起作用。请注意保持您的API密钥安全,不要共享。

我的API用于获取Chennai的天气数据。您可以使用任何API。但是当你在任何浏览器中加载API时,它应该返回一个JSON文件。例如我的API返回以下JSON文件


您可能会返回具有不同数据的文件。我们可以通过读取它来检查ESP8266是否也收到了这个JSON文件,然后在串行监视器上使用打印JSON,代码如下:

 int httpCode = http.GET(); //pass a get request                                                                 
    if (httpCode > 0) { //Check the returning code
   //   payload = http.getString();   // Store the value on varibale Payload for debugging
   // Serial.println(payload);   //Print the payload for debugging otherwise comment both lines

我已经注释掉这些代码,因为它们仅用于测试。一旦确保ESP8266能够获取JSON数据,就需要对数据进行解析。正如你所看到的,这些数据量很大,除了我们需要的数据如日期、时间、温度和湿度外,大部分数据都是无用的。

所以我们使用JSON Arduino库来分离需要的值并将其存储在一个变量中。这种方法是可行的,因为JSON文件中的值被分配为名称值对。所以这个名字是一个字符串,它将保存我们所需的值。

要实现这一点,我们需要转到一个网站,它将分析JSON文件并给我们提供Arduino代码。是的,就像那样简单。前往https://arduinojson.org/assistant/并粘贴我们在浏览器中加载的JSON文件,然后按Enter键。完成后我看起来像下面这样

向下滚动一下,查看自动创建的解析程序

你所要做的就是选择想要的变量,将它们复制并粘贴到你的Arduino IDE上,就像我做的一样。

/*Phrasing Data using the JSON librarey */ //Use https://arduinojson.org/assistant/ to get the phrasing values for your JSON string
const size_t bufferSize = JSON_OBJECT_SIZE(0) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 2*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(8) + JSON_OBJECT_SIZE(12) + JSON_OBJECT_SIZE(56) + 2160;
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& root = jsonBuffer.parseObject(http.getString());
/*End of Phrasing Data*/

//Address the value sin to desired variables
JsonObject& current_observation = root["current_observation"]; //under current_observation
JsonObject& current_observation_observation_location = current_observation["observation_location"]; //under observation_location
const char* current_observation_station_id = current_observation["station_id"]; // "ICHENNAI1" //get the location detials
const char* current_observation_local_time_rfc822 = current_observation["local_time_rfc822"]; //Local time //get the local time
const char* current_observation_temperature_string = current_observation["temperature_string"]; // "90.7 F (32.6 C)" //get the temperature value
const char* current_observation_relative_humidity = current_observation["relative_humidity"]; // "73%" //get the humidity value

我刚刚复制了变量current_observation_station_id、current_observation_local_time_rfc822、current_observation_temperature_string和current_observation_relative_humidity。因为我们打算在液晶显示屏上只显示这四个数据。

最终,我们从互联网获得了我们需要的数据,并将其保存为一个可以轻松使用的变量。要将这些数据发送到Arduino,我们只需通过串行监视器将它们串行写入。可以使用以下代码:

//Print the variables through serial monitor
Serial.print (current_observation_station_id); //send the location details to Arduino
delay(100); //stability delay
Serial.print (current_observation_local_time_rfc822); //send the local time details to Arduino
delay(100); //stability delay
Serial.print (current_observation_temperature_string); //send the temperature details to Arduino
delay(100); //stability delay
Serial.print (current_observation_relative_humidity); //send the humidity details to Arduino
delay(100); //stability delay

请注意,我使用的是Serial.print()而不是Serial.println(),因为Serial.println()命令会将不需要的/ n和/ r追加到数据中,另外。我们还增加了10秒的延迟,以便ESP8266将这些值仅在10秒的时间间隔周期内发送给Arduino开发板。

将ESP8266-01模块连接到Arduino开发板

到目前为止,我们已经对ESP8266-01模块进行了编程,它以10秒为间隔从互联网上读取所需的数据,并将其连续发送出去。现在,我们必须将ESP8266模块连接到Arduino开发板,以便可以读取此串行数据。我们还必须向Arduino添加一个LCD显示屏1602,以便显示从ESP8266模块接收到的数据。下面显示了将ESP8266模块与Arduino连接的电路图

确保GPIO_0引脚处于空闲状态,仅使用Arduino的3.3V引脚为模块供电,然后按下按钮将ESP8266模块设置为处于工作模式。现在我们上传到ESP8266的程序应该已经开始工作,模块应该通过串行引脚将数据发送给Arduino。这些串行引脚连接到Arduino上的引脚号6和7。所以我们可以使用Arduino上的软件串行选项从引脚读取这些串行数据。

Arduino程序以及工作过程

本文末尾还提供了完整的Arduino程序以及ESP8266代码。您可以向下滚动查看该程序,如果想了解该程序,请继续阅读。

接口程序非常简单,我们只需使用软件串行库从引脚6和7读取数据并将它们显示在LCD液晶屏上。由于接收中的数据是字符串格式,因此我们必须使用substring函数将有效负载分解为我们所需,或者如果需要,将其转换为整数。因此,我们首先定义LCD所连接的引脚。

const int rs = 8, en = 9, d4 = 10, d5 = 11, d6 = 12, d7 = 13; //Pins to which LCD is connected
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

由于我们已将ESP8266的Rx和Tx引脚与Arduino的第6和第7引脚连接,所以我们必须初始化这些引脚的软件串口,以便我们可以从它们接收串行数据。我将其声明为ESP_Serial,您可以根据需要进行声明。

SoftwareSerial ESP_Serial(6,7); //Tx,Rx

setup()函数中,我们初始化串行监视器的串行通信以及软件串口。我们让ESP8266程序以9600波特率进行通信,如果你想重复采集,那么我们必须对软件串行端口使用相同的波特率。我们还在LCD上显示一小段2秒钟的介绍信息。

void setup() {
  lcd.begin(16, 2); //We are using a 16*2 LCD display
  lcd.print(" Arduino & ESP"); //Display a intro message
  Serial.begin(115200);
  ESP_Serial.begin(9600);
  delay(2000);
  lcd.clear();
}

loop()函数内部,我们需要检查ESP8266是否正在发送数据。如果正在发送,那么我们从ESP8266读取字符串并将其保存到一个称为payload的变量中。变量payload是String类型的,它将保存从ESP8266模块发送的完整信息。

while (ESP_Serial.available() > 0)
  {
    payload = ESP_Serial.readString();

现在我们必须将这个字符串分成小块,以便我们可以将它们用于我们自己的目的,在本文下,我们必须将它们分开以在LCD屏幕上显示它们。这可以通过使用Arduino中的substring函数轻松完成。你必须知道每个字符的位置才能使用这个substring函数。您可以在串行监视器上打印payload,以了解字符的位置并使用它们对子字符串进行分类,如下所示

local_date = payload.substring(14, 20);
    local_time = payload.substring(26, 31);
    temperature = payload.substring(48, 54);
    Humidity = payload.substring(55, 60);

现在我可以继续使用这些变量来将它们打印在串行监视器上,或者将它们打印在LCD上。但是,在串行监视器上打印它们会帮助我们检查子字符串是否正确分割。接下来,我们只需使用以下几行将它们打印在LCD显示屏上

  lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print(local_date);
    lcd.setCursor(8, 0);
    lcd.print(local_time);
    lcd.setCursor(1, 1);
    lcd.print(temperature);
    lcd.setCursor(10, 1);
    lcd.print(Humidity);

将程序上传到Arduino,并确保连接如上面的电路图所示。调整液晶显示器的对比度,直到您清楚地看到字符。您应该在液晶显示屏上看到介绍消息,然后几秒钟后,LCD屏幕上将显示日期、时间、温度和湿度等详细信息,如下所示。

您还可以注意到,每次数据进入时,ESP8266上的蓝色指示灯都会闪烁。如果看不到,那意味着ESP未处于工作模式,请尝试按下复位按钮并检查连接。

与此类似,您可以使用任何API从互联网上获取所需的数据,并将其提供给Arduino并处理您使用Arduino的工作。 互联网上有大量的API可供使用,并且所有这些都可以制作无数的项目。 希望你了解这个项目并且喜欢构建它。

代码

本文所使用的完整代码:

Code for ESP8266:
#include <ESP8266WiFi.h> //ESP8266 Library
#include <ESP8266HTTPClient.h> //ESP8266 Library
#include <ArduinoJson.h> //For phrasing JSON file download from https://github.com/bblanchon/ArduinoJson
 
const char* ssid = "Jio-Fi"; //Enter your Wi-Fi SSID
const char* password = "pas123"; //Enter you Wi-Fi Password

String payload; //To store the JSON object as string

void setup () {
 
  Serial.begin(9600); //initialise serial monitor to send data to Arduino
  WiFi.begin(ssid, password); //connect to the network specified above
 
  while (WiFi.status() != WL_CONNECTED) { //Wait till Wi-Fi is connected
    delay(1000);
    Serial.print("Connecting.."); //Print Connecting.. till connection is established  
  }
}
 
void loop() {
  if (WiFi.status() == WL_CONNECTED) { //If Wi-Fi connected successfully 
    HTTPClient http;  //start a HTTPClinet as http 
    //####DO NOT USE THE SAME API as below
    http.begin("http://api.wunderground.com/api/abcd123qwert456/conditions/q/IN/Chennai....");  //Enter your API 
    
    int httpCode = http.GET(); //pass a get request                                                                  
 
    if (httpCode > 0) { //Check the returning code
 
   //   payload = http.getString();   // Store the value on varibale Payload for debugging
   // Serial.println(payload);   //Print the payload for debugging otherwise comment both lines

/*Phrasing Data using the JSON librarey */ //Use https://arduinojson.org/assistant/ to get the phrasing values for your JSON string 
const size_t bufferSize = JSON_OBJECT_SIZE(0) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 2*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(8) + JSON_OBJECT_SIZE(12) + JSON_OBJECT_SIZE(56) + 2160;
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& root = jsonBuffer.parseObject(http.getString());
/*End of Phrasing Data*/

//Address the value sin to desired variables 
JsonObject& current_observation = root["current_observation"]; //under current_observation
JsonObject& current_observation_observation_location = current_observation["observation_location"]; //under observation_location
const char* current_observation_station_id = current_observation["station_id"]; // "ICHENNAI1" //get the location detials
const char* current_observation_local_time_rfc822 = current_observation["local_time_rfc822"]; //Local time //get the local time
const char* current_observation_temperature_string = current_observation["temperature_string"]; // "90.7 F (32.6 C)" //get the temperature value
const char* current_observation_relative_humidity = current_observation["relative_humidity"]; // "73%" //get the humidity value

//Print the variables thorugh serial monitor
Serial.print (current_observation_station_id); //send the location details to Arduino
delay(100); //stability delay
Serial.print (current_observation_local_time_rfc822); //send the local time details to Arduino
delay(100); //stability delay
Serial.print (current_observation_temperature_string); //send the temperature details to Arduino
delay(100); //stability delay
Serial.print (current_observation_relative_humidity); //send the humidity details to Arduino
delay(100); //stability delay

    }
 
    http.end();   //Close http connection
  }
  delay(10000);    //send values to Arduino every 30 sec.
}

 

Code for Arduino:
#include <SoftwareSerial.h>
#include <LiquidCrystal.h> //Header file for LCD from https://www.arduino.cc/en/Reference/LiquidCrystal

const int rs = 8, en = 9, d4 = 10, d5 = 11, d6 = 12, d7 = 13; //Pins to which LCD is connected
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

String local_time;
String local_date;
String temperature;
String Humidity;
String payload;

SoftwareSerial ESP_Serial(6, 7); //Tx,Rx

void setup() {
  lcd.begin(16, 2); //We are using a 16*2 LCD display
  lcd.print(" Arduino & ESP"); //Display a intro message
  Serial.begin(115200);
  ESP_Serial.begin(9600);

  delay(2000);
  lcd.clear();
}

void loop() {
  while (ESP_Serial.available() > 0)
  {
    payload = ESP_Serial.readString();

    local_date = payload.substring(14, 20);
    local_time = payload.substring(26, 31);
    temperature = payload.substring(48, 54);
    Humidity = payload.substring(55, 60);

    delay(10);
    Serial.println(payload);
    Serial.println(local_time);
    Serial.println(local_date);
    Serial.println(temperature);
    Serial.println(Humidity);

    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print(local_date);
    lcd.setCursor(8, 0);
    lcd.print(local_time);
    lcd.setCursor(1, 1);
    lcd.print(temperature);
    lcd.setCursor(10, 1);
    lcd.print(Humidity);

  }
}

类似文章

发表回复