Unreliable Outputs from same code, beginner requiring guidance.

I am fairly new to arduino and am working on a project. If I upload the same code to the arduino with no changes, sometimes it will work completely fine, other times “flowSFM” will always be printed as 0 even when I know that isn’t the case, and other times “flowSFM” will be printed as normal for around 20 seconds, then will stop working and go to 0.

I am unsure of why it is so unreliable even when no changes to the code or circuit are made whatsoever. Could it be a problem in my code? Does anyone have any insight into why this might happen? Thanks

#include "ArduinoMotorShieldR3.h"
ArduinoMotorShieldR3 md;

#include <avr/pgmspace.h>
#include <Wire.h>
#include <sfm3000wedo.h>


int state = -1;
unsigned long startTime;
unsigned long duration;

SFM3000wedo measflow(64);

int offset = 32768;
int scale = 120;


void setup() {
  Wire.begin();
  delay(500);
  Serial.begin(9600);

  measflow.init();
  Serial.println("Sensor initialized!");
  md.init();

  Serial.print("Enter patient weight: ");
}


void loop() {

    if (Serial.available() > 0) {
      int weight = Serial.parseInt();
      Serial.println(weight);
      
    


  while (weight > 0) {

  
  // for reading SFM3300
  float flowSFM = measflow.getvalue();
  //if (flowSFM > 0) flowSFM = flowSFM + offset;
  if (flowSFM > 0) flowSFM = 0;
  else if (flowSFM < 0) flowSFM = flowSFM - offset;
  flowSFM = flowSFM / scale;
  flowSFM = flowSFM * 16.6666;

  if (flowSFM > 1.00) {
    Serial.println(flowSFM);
    Serial.print(millis());
    Serial.print(",  ");
    delay(100);
  }
  if (flowSFM < 1.00) {
    Serial.println(0.00);
    Serial.print(millis());
    Serial.print(",  ");
    delay(100);
  }

  if ( millis() - startTime >= duration ) {
    // advance to next state
    state++;
    if ( state > 3 ) state = 0;
    startTime = millis();
    switch (state) {
      case 0:
        md.setM1Speed(350);
        duration = 600;
        break;
      case 1:
        md.setM1Speed(0);
        duration = 500;
        break;
      case 2:
        md.setM1Speed(-350);
        duration = 275;
        break;
      case 3:
        md.setM1Speed(0);
        duration = 2000;
        break;
    }
    }
  }
  }
}
int offset = 32768;

The maximum value for an Arduino int is 32767 and this line should be corrected but that doesn't explain the inconsistent results that you are getting.

This may or may not be related, but in a previous version of the code which I thought gave reliable results, if I simply change “int offset = 32768;” to “int offset = 32767;” flowSFM no longer gives accurate results and just shows as 0. I don’t understand this as this integer doesn’t seem relevant in changing these results so drastically.

It also seems like every time I make a slight change in the code the results given go inconsistent again, could this somehow be a problem with the sensor itself? Or still the code?

Heres the previous version of the code that gave reliable results until I changed int offset to 32767:

#include "ArduinoMotorShieldR3.h"
ArduinoMotorShieldR3 md;

#include <avr/pgmspace.h>
#include <Wire.h>
#include <sfm3000wedo.h>

int state = -1;
unsigned long startTime;
unsigned long duration;

SFM3000wedo measflow(64);

int offset = 32767;
int scale = 120;


void setup() {
  Wire.begin();
  delay(500);
  Serial.begin(9600);

  measflow.init();
  Serial.println("Sensor initialized!");
  md.init();
}


void loop() {

  // for reading SFM3300
  float flowSFM = measflow.getvalue();
  //if (flowSFM > 0) flowSFM = flowSFM + offset;
  if (flowSFM > 0) flowSFM = 0;
  else if (flowSFM < 0) flowSFM = flowSFM - offset;
  flowSFM = flowSFM / scale;
  flowSFM = flowSFM * 16.6666;

  if (flowSFM > 1.00) {
    Serial.println(flowSFM);
    Serial.print(millis());
    Serial.print(",  ");
    delay(100);
  }
  if (flowSFM < 1.00) {
    Serial.println(0.00);
    Serial.print(millis());
    Serial.print(",  ");
    delay(100);
  }

  if ( millis() - startTime >= duration ) {
    // advance to next state
    state++;
    if ( state > 3 ) state = 0;
    startTime = millis();
    switch (state) {
      case 0:
        md.setM1Speed(350);
        duration = 600;
        break;
      case 1:
        md.setM1Speed(0);
        duration = 500;
        break;
      case 2:
        md.setM1Speed(-350);
        duration = 275;
        break;
      case 3:
        md.setM1Speed(0);
        duration = 2000;
        break;
    }
  }
}

Also a quick addition to that, upon changing the int offset back to 32768, it works and gives reliable results again.

Have you considered the possibility of a loose or otherwise faulty connection to the sensor?

Bonecrusher05:
Also a quick addition to that, upon changing the int offset back to 32768, it works and gives reliable results again.

Perhaps, but you are actually setting it to zero, so why not do that explicitly and not leave a bug hiding there? Why are you setting it to such a value (32767) in the first place?

aarg:
Have you considered the possibility of a loose or otherwise faulty connection to the sensor?

Yes I have considered this, however the fact that I can switch between uploading an earlier version of the code and a current one and get consistent readings on the earlier code every time yet readings of 0 each time on the later one leads me to believe that the problem lies in the code and not the connection.

Bonecrusher05:
Yes I have considered this, however the fact that I can switch between uploading an earlier version of the code and a current one and get consistent readings on the earlier code every time yet readings of 0 each time on the later one leads me to believe that the problem lies in the code and not the connection.

So use the earlier code... add changes one at a time until it fails. Then you know the problem!

aarg:
Perhaps, but you are actually setting it to zero, so why not do that explicitly and not leave a bug hiding there? Why are you setting it to such a value (32767) in the first place?

I don't quite follow. It is set to 32768, as on the datasheet for the sensor the "offset flow" is 32768, as seen here: https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/5_Mass_Flow_Meters/Datasheets/Sensirion_Mass_Flow_Meters_SFM3300_Datasheet.pdf

However, I did not write the specifics of this section of the code to get the readings from the sensor, I got it from this guide, but just used the code that involved reading the SFM3300 sensor:

aarg:
So use the earlier code... add changes one at a time until it fails. Then you know the problem!

I tried this and it seemed to work until between 20-40 seconds passed each time, where the value would then, seemingly for no reason, go back to 0 every time. It also seems that I was mistaken to say that the previous code worked, as it also had the problem of dropping to 0 after a certain time had passed, I just hadn't noticed this before as I had not tested it for extended periods of time.

In conclusion, I can now get the code to give consistent results for around 20-40 seconds, before the readings from the sensor drop to 0. It is the same code posted earlier.

If you need to handle numbers larger than an int can hold, use the 'long' type.

But the formula in the PDF looks fishy:

2.3Conversion to Physical ValuesIn order to obtain the measured flowin [slm], the measured valueneeds to be converted usingthe following formula:

I can't post it correctly but it looks like it will yield negative values for measurement values less than the "flow offset"

aarg:
If you need to handle numbers larger than an int can hold, use the ‘long’ type.

I don’t believe this is the problem, as I don’t see any integers in the code that after 20-40 seconds would be too large. I might, however, be mistaken, does it look like there are any values that if changed to “long” would fix the problem?

#include "ArduinoMotorShieldR3.h"
ArduinoMotorShieldR3 md;

#include <avr/pgmspace.h>
#include <Wire.h>
#include <sfm3000wedo.h>


int state = -1;
unsigned long startTime;
unsigned long duration;

SFM3000wedo measflow(64);

int offset = 32768;
int scale = 120;


void setup() {
  Wire.begin();
  delay(500);
  Serial.begin(9600);

  measflow.init();
  Serial.println("Sensor initialized!");
  md.init();

  Serial.print("Enter patient weight: ");
}


void loop() {

    if (Serial.available() > 0) {
      int weight = Serial.parseInt();
      Serial.println(weight);
      
    


  while (weight > 0) {

  
  // for reading SFM3300
  float flowSFM = measflow.getvalue();
  //if (flowSFM > 0) flowSFM = flowSFM + offset;
  if (flowSFM > 0) flowSFM = 0;
  else if (flowSFM < 0) flowSFM = flowSFM - offset;
  flowSFM = flowSFM / scale;
  flowSFM = flowSFM * 16.6666;

  if (flowSFM > 1.00) {
    Serial.println(flowSFM);
    Serial.print(millis());
    Serial.print(",  ");
    delay(100);
  }
  if (flowSFM < 1.00) {
    Serial.println(0.00);
    Serial.print(millis());
    Serial.print(",  ");
    delay(100);
  }

  if ( millis() - startTime >= duration ) {
    // advance to next state
    state++;
    if ( state > 3 ) state = 0;
    startTime = millis();
    switch (state) {
      case 0:
        md.setM1Speed(350);
        duration = 600;
        break;
      case 1:
        md.setM1Speed(0);
        duration = 500;
        break;
      case 2:
        md.setM1Speed(-350);
        duration = 275;
        break;
      case 3:
        md.setM1Speed(0);
        duration = 2000;
        break;
    }
    }
  }
  }
}

Often it is helpful to debug by looking at raw values from the sensor, rather than just looking at processed data that is wrong and trying to guess why it's wrong.

aarg:
Often it is helpful to debug by looking at raw values from the sensor, rather than just looking at processed data that is wrong and trying to guess why it's wrong.

I actually did not consider doing this, thank you I will try that. I also may have found a solution, this project involves a motor, and although it moves slightly without an external 12V battery plugged in, it only works properly when it is plugged in. I was carrying out these tests without the battery plugged in, when I tried it with the battery plugged in, I did not get the issue of the values dropping to 0 after some time had passed. I had not previously considered this and in hindsight, it was a bit of a stupid thing to do, so sorry for taking up your time, and thank you for the help.