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

Connecting ESP8266 (NodeMCU) with Android app (MIT APP inventor) especially the longitude and latitude from a gps module

这是我串口Arduino中的经纬度值

]1

这是我在 Mit App Inventor 中的示例设计

这是我在 Mit 应用程序中设计的块

GPS 代码:

#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 应用程序中的地图。连接使用的是 nodemcu esp8266。

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

对宽泛的问题给出狭义的回答
您应该使用其中一个教程来学习 communication/protocols 的基础知识:See here
and then dig into this

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

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

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

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

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

上执行 HTTP GET 时,此位置可用

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

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

结合GPS和网络服务器代码的关键是结合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 Connectivity component 可以查询在上一步中创建的 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 应用程序发明者屏幕添加第二个网络连接组件来使用。该组件在此示例中命名为 ReverseGeocode

然后创建一个函数从API:

获取地址

并处理来自 API 的响应:

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

此步骤的示例代码位于 http://ai2.appinventor.mit.edu/?galleryId=5471748170055680#5320688868655104

应用截图: