Encountering abnormal spikes in a Line Graph

Hi Blynk Team,

I’m currently using Blynk to monitor pH values with a line graph. I’m encountering an issue: while the live data view on both mobile and web consoles appears as expected, I’m seeing unexpected spikes when switching to 1-hour or 6-hour recorded modes on the web console. This issue does not occur on the mobile app, where the data remains consistent without spikes.

Here are the specifics of my setup:

  • Hardware: ESP32, pH Sensor via RS485 (Modbus Communication), AC input pulse to denote start and end times.

I have attached some images for reference. Could you please provide a solution for this discrepancy?

Finally this is my code snippet:

// Blynk credentials
#define BLYNK_TEMPLATE_ID "----------------"
#define BLYNK_TEMPLATE_NAME "--------------------"
#define BLYNK_AUTH_TOKEN "------------------------------------"

// Include necessary libraries
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <time.h>
#include <Wire.h>
#include <Adafruit_MCP23X17.h>

// MCP23017 GPIO Expander object
Adafruit_MCP23X17 mcp;

// Arrays to hold sensor data
String Temp[2];
String PH_R[4];
uint8_t value[4];
String result;
String PH_result;

// New WiFi credentials
const char* ssid = "---------------";
const char* password = "----------------";

// Define the pins for TX and RX
#define RS485_TX 17
#define RS485_RX 16

// Initialize HardwareSerial for RS485 communication
HardwareSerial RS485Serial(1);

// Timezone settings for India Kolkata GMT +5:30
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 5.5 * 3600;
const int daylightOffset_sec = 0;

void setup() {
  // Start Serial communication
  Serial.begin(115200);

  // Initialize the MCP23X17 GPIO expander
  mcp.begin_I2C(0x21);  // Use your MCP23017 address here

  // Initialize RS485 communication
  RS485Serial.begin(9600, SERIAL_8N1, RS485_RX, RS485_TX);

  // Set pin 8 of MCP23017 as INPUT
  mcp.pinMode(8, INPUT);

  // Initialize WiFi and Blynk
  WiFi.begin(ssid, password);
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, password);

  // Wait for WiFi connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }
  Serial.println(WiFi.localIP());

  // Initialize NTP
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
}

void loop() {
  // Run Blynk to handle communication
  Blynk.run();

  // Send predefined messages over RS485
  sendRS485Message_PH();
  delay(10);  // Small delay
  sendRS485Message_Temperature();

  // Check for incoming RS485 messages
  if (RS485Serial.available()) {
    receiveRS485Message();
  }

  // Schedule deep sleep
  scheduleDeepSleep();
}

void sendRS485Message_PH() {
  // Predefined message to request pH data
  byte PhCmd[] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x71, 0xCB };
  RS485Serial.write(PhCmd, sizeof(PhCmd));
  delay(10);  // Small delay to ensure message is sent
}

void sendRS485Message_Temperature() {
  // Predefined message to request temperature data
  byte TempCmd[] = { 0x01, 0x04, 0x00, 0x03, 0x00, 0x01, 0xC1, 0xCA };
  RS485Serial.write(TempCmd, sizeof(TempCmd));
  delay(10);  // Small delay to ensure message is sent
}

void receiveRS485Message() {
  byte buffer[32];  // Buffer to hold incoming data
  int index = 0;

  // Read incoming bytes
  while (RS485Serial.available() && index < sizeof(buffer)) {
    buffer[index++] = RS485Serial.read();

    // Process the received data
    for (int i = 0; i < index; i++) {
      if (i == 3) {
        PH_R[0] = String(buffer[i], HEX);
        value[0] = (uint8_t)strtol(PH_R[0].c_str(), NULL, 16);
      } else if (i == 4) {
        PH_R[1] = String(buffer[i], HEX);
        value[1] = (uint8_t)strtol(PH_R[1].c_str(), NULL, 16);
      } else if (i == 5) {
        PH_R[2] = String(buffer[i], HEX);
        value[2] = (uint8_t)strtol(PH_R[2].c_str(), NULL, 16);
      } else if (i == 6) {
        PH_R[3] = String(buffer[i], HEX);
        value[3] = (uint8_t)strtol(PH_R[3].c_str(), NULL, 16);
      } else if (i == 12) {
        Temp[0] = String(buffer[i], HEX);
      } else if (i == 13) {
        Temp[1] = String(buffer[i], HEX);
      }
    }

    Serial.println();

    // Combine temperature bytes into a string and convert to integer
    result = combineNumbersToString(Temp, sizeof(Temp) / sizeof(Temp[0]));
    long intValue = strtol(result.c_str(), NULL, 16);
    Serial.println(intValue / 10);  // Print temperature value

    // Rearrange bytes for pH value and create float
    uint8_t reorderedBytes[4] = { value[1], value[0], value[3], value[2] };
    float PH_R;
    memcpy(&PH_R, reorderedBytes, sizeof(PH_R));
    Serial.println(PH_R, 3);  // Print pH value with 3 decimal places

    delay(500);

    // Update Blynk values based on pin state
    int pinState = mcp.digitalRead(8);
    if (pinState == LOW) {
      Blynk.virtualWrite(V1, PH_R);
      Blynk.virtualWrite(V2, intValue / 10);
      Blynk.virtualWrite(V3, 1);
    } else {
      Blynk.virtualWrite(V1, 0);
      Blynk.virtualWrite(V2, 0);
      Blynk.virtualWrite(V3, 0);
    }
  }
}

String combineNumbersToString(String numbers[], int size) {
  String combined = "";

  // Concatenate each number
  for (int i = 0; i < size; i++) {
    combined += numbers[i];
  }

  return combined;
}

void scheduleDeepSleep() {
  struct tm timeinfo;
  if (getLocalTime(&timeinfo)) {
    if (timeinfo.tm_hour == 0 && timeinfo.tm_min == 0) {
      ESP.restart();
    } else if (timeinfo.tm_hour == 0 && timeinfo.tm_min == 5) {
      esp_sleep_enable_timer_wakeup(60 * 1000000);  // 1 minute deep sleep
      esp_deep_sleep_start();
    }
  }
}

Could someone provide a solution to my problem? It would be very helpful to me.