Problem with my custom WeatherStation data transmission

Hello fellow tinkerers!
I am in a bit of a pickle. I am using an Arduino nano to retrieve data from a bunch of sensors, and then using a serial connection to an esp8266 to send that info to a google sheet. I am using structs to send the data over the serial connection, and I lost my working copy of the code. After rewriting the code, the data is not being received right on the other side (line 156 of RX code returning false) I am not sure whether the data is being sent correctly, or if it is being received incorrectly. would love to know what you guys think. I am doing this for my grandpa here in France and leave back to the US soon, so would love to get this figured out. Thank you all in advance for the help. I am +9hr from the us so I may reply late.
Data_Transfer_Rx.ino (6.8 KB)
Data_Transfer_Tx.ino (12.3 KB)

Here is the rx code for yall

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

#define ON_Board_LED 2  //--> Defining an On Board LED, used for indicators when the process of connecting to a wifi router
#define Bucket_Size 0.2794 // bucket size to trigger tip count [mm]
#define WindSpeed_PerRotation 1.2 // bucket size to trigger tip count [mm]
String GAS_ID = "AKfycbx2s2Ab9qNppmHCFa91VRVE8lbGsH6Es4EIE-OVZlWa4yqtG4XxH4-cFAdgFrJwvOo"; //--> spreadsheet script ID

//----------------------------------------SSID and Password of your WiFi router.
const char* ssid = "Livebox-227E_2.4G"; //--> Your wifi name or SSID.
const char* password = "253A4CE599EE25A42FF5E94233"; //--> Your wifi password.

//----------------------------------------Host & httpsPort
const char* host = "script.google.com";
const int httpsPort = 443;
//----------------------------------------

WiFiClientSecure client; //--> Create a WiFiClientSecure object.


/**
 * @name WeatherData
 * @summary Contains all the weather information that is provided by the service.
 * 
 * */
typedef struct {
  int AirTemperature;
  int AirHumidity;
  int AirPressure;
  int Brightness;
  int SoilTemperature;
  int SoilMoisture;
  int LiveRain;
  int TotalRainfall;
  int WindSpeed;
  int CalDirection;
}
WeatherData;

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password); //--> Connect to your WiFi router
  pinMode(ON_Board_LED,OUTPUT); //--> On Board LED port Direction output
  digitalWrite(ON_Board_LED, HIGH); //--> Turn off Led On Board

  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    //----------------------------------------Make the On Board Flashing LED on the process of connecting to the wifi router.
    digitalWrite(ON_Board_LED, LOW);
    delay(250);
    digitalWrite(ON_Board_LED, HIGH);
    delay(250);
    //----------------------------------------
  }
  //----------------------------------------
  digitalWrite(ON_Board_LED, HIGH); //--> Turn off the On Board LED when it is connected to the wifi router.
  //----------------------------------------If successfully connected to the wifi router, the IP Address that will be visited is displayed in the serial monitor
  Serial.println("");
  Serial.print("Successfully connected to : ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
  client.setInsecure();
}

//*********************************************************************************************************************************************
/**
 * @name RecieveData
 * @summary Recieves the data over the serial line
 * 
 * @arg {WeatherData* newWeatherData} The pointer to the weather data struct to fill and complete.
 * 
 * @return {bool} If the read request failed or not.
 * 
 * */
bool RecieveData(WeatherData* newWeatherData) 
{
  return (Serial.readBytes((char*)newWeatherData, sizeof(WeatherData)) == sizeof(WeatherData));
}

void sendData(WeatherData myData) {
  Serial.println("==========");
  Serial.print("connecting to ");
  Serial.println(host);
  
  //----------------------------------------Connect to Google host
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }
  //----------------------------------------

  //----------------------------------------Processing data and sending data
  String string_Airtemperature =  String(myData.AirTemperature);
  String string_Airhumidity =  String(myData.AirHumidity);
  String string_AirPressure =  String(myData.AirPressure);
  String string_Brightness =  String(myData.Brightness);
  String string_SoilTemperature =  String(myData.SoilTemperature);
  String string_SoilMoisture =  String(myData.SoilMoisture);
  String string_LiveRain =  String((myData.LiveRain * Bucket_Size) * 760);
  String string_totalRainfall =  String(myData.TotalRainfall * Bucket_Size);
  String string_windSpeed =  String(myData.WindSpeed * WindSpeed_PerRotation);
  String string_calDirection =  String(myData.CalDirection);


  String url = "/macros/s/" + GAS_ID + "/exec?Air_Temperature=" + string_Airtemperature + "&Air_Humidity=" + string_Airhumidity + "&Air_Pressure=" + string_AirPressure +
  "&Soil_Temperature="  + string_SoilTemperature + "&Soil_Humidity=" + string_SoilMoisture +
  "&Live_Rain=" + string_LiveRain + "&Total_Rainfall=" + string_totalRainfall +
  "&Wind_Speed=" + string_windSpeed + "&Wind_Direction=" + string_calDirection +
  "&Brightness=" + string_Brightness;


  Serial.print("requesting URL: ");
  Serial.println(url);

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
         "Host: " + host + "\r\n" +
         "User-Agent: BuildFailureDetectorESP8266\r\n" +
         "Connection: close\r\n\r\n");

  Serial.println("request sent");
  //----------------------------------------

  //----------------------------------------Checking whether the data was sent successfully or not
  while (client.connected()) {
    String line = client.readStringUntil('\n');
    if (line == "\r") {
      Serial.println("headers received");
      break;
    }
  }
  String line = client.readStringUntil('\n');
  if (line.startsWith("{\"state\":\"success\"")) {
    Serial.println("esp8266/Arduino CI successfull!");
  } else {
    Serial.println("esp8266/Arduino CI has failed");
  }
  Serial.print("reply was : ");
  Serial.println(line);
  Serial.println("closing connection");
  Serial.println("==========");
  Serial.println();
  //----------------------------------------
} 



// Example
void loop() {
  if (rawdata != 1) return; // Wait until we get the new struct value (we send a 1 before sending the struct)
  WeatherData myData;
  if (!RecieveData(&myData)) { // It returns a boolean on weather or not it failed, and fills the struct that we provided it. 
    Serial.println("Failed to read data.");
  } else {
    sendData(myData);
    Serial.print("AirTemperature: ");
    Serial.println(myData.AirTemperature);
    Serial.print("AirHumidity: ");
    Serial.println(myData.AirHumidity);
    Serial.print("AirPressure: ");
    Serial.println(myData.AirPressure);
    Serial.print("Brightness: ");
    Serial.println(myData.Brightness);
    Serial.print("SoilTemperature: ");
    Serial.println(myData.SoilTemperature);
    Serial.print("SoilMoisture: ");
    Serial.println(myData.SoilMoisture);
    Serial.print("LiveRain: ");
    Serial.println(myData.LiveRain);
    Serial.print("TotalRainfall: ");
    Serial.println(myData.TotalRainfall);
    Serial.print("WindSpeed: ");
    Serial.println(myData.WindSpeed);
    Serial.print("CalDirection: ");
    Serial.println(myData.CalDirection);
    Serial.println("\n");
  }
}


//*********************************************************************************************************************************************

and the tx

// ****************************************************************************** Include Libraries **********************************************************************************

#include <Arduino.h>

#include <DHT.h>

#include <Wire.h>

#include <SFE_BMP180.h>

#include <OneWire.h>

#include <DallasTemperature.h>

#include "TimerOne.h"

#include <math.h>

//****************************************************************************** DEFINE PINS ****************************************************************************************

// ************************ Digital pins *************************************

#define WindSensor_Pin (2) // digital pin for wind speed sensor
#define rainMeter_Pin (3) // digital pin for rain sensor
#define DHT_PIN (4) // digital pin for Air humidity
#define SoilTempSensor_Pin (5) // digital pin for Soil Humidity

// ************************ Analog pins **************************************

#define SoilMoisture_Pin (A0) // analog pin for soil moisture sensor
#define WindVane_Pin (A2) // analog pin for wind direction sensor
#define BrightnessSensor_Pin (A3) // analog pin for Brightness sensor
//define AtmPressureSensor_Pin (A4)&(A5)

// ************************ Parameters ***************************************

// #define TimerLength_Microseconds(s) (s * 1000000) //Convert TimerLength to Microseconds 
#define DHTTYPE DHT22 // DHT 22  (AM2302)
#define Bucket_Size 0.2794 // bucket size to trigger tip count [mm]
#define VaneOffset 0 // define the offset for caclulating wind direction
// #define TimerLength 5 // In seconds
#define Altitude 20 // Altitude for atmospheric pressure (for calibration)
#define AirValue 450 // Soil Moisture sensor value in air (for calibration)
#define WaterValue 225 // Soil Moisture sensor value in water (for calibration)

// ****************************************************************************** CREATE OBJECTS *************************************************************************************

DHT dht(DHT_PIN, DHTTYPE);
OneWire oneWire(SoilTempSensor_Pin);
SFE_BMP180 bmp180;
DallasTemperature sensors( & oneWire);

// ****************************************************************************** Global Variables ***********************************************************************************

void RainInterrupt();
void RotationInterrupt();
void SendStruct();

long AvgCounterAirTemperature;
long AvgCounterAirHumidity;
long AvgCounterAirPressure;
long AvgCounterBrightness;
long AvgCounterSoilTemperature;
long AvgCounterSoilMoisture;
int LiveRain;
int TotalRainfall;
long AvgCounterWindSpeed;
long AvgCounterCalDirection;

int AirTemperature;

// ************************ Timers *******************************************

long contactTime;
long contactBounceTime;
long rainCheck;

// ************************ Counters *****************************************

long tipCount;
long lastTipCount;
long rotationsCount;
long totalRainCount;



/**
 * @name WeatherData
 * @summary Contains all the weather information that is provided by the service.
 * 
 * */
typedef struct {
  int AirTemperature;
  int AirHumidity;
  int AirPressure;
  int Brightness;
  int SoilTemperature;
  int SoilMoisture;
  int LiveRain;
  int TotalRainfall;
  int WindSpeed;
  int CalDirection;
}
WeatherData;
WeatherData myData;

/**
 * @name SendData
 * @summary Sends the data over the serial line
 * 
 * @arg {WeatherData* newWeatherData} The pointer to the weather data struct
 * 
 * @return {void}
 * 
 * */

void SendData(const WeatherData * newWeatherData) {
  Serial.write(1);
  Serial.write((const char * ) newWeatherData, sizeof(WeatherData));
}

// ****************************************************************************** Functions ******************************************************************************************

void VariableSetup() {
  // setup rain sensor values
  tipCount = 0;
  lastTipCount = 0;
  totalRainCount = 0;

  // setup anemometer values
  rotationsCount = 0;

  // setup timer values
  contactTime = 0;
  contactBounceTime = 0;
  rainCheck = 0;
}

//*****************************************************

int iteration = 0;
void RunAverageIteration() {
  AvgCounterAirTemperature += AirTemperature;
  AvgCounterAirHumidity += GetAirHumidity();
  AvgCounterAirPressure += GetAirPressure();
  AvgCounterBrightness += GetBrightness();
  AvgCounterSoilTemperature += GetSoilTemperature();
  AvgCounterSoilMoisture += GetSoilMoisture();
  AvgCounterWindSpeed += GetWidspeed();
  AvgCounterCalDirection += GetWindDirection();
  LiveRain = GetLiveRain();
  TotalRainfall = GetTotalRainfall();
  iteration++;
}

void GetAverage() {
     
  if (iteration == 0) {
    myData.AirHumidity = GetAirHumidity();
    myData.AirPressure = GetAirPressure();
    myData.Brightness = GetBrightness();
    myData.SoilTemperature = GetSoilTemperature();
    myData.SoilMoisture = GetSoilMoisture();
    myData.LiveRain = GetLiveRain();
    myData.TotalRainfall = GetTotalRainfall();
    myData.WindSpeed = GetWidspeed();
    myData.CalDirection = GetWindDirection();
    myData.AirTemperature = AirTemperature;
  } else {
    myData.AirTemperature = AvgCounterAirTemperature / iteration;
    myData.AirHumidity = AvgCounterAirHumidity / iteration;
    myData.AirPressure = AvgCounterAirPressure / iteration;
    myData.Brightness = AvgCounterBrightness / iteration;
    myData.SoilTemperature = AvgCounterSoilTemperature / iteration;
    myData.SoilMoisture = AvgCounterSoilMoisture / iteration;
    myData.LiveRain = LiveRain;
    myData.TotalRainfall = TotalRainfall;
    myData.WindSpeed = AvgCounterWindSpeed / iteration;
    myData.CalDirection = AvgCounterCalDirection / iteration;
  }
  avgReset();  
}

//*****************************************************

void avgReset()
{
  iteration = 0;
  AvgCounterAirTemperature = 0;
  AvgCounterAirHumidity = 0;
  AvgCounterAirPressure = 0;
  AvgCounterBrightness = 0;
  AvgCounterSoilTemperature = 0;
  AvgCounterSoilMoisture = 0;
  AvgCounterWindSpeed = 0;
  AvgCounterCalDirection = 0;
  LiveRain = 0;
  TotalRainfall = 0;
  
}

//*****************************************************

void RainInterrupt() {

  if ((millis() - contactTime) > 15) { // debounce of sensor signal
    tipCount++;
    totalRainCount++;
    rainCheck = 0;

    contactTime = millis();
  }
}

//*****************************************************

void RotationInterrupt() {

  // Interrupt handler routine to increment the rotation count for wind speed
  if ((millis() - contactBounceTime) > 15) { // debounce the switch contact
    rotationsCount++;
    contactBounceTime = millis();
  }
}


//*****************************************************

int GetAirHumidity() {
  int AirHumidity;
  AirHumidity = round(dht.readHumidity());
  return AirHumidity;
}


//*****************************************************

int GetAirPressure() {
  int AirPressure;
  char status;
  double T, P;

  status = bmp180.startTemperature();

  if (status != 0) {
    delay(status);
    status = bmp180.getTemperature(T);

    if (status != 0) {
      status = bmp180.startPressure(3);
      if (status != 0) {
        delay(status);
        status = bmp180.getPressure(P, T);


        if (status != 0) {
          AirPressure = round(bmp180.sealevel(P, Altitude));
          AirTemperature = T;
          // Pressure and Temperature
        } 
      }
    }
  }
  return AirPressure;
}

//*****************************************************

int GetBrightness() {
  int Brightness, rawBrightness;

  rawBrightness = analogRead(BrightnessSensor_Pin);
  Brightness = (800 - rawBrightness);
  if(Brightness<0)
  {
    Brightness = 0;
  }
  return Brightness;
}

//*****************************************************

int GetSoilTemperature() {
  int SoilTemperature;

  sensors.requestTemperatures();
  SoilTemperature = sensors.getTempCByIndex(0);
  return SoilTemperature;
}

//*****************************************************

int GetSoilMoisture() {
  int SoilMoisture, soilMoistureValue;

  soilMoistureValue = analogRead(SoilMoisture_Pin);
  SoilMoisture = map(soilMoistureValue, AirValue, WaterValue, 0, 100);

  if (SoilMoisture >= 100.00) {
    SoilMoisture = 100.00;
  } else if (SoilMoisture <= 0) {
    SoilMoisture = 0.00;
  } else if (SoilMoisture > 0.00 && SoilMoisture < 100.00) {
    SoilMoisture = SoilMoisture;
  }

  return SoilMoisture;
}

//*****************************************************

int GetLiveRain() {
  float LiveRain;
  LiveRain = (tipCount);

  return LiveRain;
}

//*****************************************************

int GetTotalRainfall() {
  int totalRainAmount;

  if (tipCount > 0 && lastTipCount == 0 && rainCheck >= 4) {
    totalRainCount = 0;
    lastTipCount = tipCount;
    totalRainCount = totalRainCount + tipCount;
  } else if (tipCount > 0 && lastTipCount != 0 && rainCheck < 4) {
    lastTipCount = tipCount;
    totalRainCount = totalRainCount + tipCount;
  }
  if (tipCount == 0) {
    lastTipCount = tipCount;
  }

  totalRainAmount = (totalRainCount);
  return totalRainAmount;
}

//*****************************************************

float GetWidspeed() {
  float windspeed;

  windspeed = (rotationsCount)*1.2;

  return windspeed;
}

//*****************************************************

int GetWindDirection() {
  int WindAngle;
  int vaneValue;
  int vaneDirection;

  vaneValue = analogRead(WindVane_Pin);
  vaneDirection = map(vaneValue, 0, 1023, 0, 360);
  WindAngle = vaneDirection + VaneOffset;

  if (WindAngle > 360)
    WindAngle = WindAngle - 360;

  if (WindAngle > 360)
    WindAngle = WindAngle - 360;
  return WindAngle;
}

//*****************************************************

void SendStruct() {
  SendData( &myData);
}

//*****************************************************

void PinmodesSetup() {
  pinMode(rainMeter_Pin, INPUT);
  digitalWrite(rainMeter_Pin, HIGH);

  pinMode(WindSensor_Pin, INPUT);
  digitalWrite(WindSensor_Pin, HIGH);

  attachInterrupt(digitalPinToInterrupt(rainMeter_Pin), RainInterrupt, FALLING);
  attachInterrupt(digitalPinToInterrupt(WindSensor_Pin), RotationInterrupt, FALLING);
}

// ****************************************************************************** Void Setup *****************************************************************************************

void setup() {

  Serial.begin(115200);
  sensors.begin();
  dht.begin();

  VariableSetup();
  PinmodesSetup();

  bmp180.begin();

  // ************************ Initialize Timer *********************************
  
  // Timer1.initialize(TimerLength_Microseconds(TimerLength));
  // //  Timer1.initialize(500000);
  //   Timer1.attachInterrupt(SendStruct);
}

// ****************************************************************************** Void Loop ******************************************************************************************

void loop() {
   delay(50);
  RunAverageIteration();
  Serial.println("");
  Serial.println("RAW");
  Serial.println(AvgCounterAirTemperature);
  Serial.println(AvgCounterAirHumidity);
  Serial.println(AvgCounterAirPressure);
  Serial.println(AvgCounterBrightness);
  Serial.println(AvgCounterSoilTemperature);
  Serial.println(AvgCounterSoilMoisture);
  Serial.println(LiveRain);
  Serial.println(TotalRainfall);
  Serial.println(AvgCounterWindSpeed);
  Serial.println(AvgCounterCalDirection);
  Serial.println("");

  if (iteration == 100) 
  {
    GetAverage();
    Serial.println("");
    Serial.println("AVERAGE**********************************************************************");
    Serial.println(myData.AirTemperature);
    Serial.println(myData.AirHumidity);
    Serial.println(myData.AirPressure);
    Serial.println(myData.Brightness);
    Serial.println(myData.SoilTemperature);
    Serial.println(myData.SoilMoisture);
    Serial.println(myData.LiveRain);
    Serial.println(myData.TotalRainfall);
    Serial.println(myData.WindSpeed);
    Serial.println(myData.CalDirection);
    Serial.println("*****************************************************************************");
    Serial.println("");
//    avgReset();
    SendStruct();
    delay(3000);
  }
}

Print the data you get and see what's wrong/missing.

It may be that your struct is being packed differently by the two systems. If one is padded and one is not, you may see bogus size mismatch between them.

I already tried, but the data that is being received is from the struct so doesn't really represent anything. I'm seeing random numbers.

I might not be sending the right info either, but I am fairly new to structs, so I may have made some mistakes

What's this for?

Serial.write(1);

If you look at the RX Code, I look for a 1 before reading the actual struct. This is because the Serial line is always returning a -1, so i send a one before the struct so that the rx knows the struct is after

OMG, you made me look through my code, and i ermebered the struct used to be short ints, and now it seems to work. I am going to check everything, and let you know

You have cracked it I think. Apparently int on an esp8266 is 32 bit.

yes i remeber looking with my friend, and we saw the esp and nano have different bit counts for ints, so that must have been the problem

nano is 16 bit for an int and esp is 32, but a short int is 16 on esp, that is why it didnt work, and also why we use short int on one side and not the other, Thank you sooo much for helping me remeber!!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.