compatibility of IR sensor (RPM), and HX711 (load cell)?

Hello I need to measure the RPM of a motor and at the same time the weight of a certain object.

To achieve this I have connected to an Arduino Uno two sensors:

  • an HW201 IR sensor (for RPM)
  • an HX711 with a load cell (for weight)

In the following code I'm calculating the RPM counting every 5 seconds "how many n times the IR is interrupted" and performing (n*12=RPM). I'm doing a serial communication with my pc once every 0.09 seconds.

#include "HX711.h"

HX711 scale(3, 4);

float calibration_factor = 4620; // this calibration factor is adjusted according to my load cell //
float units;
float ounces;

int output;
int RPM;

long Time0_1 = 0;
int sec0_1 = 1;

long lastTime = 0;
long fivesec = 0;
int minute = 0;
int oldOut = 1;

#define RPMpin 8
int newRPM = 0;
int lastRPM;
int n = 0;



void setup() {
  Serial.begin(9600);
  pinMode(8,INPUT);

  scale.set_scale();
  scale.tare();  //Reset the scale to 0

  long zero_factor = scale.read_average(); //Get a baseline reading
}


void loop() {


      if(sec0_1 == 1) {     //need to count for 0.1 seconds.
        Time0_1 = millis();
        sec0_1 = 0;         //pick a checkpoint for millis once every 0.1 seconds.
      }


    //RPM:
        if(fivesec == 1) {
          lastTime = millis();           //read this once
          fivesec = 0;                   //enter this once every 5 seconds.
        }
    
        output = digitalRead(RPMpin);
                      
            if(output != oldOut) {
                oldOut = output;
          
                    if(output == 0) {
                    n++;
                    Serial.print("n: "); Serial.println(n);
                    }
              }

             if(millis()-lastTime > 5000) {   //Calculating the RPM every 5 seconds.
                fivesec = 1;      //start entering fivesec IF statement again
                RPM = n*12;
                n = 0;            //restart to count RPM.
                Serial.print("RPM: "); Serial.println(RPM);
                }



  //WEIGHT:
  scale.set_scale(calibration_factor); //Adjust to this calibration factor
  units = scale.get_units(), 10;
  if (units < 0)
  {
    units = 0.00;
  }
  ounces = units * 0.035274;  

    if(millis()-Time0_1 >= 90) {    //Send data every 0.09 seconds
      //Serial.print(RPM);Serial.print(",");Serial.println(units);
      sec0_1 = 1;
    }
  
}

The code works fine, but when I'm connecting the DT and SCK pin of HX711 to pin 3 and 4 of Arduino, the RPM counter (pin 8 ) will start to perform non accurately and to count not properly the interruption of IR (it will count many less interruptions); so that i won't get the exact value of the RPM.

Notice that the code itself it's working fine until I connect the DT and SCK.
I really cannot understand why.
How can I troubleshoot this? Thank You

What does the code do if You drop the RPM part and look only ay the weight result?

Railroader:
What does the code do if You drop the RPM part and look only ay the weight result?

At the end of the code I excluded the part where I Serial.print the data every 0.09 seconds, to only focus on "the RPM part".
I've done this because if I print the values of HX711/loadcell it perform normally (i see the values once every 0.09 seconds), of course DT and SCK must be connected. What is performing poorly is the RPM part (the IR sensor reads correctly, i've also seen in a scope the HIGH - LOW state everytime the IR is blocked).
What is not independent, I think, is that the digitalRead( 8 ) is dependent from DT and SCK. It can detect the blocking of the IR correctly only if I perform it very slow (once every seconds). If I try to block the IR, let's say 7 times in one second, it will detect only one block of the IR.

Excluding a Serial.print is not what I thought of. Uncomment the access to the weight library, eventually disconnect the 2 wires. Does RPM work then?

units = scale.get_units(), 10;

This syntax is not correct for .get_units(). I believe that with the comma operator units will always read 10.
What are you trying to do here?

scale.set_scale(calibration_factor);

Why is this in loop() instead of setup?

My best guess on the fundamental problem is that the HX711 reading is slow, and is blocking the IR pin reading. The read() function has a line about waiting for scale.ready(). Ready is achieved when the DT pin which is set for INPUT_PULLUP mode by the code is pulled low by the scale.

It's not clear to me why that isn't happening in your case.

There is a fork from the library which has a non blocking read function.

There is an example called HX711_non_blocking which uses an if (scale.ready()) instead of a while( !scale.ready()) function.

Railroader:
Excluding a Serial.print is not what I thought of. Uncomment the access to the weight library, eventually disconnect the 2 wires. Does RPM work then?

Yes as soon as I disconnect both DT and SCK wires, the RPM works flawless, as it should be.

cattledog:
This syntax is not correct for .get_units(). I believe that with the comma operator units will always read 10.
What are you trying to do here?

I really don't know because here I just copied the code, I saw that it worked and I moved on.
I've found that there are different types of HX711 libraries, so my major concern here is that since I've included this library that I'm using right now for this code, it happened that when I added a different HX711 library from the current one, the IDE gave me back several generic errors such as: "this function123 is already included in another HX711 library...". So i would need another PC to experiment with this.

Anyway since you told me non blocking, you gave me a hint! I've put the set_scale in void setup(), and in void loop I've put the entire reading process of HX711 inside the Serial.print (that I perform once every 0.09s). In this case, I think, I'm non blocking the digital.Read( 8 ) process for the RPM. And now the IR sensor is working well.
This is just the last part of the code that I modified:

  //WEIGHT:

    if(millis()-Time0_1 >= 90) {
             //  scale.set_scale(calibration_factor); //moved to void setup()
              units = scale.get_units(), 10;
        
            if (units < 0){
              units = 0.00;
            }
            
        ounces = units * 0.035274;
      //Serial.print(RPM);Serial.print(",");Serial.println(units);
      sec0_1 = 1;
    }

  
}

This is a temporary solution but at least the IR is working well also with very fast movements, that are detected correctly by digital.Read( 8 ).

Can I improve this in some way? Maybe can I add a function that perform this in the HX711.cpp?
Anyway Thanks

In loop, make one call to RPM handler and one call to weight handler. How often You do any reading is coded inside each handler.
Clean up the mess regarding the libraries. I don't quite understand the sutuation but surely another helper do.

Yeah your code is too messy, create separate functions for your sensors and simply call them in your main function, that way code will be clear, thus easy to understand & debug. Moreover, try this Arduino UNO Proteus Library and simulate your code in software, instead of working on hardware directly.

//units = scale.get_units(), 10;
units = scale.get_units();

No matter how you arrange this, you will not be polling the rpm sensor while you are reading the scale. If the reading takes longer than the time between pulses, you will miss it.

What is the rpm? What is the value of n used in the 5 second reading?

You can not use interrupts for the rpm count because the HX711 library disables interrupts during the scale reading. You might be able to queue one interrupt on the ir sensor while they are suspended for the scale reading.

cattledog:

//units = scale.get_units(), 10;

units = scale.get_units();




No matter how you arrange this, you will not be polling the rpm sensor while you are reading the scale. If the reading takes longer than the time between pulses, you will miss it.

What is the rpm? What is the value of n used in the 5 second reading?

I didn't thought that. So i measured with micros() the TimeLost (cumulative in 5 seconds) while I'm reading the value with the HX711, and it's giving me a result of 55000 roughly, so it's 55ms on average. I tried to delete the HX711 part from the if statement and it gives me back 200 microseconds lost on average in 5 seconds..
I usually reach an RPM that goes from 1000 to 4000.
Let's say Arduino shows me a value of 2400. If I take in consideration the total time lost in the reading process of HX711 i would lost the 55/5000 = 0.011 = 1.1%. So can I correct the observed value with this total time wasted (assuming a constant RPM, that is my case fortunately).
So I'm currently calculating RPM every 5 seconds in this way: RPMobs = nobs12 (n is the time that IR is blocked).
I would correct the observed value in this way: ncorr = nobs + nobs(TimeLost/fivesec)... and then
RPMcorr = ncorr
12. So if I detect an RPM of 2400 in reality I should have 2426.4 RPM..
Can this be correct?

Once I will have the hardware in front of me I will make a try with a Arduino with just RPM code and this last one to see if I encounter differences between these two.

cattledog:
You might be able to queue one interrupt on the ir sensor while they are suspended for the scale reading.

I didn't understand this...

Make one capture of the RPM, the time between 2 pulses. After this You make a weight reading.
Or You can make a few RPM measurements, then a weight reading.

I usually reach an RPM that goes from 1000 to 4000.
Let's say Arduino shows me a value of 2400.

2400 rpm is 40 rev/sec or 25 ms between pulses. If the scale reading takes more than this amount of time you can miss pulses.

Hello I need to measure the RPM of a motor and at the same time the weight of a certain object.

Is this some sort of dynamometer where you need a close correlation between the scale and the rpm? Or are the two measurements independent?

How fast does the rpm vary?

I think that reading the scale and the rpm sequentially and independently may be your best approach.

cattledog:
Is this some sort of dynamometer where you need a close correlation between the scale and the rpm? Or are the two measurements independent?

How fast does the rpm vary?

I think that reading the scale and the rpm sequentially and independently may be your best approach.

Q1) Yes it's a dyno! I tried the code with the last correction with a mini 3-6V DC motor and the RPM reading is pretty constant: the deviation from the mean is about (-12V,12V) that is acceptable if we keep in mind that for every IR detection (pulse) it counts +12 RPM.
My problem here is that I'm doing a serial communication with python (need to store data and analyze it) with 2 Arduino uno already (one for voltage and current, and another one for torque and rpm). Python is not very good at serial communication with Arduino (based on my feeling, and what google says), so adding a third Arduino will complicate the communication even more.
Q2) The motor is Handmade so has not the same stability of the RPM of an industrial motor. Anyway I've ordered a digital tachometer and I will test with it, as soon as I receive the product and do the comparison.
If it's not a reliable and concrete solution I'll change this approach.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.