首页 > 解决方案 > 将 ESP8266 (NodeMCU) 与 Android 应用程序(MIT APP 发明者)连接,尤其是来自 gps 模块的经度和纬度

问题描述

这是我的串行 Arduino 中的经纬度值。

在此处输入图像描述] 1

这是我在 Mit App 发明者中的示例设计 在此处输入图像描述

这是我在 Mit 应用程序中的设计块 在此处输入图像描述

全球定位系统代码:

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

static const int RXPin = 3, TXPin = 4;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

void setup(){
  Serial.begin(9600);
  ss.begin(GPSBaud);
}

void loop(){
  // This sketch displays information every time a new sentence is correctly encoded.
  while (ss.available() > 0){
    gps.encode(ss.read());
    if (gps.location.isUpdated()){
      Serial.print("Latitude= "); 
      Serial.print(gps.location.lat(), 6);
      Serial.print(" Longitude= "); 
      Serial.println(gps.location.lng(), 6);
    }
  }
}

Nodemcu Esp8266

#include <ESP8266WiFi.h>
#include <WiFiClient.h> 
#include <ESP8266WebServer.h>

const char* host = "GPS_NodeMCU";
const char* ssid = "GPS_BOT";

ESP8266WebServer server(80);

void setup() {
  Serial.begin(115200);


// Connecting WiFi

  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid);
// Starting WEB-server

     server.on ( "/", HTTP_handleRoot );
     server.onNotFound ( HTTP_handleRoot );
     server.begin();    

}

void loop() {
  server.handleClient();
   delay(50);
}

void HTTP_handleRoot(void) {

if( server.hasArg("State") ){
       Serial.println(server.arg("State"));
  }
  server.send ( 200, "text/html", "" );
}

如何使用 Arduino 将我的序列中的纬度和经度值发送到我在 Mit App 中创建的 android 应用程序中的 Map。该连接使用的是 nodemcu esp8266。

有可能吗?抱歉,我只是 Arduino 的初学者 :) :)

标签: arduinogpsarduino-unoarduino-esp8266app-inventor

解决方案


有很多方法可以实现这一点,但粗略地说有几个问题需要解决:

  1. 读取 GPS 数据并使其远程访问
  2. 在 MIT 应用程序中获取数据
  3. (奖金 - 评论中的部分问题)查找坐标的地址并显示在地图中

下面的示例实现了一个最小解决方案,并假设 MIT 应用程序可以访问同一网络上的 ESP8266。

读取 GPS 数据并使其远程访问

ESP8266 可以循环读取 GPS 数据,并通过ESP8266WebServer. 在这里,我们实现了一个 REST 端点,该端点将位置作为 JSON 有效负载返回。因此,当客户端在http://esp8266-ip-address/location.

您可以使用以下方法进行测试:

curl -XGET http://esp8266-ip-address/location

结合 GPS 和 web 服务器代码的关键是结合代码loop()并确保它是非阻塞的。这允许两个函数完成它们的任务。例如

void loop() {
  server.handleClient();
  handleGpsData();
}

void handleGpsData() {
  while (ss.available() > 0) {
    gps.encode(ss.read());
    printGpsLocation();
  }
}

完整的 Arduino 代码示例是:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ArduinoJson.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

ESP8266WebServer server(80);

struct GpsLocation {
  float latitude;
  float longitude;
};

StaticJsonDocument<200> GpsLocationJson;

static const int RXPin = 3, TXPin = 4;
static const uint32_t GPSBaud = 9600;

TinyGPSPlus gps;

SoftwareSerial ss(RXPin, TXPin);

const char* SSID = "GPS_NodeMCU";
const char* PASSWORD = "GPS_BOT";

void setup() {
  Serial.begin(115200);
  ss.begin(GPSBaud);

  Serial.print("Connecting to ");
  Serial.println(SSID);
  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.print("Connected. IP address: ");
  IPAddress ipAddress = WiFi.localIP();

  Serial.println(ipAddress);

  server.on("/location", handleLocation);
  server.begin();
}

void loop() {
  server.handleClient();
  handleGpsData();
}

void handleGpsData() {
  while (ss.available() > 0) {
    gps.encode(ss.read());
    printGpsLocation();
  }
}

void printGpsLocation() {
  if (gps.location.isUpdated()) {
    Serial.print("Latitude =");
    Serial.print(gps.location.lat(), 6);
    Serial.print(" Longitude = ");
    Serial.println(gps.location.lng(), 6); 
  }
}

void handleLocation()
{
  auto requestMethod = server.method();
  if (requestMethod == HTTP_GET)
  {
    sendLocation();
  }
}

void sendLocation() {
  if (isGpsDataValid()) {
    auto location = getGpsLocation();
    GpsLocationJson["latitude"] = location.latitude;
    GpsLocationJson["longitude"] = location.longitude;

    String jsonString;
    serializeJson(GpsLocationJson, jsonString);

    server.send(200, "application/json", jsonString);
  } else {
    Serial.println("404: No GPS co-ordinates");
    server.send(404);
  }
}

bool isGpsDataValid() {
  return gps.location.isValid();
}

struct GpsLocation
getGpsLocation() {
  struct GpsLocation gpsLocation = {
    gps.location.lat(),
    gps.location.lng()
  };

  return gpsLocation;
}

在 MIT 应用程序中获取数据

MIT App Inventor 有一个Web 连接组件,可以查询在上一步中创建的 REST 端点。

例如,使用以下组件创建一个屏幕:

  • 文本框
  • 按钮
  • 地图
  • 地图标记
  • 网络连接

文本框允许您输入 ESP8266 的 IP 地址。

按下按钮从 ESP8266 检索位置,平移地图位置并移动地图标记。

请参阅下面的屏幕截图。示例应用程序已发布到http://ai2.appinventor.mit.edu/?galleryId=5471748170055680

屏幕组件:

在此处输入图像描述

初始化坐标并创建一些辅助程序来操作坐标和移动标记:

在此处输入图像描述

处理按钮点击和来自 ESP8266 的响应:

在此处输入图像描述

查找坐标地址并在地图中显示

这部分是在评论中作为问题提出的。

有许多服务可以对坐标进行反向地理编码。一个例子是Open Street Map Nominatim API

这提供了一个简单的 GET 端点,可以像这样使用:

https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=-34.44076&lon=144

响应中的display_name属性具有格式化的地址。

这可以通过向 MIT 应用程序发明者屏幕添加第二个 Web 连接组件来使用。此组件ReverseGeocode在此示例中命名。

然后创建一个函数从 API 获取地址:

在此处输入图像描述

并处理来自 API 的响应:

在此处输入图像描述

最后,修改处理来自 ESP8266 的响应的代码以调用新函数:

在此处输入图像描述

此步骤的示例代码可在http://ai2.appinventor.mit.edu/?galleryId=5471748170055680#5320688868655104获得

应用截图:

在此处输入图像描述


推荐阅读