TCS34725 stopped after 2 months

283 Views Asked by At

Currently i'm working on a project where i need to monitor some sensor. One of the sensor I'm using is TCS34725 RGBC light sensor. Using Blynk, i log the data to a database and display it on a browser dashboard and Blynk app. After let it run of 2 month (approx.) it stopped to read the value.

////---------- 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    
  }  

}

This code works for 2 month. Other than TCS34725, I have SHT31-D, 7805 5V regulator, and a 3030 5V fan in a circuit connected to WeMos D1 mini. The only accident ever happen is the box (where i put all the circuit) fell 10 - 20 cm and still working for few weeks.

The only value I can get is when I reset my Wemos D1 mini and It will send 1 reading before sending 0s.

1

There are 1 best solutions below

1
On

Your timer has probably overflown and started from zero. In the source of BlynkTimer you can see that this timer value is an unsigned long. You can easily find out what is the size of an unsigned long by looking at the doc, but even easier is by doing this in your arduino code:

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

I didn't test on an arduino but it should be a size of 4 bytes. Unsigned means the variable can only take on positive values. With 4 bytes there are 4 * 8 = 32 bits, so the timer variable can take on 2^32 different values, that is a maximum of 2^32 - 1 = 4294967295. BlynkTimer is measured in milliseconds. So converting 4294967295 back this gives:

4294967295 milliseconds = 4294967 seconds = 1193 hours ~= 50 days

This is 10 days short of two months, so this could very well be causing the behavior you're describing. I'm not going into this library right now, but I will tell you this: weird behavior caused by timer variables can often be circumvented. Instead of looking wether a timer variable is bigger than a certain value, you check wether the difference with that value is bigger than zero. Allow me to demonstrate:

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

Say that the value of timer is equal to 4294967290, which is close to its max value of 4294967295. Now we're trying to check wether timer is bigger than 4294967292 but at the time of comparison, timer has reached its max value and started back from 0. So in the first case described above you're checking 0 > 4294967292. This yields false, while in fact you would have wanted it to yield true. In the second case you're doing the following: 0 - 4294967292 > 0, the result of this calculation yields 2 > 0, which is obviously true, as desired.

With this information you can manually try to fix the library. Another, somewhat more dirty, workaround would be to just have the esp8266 reboot itself after 49 days.

Another little hack would be to declare timer as an **unsigned long long*. Notice that the word long is in there twice, so this gives you 64 bits of precision, meaning the timer would runout in (2^64 - 1) / 1000 / 3600 / 24 = 213503982335 days. However, the millis() function in Arduino yields a 32 bit value, so in most cases this won't help you a lot I'm afraid. Unless you do something like this when increasing your 64 bit value:

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;
}