Photon heart bit

Hi There!
Which is the maximum heart bit photon can support?
I am intending to send data every 5 to 10 minutes.
Is that possible?
I tried 8 minutes and after 1-hour approx photon started to blink red.
I am using the following scheme for send values:

unsigned long lastvalues;// Global initialize to 0
const unsigned long Sendvalues = 480000L;
............................
.........................
void loop() {
  unsigned long topLoop = millis(); 
  i

if ( (topLoop - lastvalues) >= Sendvalues) 
      { lastvalues = topLoop;
        ............................
        ............................}

Thanks for any help.

But how are you sending data? With a particle cloud function, TCP or UDP? Something else? I take it you use some sort of buffer however you send that data? Can you show us how you manage that buffer?

Too many unknows to give you a less vague answer.

3 Likes

@joost
I am sending data to photon from external MCU using the serial port.
Also, I’m using Ubidots to send data to the dashboard.
The data I’m sending is like that:

/*  A78.04%81.09%80.20%36.75%78.40%111.13%78.35%81.66% '\n' */

The external MCU send data every 2 seconds so when the Ubidots should run, it has the more updated data.
After unparse de data, it is sending through TCP using API provided from Ubidots libraries for the Particle devices.
The point is sending data, for example, every 5, 10, 15 or 20 second implies a lot of “dots” monthly, or a big bill, in this case for the development stage.
So I would like to send data to Ubidots every 10 minutes for example, but this action
seems to overflow the Photon serial buffer, it is something I am assuming.
That situation motivated my previous post.
Maybe I would need to clean up the Photon’s serial buffer once it processes the serial data received.
Thanks for any help

I suggest you post some of your code that handles the serial port, buffers it and sends it on to Ubidots. All I can say now is that your issue “feels like” a buffer handling problem (e.g. overrun, handshake with external MCU etc.) but I can be waay out of wack without some code…

I am not familiar with Ubidots on the programming side, others will need to comment on that. But again, a bit of code will go a long way getting returns/help on your post.

2 Likes

@joost
Hi
Thank you for your suggestion. Really the issue was about serial buffer overflow.
I workout that reading the buffer more frequently without sending data to Ubidots.
The data is only sending when a counter variable accumulates an X*5000L, I mean a constant times 5 seg. This lets me send info with update rate off 10, 15 and 20 minutes.
But I am facing the challenge of change dynamically that update rate of data send to Ubidots. I mean using a widget switch(1/0) from the dashboard, be able to select between 5 sec and for example 20 minutes for update rate.

For the regular update rate, I am using the following scheme:

void loop() {
  unsigned long topLoop = millis(); 
  

if ( (topLoop - lastvalues) >= Sendvalues) 
      { lastvalues = topLoop;
    
       Function 1
       Function 2
      .................
       Function n

}

}

I am trying to modify on the fly the variable “Sendvalues” using a widget switch (1/0) from the dashboard.
’‘Sendvalues’’ is a constant unsigned long, so I tried to use unsigned long and change that value at "if ( (topLoop - lastvalues) >= Sendvalues) ".
That doesn’t work, after a few second Photon starts to flash solid red.
Do you have some idea how to accomplish that?
Thank you for any help.

Ah, buffer overflow, that’s what it felt like. The logic you present here seems ok. I would define “topLoop” outside loop() but this would not fix the problem you have. Perhaps go back to your buffer and make sure all is OK?

Be very strickt/clear on how and when you handle that buffer. Also be clear on how you name things; variables such as ‘topLoop’, ‘lastvalues’, ‘Sendvalues’ are not clear to me and not uniformly defined (camel case). Better (ihmo) would be ‘currentTime’, ‘lastSyncTime’ and ‘syncPeriod’. You can then write:

  currentTime = millis();
  if ( currentTime > lastSyncTime + syncPeriod) {
     lastSyncTime = currentTime;

    .....
  }

that just reads more like the logic you intended to me.

I don’t suggest that the naming causes your problem, I do suggest that proper naming and being very detail oriented is an attitude you should have as a programmer to solve sticky issues such as buffer overrun.

2 Likes

@joost
Hi Joost I would need your valuable help once more.
It’s about the same code we talked about at the beginning of the post.
As I told you this code send data to UBIDOTS so I can visualize on the dashboard.
As you will see on the Photon code, the MCU is sending more data that Photon is sending to UBIDOTS cloud, in this case just two variables.
This for economical reasons.
The point is that very randomly the Photon appears breathing green and in this case, I understand that something in the code is blocking the cloud connection.
Well, I told you at the previous post the problem with the serial buffer overrun was solved.
Now I am wondering if you with your experience can help me taking a look at the code, I will appreciate it very much.
The code works wonderfully 24/7 with the exceptional periods I found it breathing green. If I power cycle the photon the code run well again.



// This #include statement was automatically added by the Particle IDE.
#include <Ubidots.h>

/* Note: the external MCU sends the following string every 2000 ms.*/

/*  A78.04%81.09%80.20%36.75%78.40%111.13%78.35%81.66% '\n' */

/****************************************
 * Include Libraries
 ****************************************/
#include <string.h>
#include <stdio.h>
/****************************************
 * Define Constants
 ****************************************/
#ifndef TOKEN
#define TOKEN "XXXXXXXXXXXXXXXXXXXXXXXXXX"  // Put here your Ubidots TOKEN
#endif

Ubidots ubidots(TOKEN);

void waitForString(void);
char Temp[200]={'\0'};  
char data;

unsigned long lastvalues;// Global initialize to 0
const unsigned long sendValues =5000L;

char* Temp0;
char* Temp1;
char* Temp2;
char* Temp3;
char* Temp4;
char* Temp5;
char* Temp6;
char* Temp7;
char* Irms1;
char* Irms2;  

double value0;
double value1;
double value2;
double value3;
double value4;
double value5;
double value6;
double value7;
double value8;
double value9;
int counter=0;

/****************************************
 * Auxiliar Functions
 ****************************************/
void waitForString()
{
    
  //  store the string received for external MCU 
 
int i=0;
data=0;

  while (Serial1.available( ) &&  data !='A')  // check for A

           { data =  Serial1.read();}

   while ( Serial1.available( )  && data!='\n' )
  
  
     {   
    
          Temp[i] =  Serial1.read();
         
         i++; 
     }

Temp0 = strtok (Temp,"%");
Temp1 = strtok (NULL, "%");
Temp2= strtok (NULL, "%");
Temp3= strtok (NULL, "%");
Temp4= strtok (NULL, "%");
Temp5= strtok (NULL, "%");
Temp6= strtok (NULL, "%");
Temp7= strtok (NULL, "%");         
Irms1=strtok  (NULL ,"%");
Irms2=strtok  (NULL ,"%");         
         
value0=atof(Temp0);
value1=atof(Temp1);
value2=atof(Temp2);
value3=atof(Temp3);
value4=atof(Temp4);
value5=atof(Temp5);
value6=atof(Temp6);
value7=atof(Temp7);
value8=atof(Irms1);
value9=atof(Irms2);
}







/****************************************
 * Main Functions
 ****************************************/
void setup() {
  
   Serial1.begin(57600);
   
}

void loop() {
  unsigned long topLoop = millis(); 
  
if ( (topLoop - lastvalues) >= sendValues) 
      { lastvalues = topLoop;
    
    counter++;
    
 if ( counter==20)
        
      {  
        counter=0;  
      
         ubidots.setMethod(TYPE_TCP);  //Set to TCP the way to send data
        
        waitForString();
 
 
        ubidots.add("Data0", value0);  
        ubidots.add("Data1", value1); 

      if(ubidots.isDirty()){
 
        ubidots.sendAll(); }
     
   
      }// end if counter++


 else{ waitForString();}// Reading serial1 buffer besido not using the data storaged
                        
                        
     
    
     } // End if toplop
    
      
      
}// end function

Thank you very much.

While I have an issue with some of the design and coding style, I do not see anything in your code that could lead to losing the particle cloud. Which particle OS version are you using? There are some problems with 0.7 and particle cloud connectivity as I understand it (I could be wrong), please research the forum here for that info. I can tell you that some of my photons have a hard time connecting to the cloud, I appear to have less problems with the P1 devices.

Sorry I don’t have a “this is it” answer for you.

I do suggest you work on your coding style a bit - indentations and the use of brackets must be consistent and condusive to gaining a good grasp on a program’s flow. E.g. this:

  while (Serial1.available( ) &&  data !='A')  // check for A

           { data =  Serial1.read();}

   while ( Serial1.available( )  && data!='\n' )
  
  
     {   
    
          Temp[i] =  Serial1.read();
         
         i++; 
     }

is not nearly as clear to understand as this:

  while (Serial1.available( ) &&  data !='A') {
  	data = Serial1.read();
  }

  while ( Serial1.available( )  && data!='\n' ) {
    Temp[i] = Serial1.read();
    i++;
  }

Again, the formatting is not your problem here, just trying to show you a better way to code … By the way, the “handshaking” (if you can call it that) by means of these two while()-loops has some side effects you may want to think about at some time: a) it waists a lot of CPU time, b) the program is ‘stuck in the loop’ if the external MCU does not behave, c) if the external MCU sends too many data bytes (or you have noise on the line) your second while() loop will crash. Also, the series of Temp0…Temp7 and value0…value9 variables are better kept in an array.

1 Like

Just to know, do you need to catch all data between two intervals?
If not, it’s safe to let the RX buffer “overflow”. It’s a circular buffer which will just overwrite “outdated” contents.

@Joost Than you very much for your valuable help. Regarding the OS, yes all my Photons have 0.7.0. I’ll take action to change this on at least one of them.
Thank you for correcting me regarding the coding style.
Have a great day.

Hi, @ScruffR
Thank you for taking a look at my code. Answering your question if I need to catch all data between intervals, I would tell you that for intervals like 5, 7 or 10 minutes it’s it not necessary.
But because the user would need to get info, lets said in “real time” the basic interval of a few seconds it would be necessary.
At the beginning of this post, I was sending data with an interval of 15, 20, 30 sec just for test Ubidots dashboards. The downside of that was that in a few minutes the Photon started to blink solid red continuously, @joost suggested to me that this would be a serial port overrun. Taking this into consideration I made some changes to the code.
II you observe the code the if … else corresponding to :
if ( (topLoop - lastvalues) >= sendValues), the content else’s curly bracket was just {;}
do nothing,
When I populated that else with the function which read the serial1 port
" waitForString() " the problem with the serial buffer disappears. Correct me if I am wrong but apparently that function discharge the buffer.
One important point is that the exterior MCU sends data serially to Photon every 2000 ms. That it’s so because I need to get the most updated data values when the intervals of 5, 7 or 10 min expire.

Having done that changes, in two opportunities the Photon started to breathe green.

So I would like to conciliate the fact that more than 99% of the time Photon works OK with that “else” populated, with the fact that: " it’s safe to let the RX buffer “overflow”. It’s a circular buffer which will just overwrite “outdated” contents." as you said.

I would appreciate your opinion about that and regarding switch from OS 0.7.0 to 0.6.0.
Thank you very much.

That's the easier part. If you have to downgrade (for whatever reason) I'd not go down to 0.6.0 but 0.6.3 (on Photon) and 0.6.4 (on Electron).
But you may also consider giving 0.8.0-rc.10 a shot.

That might be a workaround for your issue, but I'm pretty sure the root cause is not the "overflow" of the RX buffer due to above reason. However, if you are dealing with a circular buffer which may refill very rapidly, you may be reading more data into your intermediate buffer than you anticiapted due to "overwritten" bytes which would otherwise signal an "end-of-packet" your code may be relying on and hence overflowing your intermediate buffer rather than the internal RX buffer.

waitForString() is not limiting i nor does it feature a timeout for the case that either of the internal while() loops fails to satisfy its exit condition.
The former may lead to SOS panic and the latter to the breathing green issue you experience.
That function also doesn't deal with partial packets.

In addition to modifying the while loop as you said

waitForString() is not limiting i nor does it feature a timeout for the case that either of the internal while() loops fails _emphasized text_to satisfy its exit condition.

What about implementing a Photon digital output to enable the serial transmission from the external MCU, only when the interval is about to expire?
Do you believe that that could be the easiest solution to this issue?
On the other hand, as you said,

But you may also consider giving 0.8.0-rc.10 a shot.

and keeping the above code, do you think that that change can have a positive impact on breathing green issue?
Thanks again for your opinion on that.

Possibly, but no promises.

If that's an option then just ignoring all incoming bytes till then should do the trick just the same.

If that's the case, then you'd just need to have some sort of timer set a flag which arms the receiving code 2+ sec before your expected transmission, have a tight loop wait for your start byte with a timout of 2000ms add a second loop that waits for Serial1.available() to reach your expected payload length (providing it's no more that 60 byte) or bail out after a sensible timeout (calculated from transmission length and baudrate plus some extra milliseconds).

@ScruffR
Thank for your help
The code is working OK sending a request to the external MCU every time the interval is about to expire.
Now I have other question, I am using the following scheme for the void loop():

unsigned long topLoop = millis();
if ( (topLoop - lastvalues) >= sendvalues) {
lastvalues = topLoop;
Func 1();
Func 2();
…
Func n();
}
I would need to change on the fly the “sendValues” value, I mean I need to switch from a long interval to a short interval.
I would like to do that using a digital on/off switch on the Ubidots dashboard.
That switch is assigned to a variable which value is get from a GET request.
That request is inside the Photon code.
I have tried something but it doesn’t work. I a very trivial code but the speed of the count should be changed as the switch in the dashboard switch from 0 to 1 or vice versa.
Her is the code that only increments the counter every 30 sec and it doesn’t work for 5 sec.

// This #include statement was automatically added by the Particle IDE.
#include <Ubidots.h>


/* Note: the external MCU sends the following string every 2000 ms.*/

/*  A78.04%81.09%80.20%36.75%78.40%111.13%78.35%81.66% '\n' */

/****************************************
 * Include Libraries
 ****************************************/
#include <string.h>
#include <stdio.h>
/****************************************
 * Define Constants
 ****************************************/
#ifndef TOKEN
#define TOKEN "XXXXXXXXXXXXXXXXXXXXXXXXXXX"  // Put here your Ubidots TOKEN
#endif

#ifndef VAR_ID
#define VAR_ID "5ba27596bbddbd143709f769"  // Put here your data source name or VAR _ID
#endif
#ifndef VAR_LABEL
#define VAR_LABEL "Valor" // Put here your variable api label : letras
#endif
#ifndef DEVICE_LABEL
#define DEVICE_LABEL"MESON3" //  es Meson2 Put here your device api label
#endif


Ubidots ubidots(TOKEN,"industrial.api.ubidots.com");


unsigned long lastvalues;// Global initialize to 0
unsigned long sendvalues =5000L;
bool Valor;

int counter=0;

void setup() {
    
   Serial1.begin(57600);
  //ubidots.setDebug(true);  //Uncomment this line for printing debug messages
  
}


void loop() {
  unsigned long topLoop = millis(); 
  

if ( (topLoop - lastvalues) >= sendvalues) {
       
        lastvalues = topLoop; 
   
    
  
  
   if (counter>450000){
    counter=0;
    }
    
    counter++;
    ubidots.add("Data0", counter); 
    ubidots.sendAll();
   
   
  Valor = ubidots.getValueWithDatasource(DEVICE_LABEL, VAR_LABEL);
    
     if (Valor==0){
    sendvalues=5000L;
     }
   
    else if ( Valor==1)
    { sendvalues=30000L;
    }
   
else{;} 
}



}


I am using the Ubidots library for Photon.
Thanks for any helps

A first step to correctly assess the structure of your code proper indentaion would help :wink:

Once you’ll reformat your code you may see that you don’t get the desired value as quickly as you may think you do.

Now I have a better style to the code.
Besides that, I cannot understand when you said

You may see that you don’t get the desired value as quickly as you may think you do.

I understand that an RTO give you a slice of time of x ms to run your code but that does not clarify me what you said.
Here is the code again;

// This #include statement was automatically added by the Particle IDE.
#include <Ubidots.h>


/* Note: the external MCU sends the following string every 2000 ms.*/

/*  A78.04%81.09%80.20%36.75%78.40%111.13%78.35%81.66% '\n' */

/****************************************
 * Include Libraries
 ****************************************/
#include <string.h>
#include <stdio.h>
/****************************************
 * Define Constants
 ****************************************/
#ifndef TOKEN
#define TOKEN "xxxxxxxxxxxxxxxxxx"  // Put here your Ubidots TOKEN
#endif

#ifndef VAR_ID
#define VAR_ID "5ba27596bbddbd143709f769"  // Put here your data source name or VAR _ID
#endif

#ifndef VAR_LABEL
#define VAR_LABEL "Valor" // Put here your variable api label : letras
#endif

#ifndef DEVICE_LABEL
#define DEVICE_LABEL"MESON3" //  es Meson2 Put here your device api label
#endif


Ubidots ubidots(TOKEN,"industrial.api.ubidots.com");


unsigned long lastvalues;// Global initialize to 0
static unsigned long sendvalues =30000L;




static bool Valor;

int counter=0;

void setup() {
    
   Serial1.begin(57600);
  //ubidots.setDebug(true);  //Uncomment this line for printing debug messages
  
}


void loop() {
  unsigned long topLoop = millis(); 
  
  

   
    
  

    if ( (topLoop - lastvalues) >= sendvalues) {
       
        lastvalues = topLoop; 
  
  
  
   if (counter>450000){
    counter=0;
    }
    
    counter++;
    ubidots.add("Data0", counter); 
    ubidots.sendAll();
   
  
     
    
     if (Valor==1){
     sendvalues=30000L;
     }
   
     
      sendvalues= 5000L;
      Valor = ubidots.getValueWithDatasource(DEVICE_LABEL, VAR_LABEL);
     
}



}

Thank you for your time.

If you code looked like this (with consistent indentation and without unnecessary blank lines)

void loop() {
  unsigned long topLoop = millis(); 
  if ( (topLoop - lastvalues) >= sendvalues ) {
    lastvalues = topLoop; 
    if (counter>450000) {
      counter=0;
    }  
    counter++;
    ubidots.add("Data0", counter); 
    ubidots.sendAll();
    
    if (Valor==1) {
      sendvalues=30000L;
    } 
    sendvalues= 5000L;
    Valor = ubidots.getValueWithDatasource(DEVICE_LABEL, VAR_LABEL); 
  }
}

You could see much easier

  1. your ubidots calls are inside the block that is only ever executed once every 5000ms
  2. your sendvalues will always be 5000, even when Valor == 1 due to the lack of the (previously present) else if (Valor == 0) block (which I’d rather write as a simple else).

Having said this, I’d write something like this

void loop() {
  unsigned long topLoop = millis(); 

  Valor = ubidots.getValueWithDatasource(DEVICE_LABEL, VAR_LABEL);  // get value every iteration of loop
  //sendvalues = (Valor == 1) ? 30000L : 5000L;                     // if not otherwise used, I'd omit sendvalues and this line and just use `Valor` direct as
  if ( (topLoop - lastvalues) >= (Valor ? 30000L : 5000L) ) {
    lastvalues = topLoop; 
    if (++counter > 450000)                                         // do you really only want to reset every 26 days (450000 * 5sec) minimum?
      counter = 0; 

    ubidots.add("Data0", counter); 
    ubidots.sendAll();   
  }
}

If you want to reduce the network traffic for requesting Valor you may want wrap that in an independent “millis() timed block” (e.g. once per second).

BTW, have you checked whether Valor changes at all when changing it on the remote end?

@ScruffR
Thank you, it sound to me very interesting what you are suggesting me, I’ll give a try it.
My point is that I am not familiar with Arduino code, I currently use Cypress PSoc5LP which include all the analog and digital block in one chip and I am not using RTOs. So for me Photon means internet connectivity only.
Cypress also have internet connectivity but is more complicated to manage it Photon is more friendly.

Thanks for your help to use photon.