Timer interrupts on the Particle photon and Blynk Communication via Bluetooth problem

You are trying to run all these functions potentially thousands of times a second…

And that is NOT the correct way to run the Blynk.run() command and most definitely NOT the correct way to run all those Blynk.virtualWrite() commands :scream:

Please read this (and the Docs, etc)… Try out some basic Blynk examples until you really understand how Blynk works and don’t try to reinvent the wheel :stuck_out_tongue:

http://help.blynk.cc/getting-started-library-auth-token-code-examples/blynk-basics/keep-your-void-loop-clean

Good day Gunner

Thank you for your speedy reply. I actually have completed a program in the manner described in your post. However it does not help. Here is that version of my code:


#include <BlynkSimpleSerialBLE.h>
#include <CE_BME280.h>
#define Addr 0x76                                           //BME280 address 118

char auth[] = "c39c9a12d53241fca5eb0975bc7c1b41";
void BlynkComms(void);
void DisplayOnSerialMonitor();

void GetBME280SensorData(void);                             //Get BME280 Sensor data
float Temperature;
float Pressure;
float pressure1 = 991;
float pressure2 = 991; 
float Humidity;
float Altitude;
float Dewpoint;
byte BME280SensorConnected=0;
String BME280SensorState("");                               //To store the connection status of the sensor

CE_BME280 bme;                                              // I2C


void WindsensorSetup(void);                                 //Function to initialse the windsensor
void Revolution(void);                                      //Interrupt function ISR
void WindDirection(void);                                   //To get wind direction data
void Windsensor(void);                                      //Function to get windsensor data
int WindspeedPin=D3;                                        //Digital Read pin to detect revolutions of wind speed sensor 
float SampleTime=5000;                                      //Sample time in milliseconds
float Speed=0;                                              //Wind speed in in Km/hr 
volatile int RevCount=0;                                    //Since the main program and ISR are sharing this variable
int AnalogPin1=A1;                                          //Analog read pin for Wind Direction
int AnalogPin6=A6;                                          //Analog pin used as an output to the wind sensor detection circuit
int AnalogPin4=A4;                                          //Analog pin used as an input to the microcontroller from the wind sensor detection circuit
float AnalogValue=0;                                        //Voltage of the potentiometer from the wind direction sensor
String Direction;
String North("North");
String NorthEast("North East");
String East("East"); 
String SouthEast("South East");
String South("South");
String SouthWest("South West");
String West("West");
String NorthWest("North West");
String WindsensorState("");                                 //Store the connection status of the windsensor
byte WindsensorConnected=0;                                 //Variable used to control the execution of the WindsensorSetup function
Timer timer(SampleTime, WindSpeed);                         //Use of timers to calculate Windspeed, every 5 seconds. It has more precise timing than milli 
BlynkTimer timer1;                                          //Create timer called timer1 

void setup() {
    
    Serial.begin(9600);
    Serial1.begin(9600);
    Blynk.begin(Serial1, auth);
    pinMode(WindspeedPin,INPUT);                    //Specifies the Digital pin as an input with a weak internal pull down resistor ??????????***IS THE PULL UP REQUIRED???***
    pinMode(AnalogPin6, OUTPUT);                            //Set analog pin A6 as Output
    pinMode(AnalogPin4, INPUT_PULLDOWN);                    //Set analog pin A4 as Input with a weak internal pull down resistor
    timer1.setInterval(1000L, BlynkComms);                  //Set timer1 to periodically send data to Blynk every second
    Serial.println("BME280 and Windsensor Blynk detection test");
    delay(3000);
   

}

void loop() {
    
    GetBME280SensorData();
    Windsensor();
    timer1.run();
    Blynk.run(); 
    DisplayOnSerialMonitor();
    delay(500);

}


void WindsensorSetup(){
     
    Speed=0;
    RevCount=0;    
    timer.start();                                           //Initialize Timer interrupt
    attachInterrupt(WindspeedPin, Revolution, FALLING);      //When the reed switch closes, ISR triggered on the falling edge only 
    WindsensorConnected=1;
    
}


void Revolution(){

    //Hardware solves debounce issue
    RevCount=RevCount+1;    
   
}


void WindSpeed(){
     
    Speed=(3.621015*RevCount)/(SampleTime/1000);            //Speed in km/hr. Formula adpated from technical manual check Bookmarks Davis says 1600 rev/hr ---> 1 mile/hour
    RevCount=0;
    timer.reset();                                          //RESET THE TIMER TO RESTART THE COUNT FROM ZERO 
    
}
 
 
void WindDirection(){
    
    int RawValue=0;

   
    RawValue=analogRead(AnalogPin1);
    AnalogValue=(3.3*RawValue)/4096;
    
    if(AnalogValue>= 2.8875){
       
        Direction=NorthWest; 
    
    }
    
    else if(AnalogValue>= 2.475){
        
        Direction=West; 
      
    }
    
    else if(AnalogValue>= 2.0625){
        
        Direction=SouthWest; 
       
    }
    
    else if(AnalogValue>= 1.65){
        
        Direction=South; 
 
    }
    
    else if(AnalogValue>= 1.2375){
        
        Direction=SouthEast; 
   
        
    }
    else if(AnalogValue>= 0.825){
        
        Direction=East; 
        
    }
    
    else if(AnalogValue>=0.4125 ){
        
        Direction=NorthEast; 
     
    }
    
    else if(AnalogValue<0.4125 ){
       
        Direction=North; 
        
    }
    
}


void GetBME280SensorData(){
    
    if(!bme.begin(Addr)){                                  
    
        Serial.println("\nBME280 sensor not connected");    
        BME280SensorState="Disconnected";
        Serial.println(BME280SensorState);
        BME280SensorConnected=0;  
        Temperature = 0;
        Humidity = 0;
        Pressure = 0;       
        Dewpoint = 0;
     

    }
    else if(bme.begin(Addr)){
       
       if(BME280SensorConnected==0){                                        
        
        BME280SensorState="Connected";
        BME280SensorConnected=1;                                            
        Serial.println("BME280 sensor is connected and setup is complete"); //Remove
        delay(300);                                                         //To allow BME280 to stablise before measurements are taken
       
       }
       
        
        Temperature = bme.readTemperature();
        Humidity = bme.readHumidity();
        Pressure = (bme.readPressure()/100);                                //To convert to hPa
        Dewpoint = Temperature - ((100 - Humidity)/5);                      //!!!USE BETTER FORMULA if result not accurate!!!!
         
        
        
    }
     
     
}     

void Windsensor(){
    
    digitalWrite(AnalogPin6, HIGH);
    
    if(digitalRead(AnalogPin4) == HIGH){                        //To detect if the windsensor is connected to the weather station
        
        if (WindsensorConnected == 0){                          //Setup windsensor only the first time after it is detected
        
            WindsensorSetup();
            WindsensorState="Connected";                                  
            Serial.println("Windsensor is connected and setup is complete");    //REMOVE AFTER TESTING
            
       
        }
        
        if(Speed==0){                                           //if there is a wind speed measurement than look for the wind direction
        
            Direction="None";
        
        }
        else
        WindDirection();                                        //Call wind direction function
        
        
    }
    else if(digitalRead(AnalogPin4) == LOW){                    //If the sensor is not connected disable the timer and interrupt once 
        
        timer.stop();
        timer.reset();
        detachInterrupt(WindspeedPin);
        WindsensorConnected=0;
        WindsensorState="Disconnected";
        Serial.println("Windsensor is not connected");
        RevCount=0;
        Speed=0;
        Direction="None";
        
    }
    
    digitalWrite(AnalogPin6, LOW);                             
    
}


void BlynkComms(){
    
    Blynk.virtualWrite(V0, Temperature);
    Blynk.virtualWrite(V8, BME280SensorState); 
    Blynk.virtualWrite(V1, Humidity);
    Blynk.virtualWrite(V9, BME280SensorState);
    Blynk.virtualWrite(V2, Pressure);
    Blynk.virtualWrite(V10, BME280SensorState);
    Blynk.virtualWrite(V4, Dewpoint);
    Blynk.virtualWrite(V11, BME280SensorState); 
    Blynk.virtualWrite(V5, Direction); 
    Blynk.virtualWrite(V12, WindsensorState);
    Blynk.virtualWrite(V6, Speed);
    Blynk.virtualWrite(V13, WindsensorState);
    
}

void DisplayOnSerialMonitor(){
    
    Serial.print("Temperature ");                           
    Serial.print(Temperature);
    Serial.println(" C");
    Serial.print("Humidity ");
    Serial.print(Humidity);
    Serial.println(" %");
    Serial.print("Pressure ");
    Serial.print(Pressure);
    Serial.println(" hPa");
    Serial.print("Dewpoint ");
    Serial.print(Dewpoint);
    Serial.println(" C");
    Serial.println("");
    Serial.printlnf("\nRev Count: %d", RevCount);
    Serial.print("Wind direction: ");
    Serial.print(Direction);
    Serial.printlnf("\nAnalog voltage: %fV", AnalogValue);
    Serial.printlnf("Windspeed %f km/h\n", Speed);
    
    
}

The interrupt “Revolution” seems to be occurring more than it should. Instead of reading a count of say 10 it will read 20 or jump to 34 instead of 21 etc. Could the timer interrupt be affected by the Blynk code in a some weird and observable manner?

Either you’ve posted the wrong code, or you’ve not understood the “Keep your void loop() clean” document

Pete.

@PeteKnight @Gunner
Good day Pete

I have posted the right code. This is the least amount of code that I can use in order to execute all the other code I need to. Do simply put the rest of my functions in the function i created for the Blynk communication and have only blynk.run and timer.run in the void loop?

I guess i did not understand :disappointed:. How do i keep void loop as empty as the example in the post whilst also allowing my actual program to run? Please, tell me how should I be doing it? Thanks in advance.

With a timer routine. Call your functions at timed intervals, not several thousand times a second.
Your device has it’s own timer functions.

https://docs.particle.io/reference/device-os/firmware/photon/#software-timers

1 Like
1 Like

Everything you need to do is outlined in the document that was linked earlier. If you don’t understand some of it then I’d suggest re-reading it a few times. If you still don’t understand some of it then quite the parts of the document that you’re having difficulty with. This will allow the document to be clarified and improved in future to make it more understandable…

Pete.

1 Like

Thank you very much guys. I had not thought about it that way. I will try that out.

@PeteKnight @Costas

I have changed my code as you and the article has advised and everything is running smoothly. Thanks again.
Now I’m investigating the possibility of implementing some energy saving techniques associated with putting my controller in its sleep mode for any duration between 100ms to 500ms, I am still deciding. However, my concern is that whilst in sleep mode, the execution of the code in my void loop will be halted. I think running a timer interrupt to run the Blynk.run and timer.run code should solve this problem. Is there a minimum frequency that these two commands need to be executed per second to avoid any problems ? Thanks in advance.

I have no idea about sleep modes on your board, especially using Bluetooth. If the sleep mode turns Bluetooth off then sleeping for a short period probably won’t help you, as the re-connection process will take a while.
If you aren’t using Wi-Fi and can turn this off permanently then that will save you power.

You almost certainly won’t be able to use timers successfully, or keep a Blynk connection going, in sleep mode.

Pete.

That’s hardly going to stop global warming :slight_smile:
What are you really wanting to do?
Like @PeteKnight I don’t have any practical experience with your board type.

1 Like

@Costas @PeteKnight

Thank you guys for replying so quickly. I understand that you may not be familiar with the board i am using. I would like to know what is the minimum frequency, required by Blynk, that the Blynk.run and timer.run commands need to be executed so that i do not have Blynk timer issues nor Blynk connection issues. If i know what that minimum frequency is then i can try to put my board in sleep mode long enough to conserve energy but wake it up soon enough to allow the two commands to run.

I am not attempting to stop global warming :joy: But i am trying to maximize the number of hours i get from the battery powering my project :slightly_smiling_face:

@Alli check the docs for heartbeat. You can change the default 10 or 20 seconds to your own preferences.

@Costas

Thank you Costas again for your response. Reading through the doc regarding “heartbeat” i cannot help but wonder if i require blynk.run if i periodically call on heartbeat? If i am still required to use blynk.run in conjunction with heartbeat than the question still remains what is the minimum number of times that blynk.run needs to be executed per second? Also what is the minimum number of times that timer.run need to be called (For BlynkTimer)? I can’t seem to be find this information in the docs.

Both Blynk.run() and Timer.run() should be called as frequently as is possible, hence their recommendation as some of the ONLY code in the void loop(), whenever possible, so as to eliminate any delays or blocking of them being frequently called… think of it like your own breathing, yes you could hold your breath occasionally, but not recommended long term for overall functionality :stuck_out_tongue_winking_eye:

The heartbeat is just Blynk’s way of keeping tabs between the Hardware and the Server link… Since if the Server looses the heartbeat, then it starts displaying such in the App and eventually shutting down the supposedly non-existent connection.

@Gunner

So if i were to call these Blynk.run and Timer.run every 2 seconds this is acceptable?
And using this frequency means i will no longer need to use heartbeat since Blynk.run will take care of all blynk’s communication needs?

Well, you are messing with essential timing in both libraries that will have foreseen and unforeseen consequences.

Adding Blynk to an existing Arduino process can be akin to adding a trailer to a vehicle… same old driving experience… until you try to accelerate, break, turn sharply, park and so on… Lots of extra things to consider now, and the solution would NOT be to snooze and only think about it every two seconds :wink:

Learn how Blynk works with the basics first, then look around at others examples to see how structured timing of functions and other tricks allow both Blynk and other timing sensitive code to co-exist.

i am trying to do exactly that. I have looked at the information on timers on the blynk docs and as well heartbeat and Blynk but it does not have the answers i am looking for. Can you please give me some direction by posting a few links that i could follow?

I am really not sure of the exact questions you need answered… You seem to be asking if you can disregard basic necessities in Blynk and timer operations… And the answers are essentially NO, as doing so is not recommended until you really know what you are doing (and even then, not likely)… And honestly, that comes with experience.

Good day Blynk community

I have encountered a strangely similar problem with my project. I am using the latest blynk version 2.27.1 on my android Samsung note 4 smart using android version 5.1.1 lolipop. My project requires the communication of data from my micro-controller Particle Photon to the Blynk app via a jdy-09 BLE module.

Here is the strange part, my project was working perfectly fine up until a few days ago. i switched my project off the last time it was working and then tried yesterday (no change in code or hardware) and it refused to connect correctly with the Blynk app. The connection status would say “connecting” forever but never connects. Some times it would say connected but variables on Blynk’s widget would never update. Most of the time it would say that it could not connect to the Bluetooth module and that i should make sure my auth token was correct. Here is what i tried:

  1. I changed the auth token on my Blynk project and on my micro to test communication using a different auth token number.
  2. I than suspected that my Bluetooth module might be faulty so i tested my Bluetooth module using a terminal app and an arduino. After setting up the code in arduino i was able to send data to arduino via the bluetooth module from my android phone’s terminal app and from the terminal app to the arduino (Displayed on the serial monitor)
  3. I than tested the bluetooth communication pins of my photon using an arduino. This was to test if the serial pins on my photon were functioning correctly. A number was send from the photon to the arduino and the same number was sent back to the photon from the arduino via their TX and RX pins and the results were displayed on the serial monitor. The pins were functioning correctly.
  4. I than re-uploaded coded examples requiring blynk communication via bluetooth , aside from the code that was already working in my photon a few days ago, and all of them experienced the same communication problem. This eliminated any coding or software errors on the microcontroller.

From this, i think that the only other issue can be with the Blynk app itself. It was the only thing i altered between the two days: I updated the software and added a few new widgets onto the screen (eventor, email notification and led) , that i was planning to program functionality for in the coming few days. Even after i updated the software the app was running fine, i only think i really changed was the addition of widgets. I removed all these added widgets but this also did not solve the problem. Please advise what can i do to find the cause of this problem, or is there a solution that i have not come across as yet?