Help needed to intergrade code with Blynk

Hi there, I’m totally new here.

I have plenty experience in electronics and absolutely nothing in coding, but trying my best to learn.
I am attempting to get the Blynk app to recognise an analogue AC voltage sensor. The issue is that it need some code to calculate the correct values.

I’m using the Arduino UNO with Ethernet Shield on the Blynk Server.

From what I’ve learnt so far from:

https://examples.blynk.cc/?board=Arduino%20Uno&shield=Ethernet%20Shield%20W5100&example=GettingStarted%2FGetData
and

Is that I need to insert the code below in the Blynk simple Ethernet code and set it as a virtual pin, Simple right? well maybe for someone experienced. I’ve been struggling for two days with this and the best I have managed is to get the correct values displayed in “Serial Monitor” while the Arduino remains online but cannot get it to display the correct voltage values in the App.

This is the code needed for the Voltage sensor

#include <Filters.h> //Easy library to do the calculations
#include <SPI.h>     //Libraries for the OLED display
#include <Wire.h>


float testFrequency = 50;                     // test signal frequency (Hz)
float windowLength = 40.0/testFrequency;     // how long to average the signal, for statistist

int Sensor = 0; //Sensor analog input, here it's A0

float intercept = -0.04; // to be adjusted based on calibration testing
float slope = 0.0430; // to be adjusted based on calibration testing
float current_Volts; // Voltage

unsigned long printPeriod = 1000; //Refresh rate
unsigned long previousMillis = 0;


void setup() {
  Serial.begin( 9600 );    // start the serial port
  

}

void loop() {
  
  RunningStatistics inputStats;                //Easy life lines, actual calculation of the RMS requires a load of coding
  inputStats.setWindowSecs( windowLength );
   
  while( true ) {   
    Sensor = analogRead(A0);  // read the analog in value:
    inputStats.input(Sensor);  // log to Stats function
        
    if((unsigned long)(millis() - previousMillis) >= printPeriod) {
      previousMillis = millis();   // update time every second
            
      Serial.print( "\n" );
      
      current_Volts = intercept + slope * inputStats.sigma(); //Calibartions for offset and amplitude
      current_Volts= current_Volts*(40.3231);                //Further calibrations for the amplitude
      

And this is the code I’m attempting to insert it into

#define BLYNK_PRINT Serial


#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "vN_i4iz0BP9K7NGz3qI4h8qaKDVH-uUV";

#define W5100_CS  10
#define SDCARD_CS 4

void setup()
{
  // Debug console
  Serial.begin(9600);

  pinMode(SDCARD_CS, OUTPUT);
  digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card

  Blynk.begin(auth);
  // You can also specify server:
  //Blynk.begin(auth, "blynk-cloud.com", 80);
  //Blynk.begin(auth, IPAddress(192,168,1,111), 8080);
  // For more options, see Boards_Ethernet/Arduino_Ethernet_Manual example
}

void loop()
{
  Blynk.run();
}

I Have managed to use the timed function and link A1 to a virtual pin V1, but the values displayed in the Blynk app jump between 335VAC and 750VAC. this is the code that I used.


#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "vN_i4iz0BP9K7NGz3qI4h8qaKDVH-uUV";

#define W5100_CS  10
#define SDCARD_CS 4
int sensorValue = A1; //Sensor analog input, here it's A0
BlynkTimer timer; // Announcing the timer

void setup()
{
  // Debug console
  Serial.begin(9600);

  pinMode(SDCARD_CS, OUTPUT);
  digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card

  Blynk.begin(auth);
  // You can also specify server:
  //Blynk.begin(auth, "blynk-cloud.com", 80);
  //Blynk.begin(auth, IPAddress(192,168,1,111), 8080);
  // For more options, see Boards_Ethernet/Arduino_Ethernet_Manual example

  timer.setInterval(1000L, sensorDataSend); //timer will run every sec 
}

void sensorDataSend()
{
  sensorValue = analogRead(A1);         // reading sensor from analog pin
  Blynk.virtualWrite(V1, sensorValue);  // sending sensor value to Blynk app
}

void loop()
{
  Blynk.run();
  timer.run();        // run timer every second
}

I would seriously appreciate some help or guidance in the right direction please.

you need to put all of the voltage sensor stuff in the timed function. You can probably do away with the while statement, and the millis stuff as the function will only run as often as the timer is set to.

Something like below. (it looks like part of the voltage senor code is missing, so I just had it print/send the value)

#include <SPI.h>
#include <Ethernet.h>
#include <BlynkSimpleEthernet.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "vN_i4iz0BP9K7NGz3qI4h8qaKDVH-uUV";

#define W5100_CS  10
#define SDCARD_CS 4
BlynkTimer timer; // Announcing the timer

float testFrequency = 50;                     // test signal frequency (Hz)
float windowLength = 40.0/testFrequency;     // how long to average the signal, for statistist

int Sensor = 0; //Sensor analog input, here it's A0

float intercept = -0.04; // to be adjusted based on calibration testing
float slope = 0.0430; // to be adjusted based on calibration testing
float current_Volts; // Voltage



void setup()
{
  // Debug console
  Serial.begin(9600);

  pinMode(SDCARD_CS, OUTPUT);
  digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card

  Blynk.begin(auth);
  // You can also specify server:
  //Blynk.begin(auth, "blynk-cloud.com", 80);
  //Blynk.begin(auth, IPAddress(192,168,1,111), 8080);
  // For more options, see Boards_Ethernet/Arduino_Ethernet_Manual example

  timer.setInterval(1000L, sensorDataSend); //timer will run every sec 
}

void sensorDataSend()
{
     RunningStatistics inputStats;                //Easy life lines, actual calculation of the RMS requires a load       of coding
  inputStats.setWindowSecs( windowLength );
     
    Sensor = analogRead(A0);  // read the analog in value:
    inputStats.input(Sensor);  // log to Stats function
        
 
            
      Serial.print( "\n" );
      
      current_Volts = intercept + slope * inputStats.sigma(); //Calibartions for offset and amplitude
      current_Volts= current_Volts*(40.3231);                //Further calibrations for the amplitude
        Serial.print( current_Volts );
       Blynk.virtualWrite(V1, current_Volts);
}

void loop()
{
  Blynk.run();
  timer.run();        // run timer every second
}
1 Like

Thanks Toro_Blanco, the code runs fine but the values displayed are still inaccurate. The voltage values jump between 350VAC and 750VAC when connected to A0. I know that the values read correct when using only the code for the AC voltage sensor.

Yes there is a piece of the code missing but that is for and LCD display, I removed that part

Image of the serial monitor when running only the code for the AC sensor

The code of @Toro_Blanco is theoretically correct, but in this case not working because

  1. you didn’t help disclose that you have to take a lot of measurements at very high frequency (voltage signal at 50HZ), then use statistic math in Filters library to calculate the sigma()
  2. we don’t know even what type of sensor you’re using.

Having similar background, I can understand this is the sampling speed problem.
Try this code that hopefully fixes the sampling speed issue if slow UNO (16MHz) is still fast enough with Blynk in loop(). If not, you have to use faster boards, such as ESP826 or ESP32 (80/160/240 MHz)

#if defined(ESP8266) || defined(ESP32)
#error This code is designed to run on Arduino AVR (Nano, UNO, Mega, etc.) platform, not ESP8266 nor ESP32! Please check your Tools->Board setting.
#endif

#define BLYNK_PRINT Serial

#include <SPI.h>
#include <Wire.h>
#include <Ethernet.h>

#include <Filters.h>  // https://github.com/JonHub/Filters

// Only use true for Mega1280 or Mega2560. For UNO, use false
#define USE_BLYNK_WM      false

#if USE_BLYNK_WM

// Start location in EEPROM to store config data. Default 0
// Config data Size currently is 128 bytes)
#define EEPROM_START     768    //512

#include <EthernetWebServer.h>
#include <BlynkSimpleEthernet_WM.h>               // https://github.com/khoih-prog/BlynkEthernet_WM
#else
#include <BlynkSimpleEthernet.h>

#define USE_LOCAL_SERVER      true

#if USE_LOCAL_SERVER
char auth[] = "******";
char server[] = "account.duckdns.org";
//char server[] = "192.168.2.112";
#else
char auth[] = "******";
char server[] = "blynk-cloud.com";
#endif

#define BLYNK_HARDWARE_PORT       8080
#endif

#define W5100_CS  10
#define SDCARD_CS 4

//float testFrequency = 50;   // test signal frequency (Hz)
//float windowLength = 20.0/testFrequency;     // how long to average the signal, for statistist

//float windowLength = 40.0;  // how long to average the signal, for statistist
float testFrequency = 50;                     // test signal frequency (Hz)
float windowLength = 40.0/testFrequency;     // how long to average the signal, for statistist

int Sensor = 0;             //Sensor analog input, here it's A0

float intercept = -0.04;    // to be adjusted based on calibration testing
float slope     = 0.0430;       // to be adjusted based on calibration testing
float current_Volts;        // Voltage

unsigned long printPeriod     = 1000; //Refresh rate
unsigned long previousMillis  = 0;

int sensorPin = A0; //Sensor analog input, here it's A0

RunningStatistics inputStats;                //Easy life lines, actual calculation of the RMS requires a load of coding

void setup()
{
  // Debug console
  Serial.begin(115200);

  Serial.println(F("\nStart W5100_WM_Config"));

  pinMode(SDCARD_CS, OUTPUT);
  digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card

  inputStats.setWindowSecs( windowLength );

#if USE_BLYNK_WM
  Blynk.begin();
#else
#if USE_LOCAL_SERVER
  Blynk.begin(auth, server, BLYNK_HARDWARE_PORT);
#else
  Blynk.begin(auth);
  // You can also specify server:
  //Blynk.begin(auth, server, BLYNK_HARDWARE_PORT);
#endif
#endif

#if USE_BLYNK_WM
  if (Blynk.connected())
  {
    Serial.print(F("Conn2Blynk: server = "));
    Serial.print(Blynk.getServerName());
    Serial.print(F(", port = "));
    Serial.println(Blynk.getHWPort());
    Serial.print(F("Token = "));
    Serial.print(Blynk.getToken());
    Serial.print(F(", IP = "));
    Serial.println(Ethernet.localIP());
  }
#endif
}

void measureLoop()
{
  Sensor = analogRead(sensorPin);   // read the analog in value:
  inputStats.input(Sensor);         // log to Stats function

  if ( millis() - previousMillis >= printPeriod )
  {
    previousMillis = millis();      // update time every second

    current_Volts = ( intercept + slope * inputStats.sigma() ) * (40.3231); //Calibrations for offset and amplitude
    Serial.print( "Voltage : " );
    Serial.println( current_Volts );
    Blynk.virtualWrite(V1, current_Volts);
  }

}

void loop()
{
  Blynk.run();

  // run as fast as possible to measure high frequency (50Hz)
  measureLoop();
}

1 Like

Hi Khoih,

It is this Voltage sensor ZMPT101B as this one here. Yes it is 50Hz @ 240VAC. I included Filters.h on all the sketches that I tried. The original author explained that it is need to calculate the output.

With the code above the Arduino does not connect to Blynk server. This is the output from the serial monitor

You have to either change the Serial speed to 9600 in the code or change the computer Serial port speed to 115200

void setup()
{
  // Debug console, change speed to 9600 here
  Serial.begin(9600);
  //Serial.begin(115200);

  Serial.println(F("\nStart W5100_WM_Config"));
  ...
}

you also have to change to use Cloud Server by

#define USE_LOCAL_SERVER      false

and also the auth token.

Anyway, this is the new code with those lines changed

#if defined(ESP8266) || defined(ESP32)
#error This code is designed to run on Arduino AVR (Nano, UNO, Mega, etc.) platform, not ESP8266 nor ESP32! Please check your Tools->Board setting.
#endif

#define BLYNK_PRINT Serial

#include <SPI.h>
#include <Wire.h>
#include <Ethernet.h>

#include <Filters.h>  // https://github.com/JonHub/Filters

// Only use true for Mega1280 or Mega2560. For UNO, use false
#define USE_BLYNK_WM      false

#if USE_BLYNK_WM

// Start location in EEPROM to store config data. Default 0
// Config data Size currently is 128 bytes)
#define EEPROM_START     768    //512

#include <EthernetWebServer.h>
#include <BlynkSimpleEthernet_WM.h>               // https://github.com/khoih-prog/BlynkEthernet_WM
#else
#include <BlynkSimpleEthernet.h>

#define USE_LOCAL_SERVER      false

#if USE_LOCAL_SERVER
char auth[] = "******";
char server[] = "account.duckdns.org";
//char server[] = "192.168.2.112";
#else
char auth[] = "vN_i4iz0BP9K7NGz3qI4h8qaKDVH-uUV";
char server[] = "blynk-cloud.com";
#endif

#define BLYNK_HARDWARE_PORT       8080
#endif

#define W5100_CS  10
#define SDCARD_CS 4

//float testFrequency = 50;   // test signal frequency (Hz)
//float windowLength = 20.0/testFrequency;     // how long to average the signal, for statistist

//float windowLength = 40.0;  // how long to average the signal, for statistist
float testFrequency = 50;                     // test signal frequency (Hz)
float windowLength = 40.0/testFrequency;     // how long to average the signal, for statistist

int Sensor = 0;             //Sensor analog input, here it's A0

float intercept = -0.04;    // to be adjusted based on calibration testing
float slope     = 0.0430;       // to be adjusted based on calibration testing
float current_Volts;        // Voltage

unsigned long printPeriod     = 1000; //Refresh rate
unsigned long previousMillis  = 0;

int sensorPin = A0; //Sensor analog input, here it's A0

RunningStatistics inputStats;                //Easy life lines, actual calculation of the RMS requires a load of coding

void setup()
{
  // Debug console
  Serial.begin(9600);

  Serial.println(F("\nStart W5100 Voltage Measure"));

  pinMode(SDCARD_CS, OUTPUT);
  digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card

  inputStats.setWindowSecs( windowLength );

#if USE_BLYNK_WM
  Blynk.begin();
#else
#if USE_LOCAL_SERVER
  Blynk.begin(auth, server, BLYNK_HARDWARE_PORT);
#else
  Blynk.begin(auth);
  // You can also specify server:
  //Blynk.begin(auth, server, BLYNK_HARDWARE_PORT);
#endif
#endif

#if USE_BLYNK_WM
  if (Blynk.connected())
  {
    Serial.print(F("Conn2Blynk: server = "));
    Serial.print(Blynk.getServerName());
    Serial.print(F(", port = "));
    Serial.println(Blynk.getHWPort());
    Serial.print(F("Token = "));
    Serial.print(Blynk.getToken());
    Serial.print(F(", IP = "));
    Serial.println(Ethernet.localIP());
  }
#endif
}

void measureLoop()
{
  Sensor = analogRead(sensorPin);   // read the analog in value:
  inputStats.input(Sensor);         // log to Stats function

  if ( millis() - previousMillis >= printPeriod )
  {
    previousMillis = millis();      // update time every second

    current_Volts = ( intercept + slope * inputStats.sigma() ) * (40.3231); //Calibrations for offset and amplitude
    Serial.print( "Voltage : " );
    Serial.println( current_Volts );
    Blynk.virtualWrite(V1, current_Volts);
  }

}

void loop()
{
  Blynk.run();

  // run as fast as possible to measure high frequency (50Hz)
  measureLoop();
}


Thank you very much,

I will test it tonight when I get home and post feedback.

Thank you so very much. This worked 100%

1 Like