使用 wifiManager 通过 Arduino Uno r3 和 ESP8266-01 将传感器信息发送到 ThingSpeak
Sending sensor info to ThingSpeak through Arduino Uno r3 and ESP8266-01 using wifiManager
我有一个项目,其中有一个水位传感器连接到我的 Arduino Uno r3。我有一个 ESP8266-01 模块连接到我的 Arduino。使用 AT 命令,我能够将传感器结果上传到 ThinkSpeak。但是我希望能够登录到其他 wifi 频道,所以我在我的 ESP8266 上设置了 wifiManager.h、ESP8266WiFi.h、DNSServer.h 和 ESP8266WebServer.h,一切正常。由于它无法连接,因为没有 IP 和密码,它在 AP 模式下打开,我从我的电脑连接到它并登录。我输入了我的 IP 地址和密码并点击保存,ESP 被回收并连接。我现在正在尝试将传感器数据上传到 thingSpeak,但我认为 AT 命令不再起作用,因为我收到错误消息 espData 未在此范围内声明。这是我的代码。
//这是我放在 ESP8266 上的新代码,并使用 GPIO 2 将信息从传感器上传到 thinkSpeak
如您所见,我使用 wifiManager 连接到 wifi,然后通过 GPIO 2 端口读取由 Arduino 供电的传感器。
#include <FS.h>
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h>
//NEW STUFF START
char apiKey[20]="";
WiFiClient client;
char defaultHost[100] = "api.thingspeak.com"; //Thing Speak IP address (sometime the web address causes issues with ESP's :/
long itt = 500;
long itt2 = 500;
const byte wifiResetPin = 13;
int interruptPinDebounce = 0;
long debouncing_time = 1000;
volatile unsigned long wifiResetLastMillis = 0;
bool shouldSaveConfig = false;
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;}
void handleWifiReset(){
if(millis()<wifiResetLastMillis){
wifiResetLastMillis = millis();
}
if((millis() - wifiResetLastMillis)>= debouncing_time){
Serial.println("Clearing WiFi data resetting");
WiFiManager wifiManager;
wifiManager.resetSettings();
SPIFFS.format();
ESP.reset();
delay(1000);
}
wifiResetLastMillis = millis();
}
void setup() {
WiFiManager wifiManager;
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(wifiResetPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(wifiResetPin), handleWifiReset,FALLING);
//NEW STUFF START
//clean FS, for testing
//SPIFFS.format();
//read configuration from FS json
Serial.println("mounting FS...");
if (SPIFFS.begin()) {
Serial.println("mounted file system");
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
Serial.println("reading config file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("opened config file");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
json.printTo(Serial);
if (json.success()) {
Serial.println("\nparsed json");
strcpy(defaultHost, json["defaultHost"]);
strcpy(apiKey, json["apiKey"]);
} else {
Serial.println("failed to load json config");
}
}
}
} else {
Serial.println("failed to mount FS");
}
WiFiManagerParameter customHostServer("defaultHost", "Host Server", defaultHost, 100);
WiFiManagerParameter customAPIKey("apiKey", "ThingSpeakWriteAPI", apiKey, 20);
//END NEW STUFF
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
//WiFiManager wifiManager;
//NEW STUFF START
wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.addParameter(&customHostServer);
wifiManager.addParameter(&customAPIKey);
//END NEW STUFF
//reset saved settings
//wifiManager.resetSettings();
//set custom ip for portal
//wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//fetches ssid and pass from eeprom and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
wifiManager.autoConnect("AutoConnectAP");
Serial.println("Connected");
//NEW STUFF START
strcpy(defaultHost, customHostServer.getValue());
strcpy(apiKey, customAPIKey.getValue());
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["defaultHost"] = defaultHost;
json["apiKey"] = apiKey;
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
json.printTo(Serial);
json.printTo(configFile);
configFile.close();
//end save
}
Serial.println("local ip");
Serial.println(WiFi.localIP());
//END NEW STUFF
//or use this for auto generated name ESP + ChipID
//wifiManager.autoConnect();
pinMode(2,INPUT);
pinMode(1,INPUT);
Serial.println("WriteApi");
Serial.println(apiKey);
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
//save the custom parameters to FS
strcpy(defaultHost,customHostServer.getValue());
strcpy(apiKey,customAPIKey.getValue());
}
//callback notifying us of the need to save config
void loop() {
delay(5000);
String apiKey2 = apiKey;
char defaultHost[100] = "api.thingspeak.com";
pinMode(2,INPUT);
pinMode(1,INPUT);
const int waterInPin = 2; // Analog input pin that the potentiometer is attached to
const int BatteryInPin = 1; // Analog input pin that the potentiometer is attached to
int waterSensorInValue;//reading our water lever sensor
int waterSensorOutValue;//conversion of water sensor value
int BatterySensorInValue;//reading our water lever sensor
int BatterySensorOutValue;//conversion of water sensor value
// put your main code here, to run repeatedly:
waterSensorInValue = analogRead(waterInPin);
BatterySensorInValue = analogRead(BatteryInPin);
waterSensorOutValue = map(waterSensorInValue,0,1024,0,225);
BatterySensorOutValue = map(BatterySensorInValue,0,1024,0,225);
Serial.println("WaterOutValue = ");
Serial.println(waterSensorOutValue );
Serial.println("WaterInValue = ");
Serial.println(waterSensorInValue );
Serial.println("BatteryOutValue = ");
Serial.println(BatterySensorOutValue );
Serial.println("BatteryInValue = ");
Serial.println(BatterySensorInValue);
delay(18000);
itt = waterSensorInValue;
itt2 = BatterySensorInValue;
if (client.connect(defaultHost,80))
{ // "184.106.153.149" or api.thingspeak.com
itt++; //Replace with a sensor reading or something useful
String postStr = apiKey;
postStr +="&field1=";
postStr += String(itt);
postStr +="&field2=";
postStr += String(itt2);
postStr += "\r\n\r\n\r\n";
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: "+String (apiKey)+"\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(postStr.length());
client.print("\n\n\n");
client.print(postStr);
Serial.println("% send to Thingspeak");
}
client.stop();
Serial.println("Waiting…");
delay(20000);
}
我会将与传感器或互联网无关的其他代码放在 Arduino 板上
但是,只要在上传代码后直接连接到串口和 运行 ,上面的代码就可以正常工作。如果我从计算机上的串行端口拔下 Arduino,然后重新插入,什么也不会发生。我认为它应该继续 运行 上面的代码连接到互联网,读取传感器并将信息发送到 thingSpeak 但它没有。知道为什么会这样。
我用新代码替换了旧代码,据说可以将我的 thingSpeak 写入 api 保存到 SPIFFS。如果我擦除设置然后上传闪存大小设置为 512k (128k SPIFFS) FS 安装和默认主机和 Api 写入密钥保存到 SPIFF 然后 ESP8266 重新启动连接到互联网并转到 thingSpeak 和更新传感器读数。问题仍然是我想关闭 ESP8266 以节省能源,但是当我重新启动它时,只有 (void) 循环运行,所以即使认为它连接到 wifi,甚至可能连接到 thingSpeak,它也不会更新传感器输入。如何获取信息 api 从 SPIFFS 将密钥写入草图的 (void) 循环部分,以便它在关闭后将传感器数据发送到 thingSpeak。或者我没有连接到 ThingSpeak。无论如何,这是一个不同的问题,所以我会重新发布一个更具体的问题并将其标记为已回答。
这回答了我关于使用 ESP8266 和 Arduino uno 连接到不同的 wifi 和密码以及添加自定义参数的过程中的很多问题。我仍然有一些问题,但会在单独的 post 中询问,希望有人能帮助我。
我有一个项目,其中有一个水位传感器连接到我的 Arduino Uno r3。我有一个 ESP8266-01 模块连接到我的 Arduino。使用 AT 命令,我能够将传感器结果上传到 ThinkSpeak。但是我希望能够登录到其他 wifi 频道,所以我在我的 ESP8266 上设置了 wifiManager.h、ESP8266WiFi.h、DNSServer.h 和 ESP8266WebServer.h,一切正常。由于它无法连接,因为没有 IP 和密码,它在 AP 模式下打开,我从我的电脑连接到它并登录。我输入了我的 IP 地址和密码并点击保存,ESP 被回收并连接。我现在正在尝试将传感器数据上传到 thingSpeak,但我认为 AT 命令不再起作用,因为我收到错误消息 espData 未在此范围内声明。这是我的代码。
//这是我放在 ESP8266 上的新代码,并使用 GPIO 2 将信息从传感器上传到 thinkSpeak 如您所见,我使用 wifiManager 连接到 wifi,然后通过 GPIO 2 端口读取由 Arduino 供电的传感器。
#include <FS.h>
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager
#include <ArduinoJson.h>
//NEW STUFF START
char apiKey[20]="";
WiFiClient client;
char defaultHost[100] = "api.thingspeak.com"; //Thing Speak IP address (sometime the web address causes issues with ESP's :/
long itt = 500;
long itt2 = 500;
const byte wifiResetPin = 13;
int interruptPinDebounce = 0;
long debouncing_time = 1000;
volatile unsigned long wifiResetLastMillis = 0;
bool shouldSaveConfig = false;
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;}
void handleWifiReset(){
if(millis()<wifiResetLastMillis){
wifiResetLastMillis = millis();
}
if((millis() - wifiResetLastMillis)>= debouncing_time){
Serial.println("Clearing WiFi data resetting");
WiFiManager wifiManager;
wifiManager.resetSettings();
SPIFFS.format();
ESP.reset();
delay(1000);
}
wifiResetLastMillis = millis();
}
void setup() {
WiFiManager wifiManager;
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(wifiResetPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(wifiResetPin), handleWifiReset,FALLING);
//NEW STUFF START
//clean FS, for testing
//SPIFFS.format();
//read configuration from FS json
Serial.println("mounting FS...");
if (SPIFFS.begin()) {
Serial.println("mounted file system");
if (SPIFFS.exists("/config.json")) {
//file exists, reading and loading
Serial.println("reading config file");
File configFile = SPIFFS.open("/config.json", "r");
if (configFile) {
Serial.println("opened config file");
size_t size = configFile.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.parseObject(buf.get());
json.printTo(Serial);
if (json.success()) {
Serial.println("\nparsed json");
strcpy(defaultHost, json["defaultHost"]);
strcpy(apiKey, json["apiKey"]);
} else {
Serial.println("failed to load json config");
}
}
}
} else {
Serial.println("failed to mount FS");
}
WiFiManagerParameter customHostServer("defaultHost", "Host Server", defaultHost, 100);
WiFiManagerParameter customAPIKey("apiKey", "ThingSpeakWriteAPI", apiKey, 20);
//END NEW STUFF
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
//WiFiManager wifiManager;
//NEW STUFF START
wifiManager.setSaveConfigCallback(saveConfigCallback);
wifiManager.addParameter(&customHostServer);
wifiManager.addParameter(&customAPIKey);
//END NEW STUFF
//reset saved settings
//wifiManager.resetSettings();
//set custom ip for portal
//wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
//fetches ssid and pass from eeprom and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
wifiManager.autoConnect("AutoConnectAP");
Serial.println("Connected");
//NEW STUFF START
strcpy(defaultHost, customHostServer.getValue());
strcpy(apiKey, customAPIKey.getValue());
if (shouldSaveConfig) {
Serial.println("saving config");
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["defaultHost"] = defaultHost;
json["apiKey"] = apiKey;
File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) {
Serial.println("failed to open config file for writing");
}
json.printTo(Serial);
json.printTo(configFile);
configFile.close();
//end save
}
Serial.println("local ip");
Serial.println(WiFi.localIP());
//END NEW STUFF
//or use this for auto generated name ESP + ChipID
//wifiManager.autoConnect();
pinMode(2,INPUT);
pinMode(1,INPUT);
Serial.println("WriteApi");
Serial.println(apiKey);
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
//save the custom parameters to FS
strcpy(defaultHost,customHostServer.getValue());
strcpy(apiKey,customAPIKey.getValue());
}
//callback notifying us of the need to save config
void loop() {
delay(5000);
String apiKey2 = apiKey;
char defaultHost[100] = "api.thingspeak.com";
pinMode(2,INPUT);
pinMode(1,INPUT);
const int waterInPin = 2; // Analog input pin that the potentiometer is attached to
const int BatteryInPin = 1; // Analog input pin that the potentiometer is attached to
int waterSensorInValue;//reading our water lever sensor
int waterSensorOutValue;//conversion of water sensor value
int BatterySensorInValue;//reading our water lever sensor
int BatterySensorOutValue;//conversion of water sensor value
// put your main code here, to run repeatedly:
waterSensorInValue = analogRead(waterInPin);
BatterySensorInValue = analogRead(BatteryInPin);
waterSensorOutValue = map(waterSensorInValue,0,1024,0,225);
BatterySensorOutValue = map(BatterySensorInValue,0,1024,0,225);
Serial.println("WaterOutValue = ");
Serial.println(waterSensorOutValue );
Serial.println("WaterInValue = ");
Serial.println(waterSensorInValue );
Serial.println("BatteryOutValue = ");
Serial.println(BatterySensorOutValue );
Serial.println("BatteryInValue = ");
Serial.println(BatterySensorInValue);
delay(18000);
itt = waterSensorInValue;
itt2 = BatterySensorInValue;
if (client.connect(defaultHost,80))
{ // "184.106.153.149" or api.thingspeak.com
itt++; //Replace with a sensor reading or something useful
String postStr = apiKey;
postStr +="&field1=";
postStr += String(itt);
postStr +="&field2=";
postStr += String(itt2);
postStr += "\r\n\r\n\r\n";
client.print("POST /update HTTP/1.1\n");
client.print("Host: api.thingspeak.com\n");
client.print("Connection: close\n");
client.print("X-THINGSPEAKAPIKEY: "+String (apiKey)+"\n");
client.print("Content-Type: application/x-www-form-urlencoded\n");
client.print("Content-Length: ");
client.print(postStr.length());
client.print("\n\n\n");
client.print(postStr);
Serial.println("% send to Thingspeak");
}
client.stop();
Serial.println("Waiting…");
delay(20000);
}
我会将与传感器或互联网无关的其他代码放在 Arduino 板上 但是,只要在上传代码后直接连接到串口和 运行 ,上面的代码就可以正常工作。如果我从计算机上的串行端口拔下 Arduino,然后重新插入,什么也不会发生。我认为它应该继续 运行 上面的代码连接到互联网,读取传感器并将信息发送到 thingSpeak 但它没有。知道为什么会这样。
我用新代码替换了旧代码,据说可以将我的 thingSpeak 写入 api 保存到 SPIFFS。如果我擦除设置然后上传闪存大小设置为 512k (128k SPIFFS) FS 安装和默认主机和 Api 写入密钥保存到 SPIFF 然后 ESP8266 重新启动连接到互联网并转到 thingSpeak 和更新传感器读数。问题仍然是我想关闭 ESP8266 以节省能源,但是当我重新启动它时,只有 (void) 循环运行,所以即使认为它连接到 wifi,甚至可能连接到 thingSpeak,它也不会更新传感器输入。如何获取信息 api 从 SPIFFS 将密钥写入草图的 (void) 循环部分,以便它在关闭后将传感器数据发送到 thingSpeak。或者我没有连接到 ThingSpeak。无论如何,这是一个不同的问题,所以我会重新发布一个更具体的问题并将其标记为已回答。
这回答了我关于使用 ESP8266 和 Arduino uno 连接到不同的 wifi 和密码以及添加自定义参数的过程中的很多问题。我仍然有一些问题,但会在单独的 post 中询问,希望有人能帮助我。