0

目前我正在做一个需要监控一些传感器的项目。我使用的传感器之一是 TCS34725 RGBC 光传感器。使用 Blynk,我将数据记录到数据库并将其显示在浏览器仪表板和 Blynk 应用程序上。让它运行 2 个月(大约)后,它停止读取该值。

////---------- Blynk Setup
#define BLYNK_PRINT Serial // This prints to Serial Monitor

#include <ESP8266WiFi.h>  // for ESP8266
#include <BlynkSimpleEsp8266.h>  // for ESP8266
////----------

////---------- OTA Setup
#include <ESP8266mDNS.h>  // For OTA w/ ESP8266
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA
char OTAName[] = "Node1";
////----------

////---------- Projects parameter
#include <Wire.h>
#include "Adafruit_TCS34725.h"
#include "Adafruit_SHT31.h"

//#define TCS34725_INTEGRATION_TIME TCS34725_INTEGRATIONTIME_700MS
#define TCS34725_INTEGRATION_TIME TCS34725_INTEGRATIONTIME_24MS
//#define TCS34725_GAIN TCS34725_GAIN_1X
#define TCS34725_GAIN TCS34725_GAIN_60X
const float ATIME_ms = 24.0;
const float AGAINx = 60.0;
#define TCS34725_R_Coef 0.136
#define TCS34725_G_Coef 1.000
#define TCS34725_B_Coef -0.444
#define TCS34725_GA 1.0
#define TCS34725_DF 310.0

//https://www.apogeeinstruments.com/conversion-ppfd-to-lux/
#define LUX2PPFD 0.0135 //sunlight = 0.0185, Cool white CFL = 0.0135
#define PIN_PPFD V3
#define PIN_DLI V4
#define PIN_LUX V2
#define PIN_E_TEMP V0
#define PIN_E_RH V1

uint16_t r, g, b, c, LUX;
uint16_t ir;
uint16_t r_comp, g_comp, b_comp, c_comp;
float PPFD, T, H , CPL;


BlynkTimer timer;

Adafruit_SHT31 sht31 = Adafruit_SHT31();
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATION_TIME, TCS34725_GAIN);

////----------

///-----------Credentials
char auth[] =   "YourAuth";
char ssid[] = "YourSSID";
const char* pass = "YourPassword";
char server[] = "192.168.141.230";  // IP for your Local Server
int port = 8080;
////----------

void myTimerEvent()
{
  //modify this if you modify the TCS34725_INTEGRATION_TIME and TCS34725_GAIN

  tcs.getRawData(&r, &g, &b, &c);
  //LUX = tcs.calculateLux(r,g,b);
  ir = (r + g + b > c) ? (r + g + b - c) / 2 : 0;
  r_comp = r - ir;
  g_comp = g - ir;
  b_comp = b - ir;
  c_comp = c - ir;
  LUX = (TCS34725_R_Coef * float(r_comp) + TCS34725_G_Coef * float(g_comp) + TCS34725_B_Coef * float(b_comp)) / CPL;


  PPFD = LUX * LUX2PPFD;

  T = sht31.readTemperature();
  H = sht31.readHumidity();  
/*
  Serial.print("[");Serial.print(millis());Serial.print("]");
  Serial.print(F("Lux:"));Serial.print(LUX);Serial.println();;

  Serial.print("[");Serial.print(millis());Serial.print("]");
  Serial.print(F("PPFD:"));Serial.println(PPFD);

  Serial.print("[");Serial.print(millis());Serial.print("]");
  Serial.print(F("Temperature:"));Serial.print(T);Serial.print(F("C  "));Serial.print(F("Humidity:"));Serial.print(H);Serial.println(F("%"));

  Serial.println();
*/

  Blynk.virtualWrite(PIN_LUX, LUX);
  Blynk.virtualWrite(PIN_PPFD, PPFD);
  Blynk.virtualWrite(PIN_E_TEMP, T);
  Blynk.virtualWrite(PIN_E_RH, H);

}

void setup() {
  Serial.begin(9600);  // BLYNK_PRINT data

  WiFi.begin(ssid, pass); 
  Blynk.config(auth, server, port);
  Blynk.connect();

  ArduinoOTA.setHostname("Node1");  // For OTA - Use your own device identifying name
  ArduinoOTA.begin();  // For OTA


  //timer.setInterval(5 * 60 * 1000L, myTimerEvent); // every 5 minutes
  timer.setInterval(60 * 1000L, myTimerEvent); // every 1 minute
  sht31.begin(0x44);
  tcs.begin();
  CPL = (ATIME_ms * AGAINx) /(TCS34725_GA * TCS34725_DF);

  myTimerEvent();
}

void loop() {
  ArduinoOTA.handle();  // For OTA
  if(!Blynk.connected()){
    Serial.println("Blynk has been disconnected");
    Serial.print("Connecting");
    while(!Blynk.connected()){ // reconnect if Blynk is disconnected      
      Serial.print(".");    
      boolean connection = Blynk.connect();
      if(connection){
        Serial.println();
        break;
    }
  }
  }
  if(Blynk.connected()){  
    Blynk.run();
    timer.run(); // Initiates BlynkTimer
    ArduinoOTA.handle();  // For OTA    
  }  

}

此代码工作 2 个月。除了 TCS34725,我在连接到 WeMos D1 mini 的电路中还有 SHT31-D、7805 5V 稳压器和 3030 5V 风扇。唯一发生的事故是盒子(我放置所有电路的地方)下降了 10 - 20 厘米,并且仍然工作了几个星期。

我能得到的唯一值是当我重置我的 Wemos D1 mini 并且它会在发送 0 之前发送 1 个读数。

4

1 回答 1

0

您的计时器可能已溢出并从零开始。在 BlynkTimer 的源代码中,您可以看到此计时器值是无符号长整数。您可以通过查看文档轻松找出 unsigned long 的大小,但更简单的是在您的 arduino 代码中执行此操作:

unsigned long test;
Serial.println(sizeof(test));

我没有在 arduino 上进行测试,但它应该是 4 字节的大小。无符号表示变量只能取正值。4 个字节有 4 * 8 = 32 位,因此计时器变量可以采用 2^32 个不同的值,即最大值为 2^32 - 1 = 4294967295。BlynkTimer 以毫秒为单位。所以将 4294967295 转换回来,这给出了:

4294967295 毫秒 = 4294967 秒 = 1193 小时 ~= 50 天

这比两个月短了 10 天,所以这很可能导致您所描述的行为。我现在不会进入这个库,但我会告诉你:由计时器变量引起的奇怪行为通常可以被规避。不是查看计时器变量是否大于某个值,而是检查与该值的差异是否大于零。请允许我演示一下:

if(timer > SOME_THRESHOLD)       // WRONG
if(timer - SOME_THRESHOLD > 0)   // CORRECT

假设timer的值等于 429496729 0,接近其最大值 429496729 5。现在我们正在尝试检查计时器是否大于 429496729 2但在比较时,计时器已达到其最大值并从 0 开始。因此,在上述第一种情况下,您正在检查 0 > 429496729 2。这会产生false,而实际上您本来希望它产生true。在第二种情况下,您正在执行以下操作:0 - 429496729 2 > 0,此计算的结果产生 2 > 0,这显然是正确的,正如所愿。

使用此信息,您可以手动尝试修复库。另一个更脏的解决方法是让 esp8266 在 49 天后自行重启。

另一个小技巧是将计时器声明为 **unsigned long long*。请注意,long一词在那里出现了两次,因此这为您提供了 64 位的精度,这意味着计时器将在 (2^64 - 1) / 1000 / 3600 / 24 = 213503982335 天后用完。但是,Arduino 中的 millis() 函数会产生一个 32 位的值,所以在大多数情况下,恐怕这对您没有多大帮助。除非您在增加 64 位值时执行以下操作:

unsigned long long timer64 = 0;
unsigned long timer32 = millis();
unsigned long timer32_prev = timer32;

...

void incrementTimer64()
{
    timer32 = millis();
    timer64 += (unsigned long long)(timer32 - timer32_prev);
    timer32_prev = timer32;
}
于 2019-12-12T12:44:56.853 回答