Weather Station

Hello guys.

I saw a weather station on aliexpress and I thought I can make my own. :sunglasses:
Then I realized there are lots of tutorial for that. I made this one.

I have almost same hardware.
RobotDNY Mega R3 ATmega2560 and RobotDNY Nano V3 ATmega328/CH340G
2x DHT22
2x NRF24L01
DS3231 RTC
3.5" LCD ili9486

I had issue about DHT and LCD library. I changed and it's all work.
I tried inside the house. It's worked well for 2 hours maybe.

Then I put the outdoor transmitter in a box and test it again. All working
I changed receiver position it was working for a while (maybe 1 hour) then I lost outdoor signal. First I thought distance was the problem (3mt). I put back receiver old position
It work for a minute maybe then lost it again.

I saw temperature drop 20C to 4C
I didn't see below 4C also real weather almost 3-4C so
There was no rain, or snow.
I can't believe DHT22 or WiFi transmitter damaged about weather but let say it is.

I still have some issue that I can't explain.
When I waited a couple minutes outdoor signal at some point there is weird random number appear on screen


Where is that came from?
and how is that possible?

Also some times I startup system and didn't get any value indoor or outdoor.


I'm touching WiFi module then indoor value came along.

On Mega board, there is little blue led always keep blinking. When I touch WiFi module with one hand blue led flicker, when I touch with booth hand it's getting normal blinking :o

Does anyone had any idea

Here is the codes. I just changed LCD and DHT library.

Original transmitter codes;

#include "DHT.h"
#include <SPI.h>  
#include "RF24.h"

#define DHTPIN 4  
#define DHTTYPE DHT22 

RF24 myRadio (7, 8);
byte addresses[][6] = {"0"};
const int led_pin = 13;

struct package
{
  float temperature ;
  float humidity ;
};


typedef struct package Package;
Package data;

DHT dht(DHTPIN, DHTTYPE);

void setup()
{
    Serial.begin(9600);
    pinMode(led_pin, OUTPUT);
    dht.begin();
    myRadio.begin();  
    myRadio.setChannel(115); 
    myRadio.setPALevel(RF24_PA_MAX);
    myRadio.setDataRate( RF24_250KBPS ) ; 
    myRadio.openWritingPipe( addresses[0]);
    delay(1000);
}



void loop()
{
  digitalWrite(led_pin, HIGH); // Flash a light to show transmitting
  readSensor();
  Serial.println(data.humidity);
  Serial.println(data.temperature);
  myRadio.write(&data, sizeof(data)); 
  digitalWrite(led_pin, LOW);
  delay(1000);
}

void readSensor()
{
 data.humidity = dht.readHumidity();
 data.temperature = dht.readTemperature();
}

Original Receiver codes;

//If your display does not work correctly, check the User_Setup.h file that comes with the display library
//Try to use HX8357B driver to see if that works

#include <TFT_HX8357_Due.h> // https://github.com/Bodmer/TFT_HX8357_Due
#include <Sodaq_DS3231.h>  //RTC Library https://github.com/SodaqMoja/Sodaq_DS3231
#include "DHT.h"          //https://github.com/adafruit/DHT-sensor-library
#include "RF24.h"        //https://github.com/TMRh20/RF24

#define DHTPIN 8  

#define DHTTYPE DHT22 
DHT dht(DHTPIN, DHTTYPE);

RF24 myRadio (6, 7);
byte addresses[][6] = {"0"};

TFT_HX8357_Due tft = TFT_HX8357_Due();       // Invoke custom library

float remoteHumidity = 0.0;
float remoteTemperature = 0.0;

String dateString;
String hours;
int minuteNow=0;
int minutePrevious=0;

struct package
{
  float temperature ;
  float humidity ;
};

float previousIndoorHumidity = 0;
float previousIndoorTemperature = 10;

float previousRemoteHumidity = 0.1;
float previousRemoteTemperature = 0.1;

float indoorHumidity = 0;
float indoorTemperature = 0;

typedef struct package Package;
Package data;

void setup() {

  Serial.begin(9600);
  
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  delay(100);

  rtc.begin();
  dht.begin();
  delay(2000);
  //setRTCTime();

  startWirelessCommunication();
  printUI();
}

void loop() {

   checkForWirelessData();

   getAndPrintTime();
   
   printIndoorTemperature();
   printIndoorHumidity();

   printRemoteTemperature();
   printRemoteHumidity();
}

void setRTCTime()
{
  DateTime dt(2016, 6, 7, 13, 40, 30, 2); // Year, Month, Day, Hour, Minutes, Seconds, Day of Week
  rtc.setDateTime(dt); //Adjust date-time as defined 'dt' above 
}

void startWirelessCommunication()
{
  myRadio.begin(); 
  myRadio.setChannel(115); 
  myRadio.setPALevel(RF24_PA_MAX);
  myRadio.setDataRate( RF24_250KBPS ) ; 
  myRadio.openReadingPipe(1, addresses[0]);
  myRadio.startListening();
  delay(100);
}

void checkForWirelessData()
{
    if ( myRadio.available()) 
  {
    while (myRadio.available())
    {
      myRadio.read( &data, sizeof(data) );
      previousRemoteTemperature = remoteTemperature;
      previousRemoteHumidity = remoteHumidity;
      remoteTemperature = data.temperature;
      remoteHumidity = data.humidity;
    }
    Serial.print("\nPackage:");
    Serial.print("\n");
    Serial.println(data.temperature);
    Serial.println(data.humidity);
  } 
}

void printUI()
{
  
tft.drawRoundRect(5,5,470,71,5,TFT_WHITE);
tft.drawRoundRect(6,6,470,71,5,TFT_WHITE);

tft.drawRoundRect(5,90,220,225,5,TFT_WHITE);
tft.drawRoundRect(6,91,220,225,5,TFT_WHITE);

tft.drawRoundRect(250,90,220,225,5,TFT_WHITE);
tft.drawRoundRect(251,91,220,225,5,TFT_WHITE);
  
tft.fillRect(26,90,180,40,TFT_GREEN);
tft.fillRect(270,90,180,40,TFT_CYAN);

tft.setCursor(62,100);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(3);
tft.print("REMOTE");

tft.setCursor(312,100);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(3);
tft.print("INDOOR");

tft.setCursor(162,165);
tft.setTextColor(TFT_GREEN);
tft.setTextSize(6);
tft.print("%");

tft.setCursor(412,165);
tft.setTextColor(TFT_CYAN);
tft.setTextSize(6);
tft.print("%");

tft.setCursor(162,230);
tft.setTextColor(TFT_GREEN);
tft.setTextSize(6);
tft.print("C");

tft.setCursor(145,230);
tft.setTextColor(TFT_GREEN);
tft.setTextSize(2);
tft.print("o");

tft.setCursor(412,230);
tft.setTextColor(TFT_CYAN);
tft.setTextSize(6);
tft.print("C");

tft.setCursor(395,230);
tft.setTextColor(TFT_CYAN);
tft.setTextSize(2);
tft.print("o");

}

void getAndPrintTime()
{
  
   delay(100);
   DateTime now = rtc.now(); //get the current date-time
   minuteNow = now.minute();
   if(minuteNow!=minutePrevious)
   {
      readSensor();
      dateString = getDayOfWeek(now.dayOfWeek())+" ";
      dateString = dateString+String(now.date())+"/"+String(now.month());
      dateString= dateString+"/"+ String(now.year()); 
      minutePrevious = minuteNow;
      hours = String(now.hour());
    if(now.minute()<10)
    {
      hours = hours+":0"+String(now.minute());
    }else
    {
      hours = hours+":"+String(now.minute());
    }
    printTime();
   }
}

void printTime()
{
  String dateAndTime = dateString+" "+hours;
  
  tft.setTextSize(2);
  char charBuf[25];
  dateAndTime.toCharArray(charBuf, 25);
  
  tft.setTextColor(TFT_WHITE, TFT_BLACK);
  tft.drawCentreString(charBuf,240,25,2);
}

String getDayOfWeek(int i)
{
  switch(i)
  {
    case 1: return "Monday";break;
    case 2: return "Tuesday";break;
    case 3: return "Wednesday";break;
    case 4: return "Thursday";break;
    case 5: return "Friday";break;
    case 6: return "Saturday";break;
    case 7: return "Sunday";break;
    default: return "Monday";break;
  }
}

void readSensor()
{
  previousIndoorTemperature = indoorTemperature;
  previousIndoorHumidity = indoorHumidity;
  
  indoorHumidity = dht.readHumidity();
  indoorTemperature = dht.readTemperature();
  Serial.println(indoorTemperature);
  Serial.println(indoorHumidity);
}

void printIndoorTemperature()
{
  if(indoorTemperature != previousIndoorTemperature)
  {

    String temperature = String(indoorTemperature,1);

    tft.fillRect(270,232,120,40,TFT_BLACK);
  
    tft.setCursor(270,234);
    tft.setTextColor(TFT_CYAN);
    tft.setTextSize(5);
    tft.print(temperature);

    previousIndoorTemperature = indoorTemperature;
  }
}

void printRemoteHumidity()
{
  String humidity;
  if(remoteHumidity != previousRemoteHumidity)
  {
    if(remoteHumidity == 0.0 && remoteTemperature == 0.0) //We just booted up
    {
      humidity = "---";
    }else
    {
          humidity = String(remoteHumidity,1);
    }
    
    tft.fillRect(20,167,120,40,TFT_BLACK);
  
    tft.setCursor(20,167);
    tft.setTextColor(TFT_GREEN);
    tft.setTextSize(5);
    tft.print(humidity);

    previousRemoteHumidity = remoteHumidity;
  }
}

void printRemoteTemperature()
{
  String temperature;
  if(remoteTemperature != previousRemoteTemperature)
  {
    if(remoteHumidity == 0.0 && remoteTemperature == 0.0) //We just booted up
    {
      temperature = "---";
    }else
    {
          temperature = String(remoteTemperature,1);
    }
    
    tft.fillRect(20,232,120,40,TFT_BLACK);
  
    tft.setCursor(20,234);
    tft.setTextColor(TFT_GREEN);
    tft.setTextSize(5);
    tft.print(temperature);

    previousRemoteTemperature = remoteTemperature;
  }
}

void printIndoorHumidity()
{
   if(indoorHumidity != previousIndoorHumidity)
  {

    String humidity = String(indoorHumidity,1);

    tft.fillRect(270,167,120,40,TFT_BLACK);
  
    tft.setCursor(270,167);
    tft.setTextColor(TFT_CYAN);
    tft.setTextSize(5);
    tft.print(humidity);

    previousIndoorHumidity = indoorHumidity; 
  }
}

Use of the String class can cause weird problems due to memory fragmentation. That may be part of your problem. See the evils of strings page to see why and some ways to use c-strings* instead of Strings.

*null terminated character arrays.

Holly molly ;D
Thanks for answer but I can't even describe myself a beginner. This is too much for me.

If i found some time i will make another transmitter and try again.
Lets see what will happend

if your data is simply getting lots of decimal places, you can take your values, change to int and multiply by 100 to save the decimal place,

send the int, then move back to a float by multiplying by 0.1

you might also do a value check. If humidity is greater than 99 or less than 1, then show 00.0
or just do the
int newHumidity= (previousHumidity *100)
previousHumidity = (newHumidty * 0.1 )

this is not the elegant way, or the best way to write code, but if your goal is to make the numbers on the display look correct, then this might work.

once you get better at your skills, you can dig deeper and correct the problem at the source and figure where the data corruption enters.

I believe that NRF24L01 had some damage because of cold weather. I'll changed it today.

But I still don't know why I have some interference on receiver board. That's might be problem that cause weird characters I guess :cold_sweat: ?

It might power supply problem but boot devices working on separate powerbank.

Well clearly my outdoor transmitter robotdyn arduino nano does not working.
Is that normal that easily get broken :expressionless: