Two programs on arduino

I would really appreciate if somebody can help me. I am new to Arduino and I got stock. I have tried everything but nothing seems to work. I have created program to read RPM sensor and send data to Nextion touch screen. Basically I would like to read 2 RPM sensors and print data on Nextion screen. Each program works fine but if I try to merge them together I am getting error. Here is the code for first program

#include <Nextion.h>


#include <SoftwareSerial.h>





SoftwareSerial nextion(10, 11);// Nextion TX to pin 10 and RX to pin 11 of Arduino

Nextion myNextion(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port @ 9600bps
#define tachPin 3

const byte tachInterrupt = 1; // tach signal on interrupt 1 (digital pin 3)

byte engineCylinders = 2; // for tach calculation (pulses per revolution = 2 * cylinders / cycles)
byte engineCycles = 4; // for tach calculation
int refreshInterval = 500; // milliseconds between sensor updates
unsigned long previousMillis = 0;

volatile int RPMpulses = 0;

void setup()
{
  pinMode(tachPin, INPUT_PULLUP); // enable internal pullup for tach pin
  
  attachInterrupt(tachInterrupt, countRPM, FALLING);
  
  
  myNextion.init();
}

void loop()

{
  if(millis() - previousMillis > refreshInterval)
  {
    previousMillis = millis();
   
    myNextion.setComponentText("t0", String (getRPM()));
     
  }
}

 
// counts tach pulses
void countRPM()
{
  RPMpulses++;
 
}

// checks accumulated tach signal pulses and calculates engine speed
// returns engine speed in RPM
// Resolution: 30000 * engineCycles / refreshInterval / engineCylinders RPM (for default values = 20 RPM)
int getRPM()
{
  int RPM = int(RPMpulses * (30000/ float(refreshInterval)) * engineCycles / engineCylinders / 2.0 ); // calculate RPM
  RPMpulses = 0; // reset pulse count to 0
  RPM = min(9999, RPM); // don't return value larger than 9999
  return RPM;
}

Seconda code is basically the same. I just added digit 1 to all the values. Also second code is reading from diferent sensor. Here is the second code

#include <Nextion.h>


#include <SoftwareSerial.h>





SoftwareSerial nextion(10, 11);// Nextion TX to pin 10 and RX to pin 11 of Arduino
Nextion myNextion1(nextion, 9600); //create a Nextion object named myNextion using the nextion serial port @ 9600bps
#define tachPin 2


const byte tachInterrupt1 = 0; // tach signal on interrupt 1 (digital pin 2)

byte engineCylinders1 = 2; // for tach calculation (pulses per revolution = 2 * cylinders / cycles)
byte engineCycles1 = 4; // for tach calculation
int refreshInterval1 = 750; // milliseconds between sensor updates
unsigned long previousMillis1 = 0;

volatile int RPM1pulses = 0;

void setup()
{
  
  

  
  
  myNextion1.init();
  pinMode(tachInterrupt1, INPUT_PULLUP); // enable internal pullup for tach pin
  
  attachInterrupt(tachInterrupt1, countRPM1, FALLING);
  
  
  myNextion1.init();
}

void loop()

{
  if(millis() - previousMillis1 > refreshInterval1)
  {
    previousMillis1 = millis();
    
 
    myNextion1.setComponentText("t1", String (getRPM1()));
     
  }
}

 
// counts tach pulses
void countRPM1()
{
  
  (RPM1pulses++);
 
}

// checks accumulated tach signal pulses and calculates engine speed
// returns engine speed in RPM
// Resolution: 30000 * engineCycles / refreshInterval / engineCylinders RPM (for default values = 20 RPM)

int getRPM1()
{
  int RPM1 = int(RPM1pulses * (30000/ float(refreshInterval1)) * engineCycles1 / engineCylinders1 / 2.0 ); // calculate RPM
  RPM1pulses = 0; // reset pulse count to 0
  RPM1 = min(9999, RPM1); // don't return value larger than 9999
  return RPM1;
}

What would be the best way to merge this 2 programs together. I would like first program to run first and than second program after first. They don't have to run at the same time. Thank you in advance

1 Like

This Simple Merge Demo may give you some ideas.

...R

  1. You need two separate RPM variables and 2 interrupts - 1 for each motor
  2. You have 1 Nextion device, so only 1 SoftwareSerial communication and Nextion object is needed. However you will need to find a way for SendComponentText to show both RPMs at once
  3. Your getRPM function should take a parameter, so 1 function can work on both RPM variables. It would look like that:
//variables
volatile int RPMpulses = 0;
volatile int RPM1pulses = 0;

//function
int getRPM(int pulses)
{
 //count RPM
}

//calling
int rpm = getRPM(RPMpulses);
int rpm1 = getRPM(RPM1pulses);

Now the problem is that your function also zeroes your RPM pulses, so you will either write a function that takes reference to RPMpulses, or zero it in loop after calling getRPM - however since you call it in setComponentText, which seems lenghty, you might lose some pulses if they come between calculation and text setting - think about a variable holding your RPM to be sent and zeroing pulses before setting text.

1 Like

A while back I did this for a sensor monitoring two fans.

It may work for you, depending on your sensor. You would then merely need to add in the nextion stuff to send the values to the display.

I've tested it with a Hall effect sensor on somewhat slowly rotating fans... let me know if it is of any help:

// CLASS DEFINITION

class FanSpeed {
  
  public:
    void
      setup(uint8_t irq_pin, void (*ISR_callback)(void), int value),
      handleInterrupt(void);
    double
      getSpeed();

  private:
    uint32_t
      _lastMicros = 0UL,
      _interval = 60000000UL;
    void(*ISR_callback)();
};

void FanSpeed::setup(uint8_t irq_pin, void (*ISR_callback)(void), int value)
{
  attachInterrupt(digitalPinToInterrupt(irq_pin), ISR_callback, value);
}

inline void FanSpeed::handleInterrupt(void)
{
  uint32_t nowMicros = micros();
  _interval = nowMicros - _lastMicros;
  _lastMicros = nowMicros;
}

double FanSpeed::getSpeed()
{
  if (micros() - _lastMicros < 1000000UL) // has rotated in the last second
  {
    return 60000000.0 / _interval;
  }
  else
  {
    return 0;
  }   
}

// PROGRAM START

FanSpeed* fan1;
uint8_t fan1pin = 2;
FanSpeed* fan2;
uint8_t fan2pin = 3;

void setup()
{
  Serial.begin(115200);
  pinMode(fan1pin, INPUT_PULLUP);
  pinMode(fan2pin, INPUT_PULLUP);
  fan1 = new FanSpeed();
  fan1-> setup(fan1pin, []{fan1->handleInterrupt();}, FALLING);
  fan2 = new FanSpeed();
  fan2-> setup(fan2pin, []{fan2->handleInterrupt();}, FALLING);
}

void loop()
{
  static uint32_t lastMillis = 0;
  if (millis() - lastMillis > 1000UL)
  {
    Serial.print(F("Fan one speed = ")); Serial.print(floor(fan1->getSpeed() + 0.5), 0);Serial.println(F(" RPM"));
    Serial.print(F("Fan two speed = ")); Serial.print(floor(fan2->getSpeed() + 0.5), 0);Serial.println(F(" RPM"));
    Serial.print('\r');
    lastMillis = millis();
  }
}
1 Like

Thank you guys for your help. BulldogLowell thanks a lot for your program. I tested it and it works more accurately than mine. I added nextion stuff and everything works great. Only problem I have is that my rpm sensors are different from each other so I will have to have diferent math for each sensor. For the first sensor I just changed line
return 60000000.0 / _interval; to

return 30000000.0 / _interval;
and reading is accurate for the first Gauge. For the second I don't know how to change.
Thanks in advance

bovegas:
Thank you guys for your help. BulldogLowell thanks a lot for your program. I tested it and it works more accurately than mine. I added nextion stuff and everything works great. Only problem I have is that my rpm sensors are different from each other so I will have to have diferent math for each sensor. For the first sensor I just changed line
return 60000000.0 / _interval; to

return 30000000.0 / _interval;
and reading is accurate for the first Gauge. For the second I don't know how to change.
Thanks in advance

So we can make that constant settable:

// CLASS DEFINITION

class FanSpeed {
  
  public:
    void 
      setup(uint8_t irq_pin, void (*ISR_callback)(void), int value),
      handleInterrupt(void),
      setConstant(double timeConstant);
    double
      getSpeed();

  private:
    double
      _timeConstant = 60000000.0;
    uint32_t
      _lastMicros = 0UL,
      _interval = 60000000UL;
    void(*ISR_callback)();
};

void FanSpeed::setConstant(double timeConstant)
{
  _timeConstant = timeConstant;
}

void FanSpeed::setup(uint8_t irq_pin, void (*ISR_callback)(void), int value)
{
  attachInterrupt(digitalPinToInterrupt(irq_pin), ISR_callback, value);
}

inline void FanSpeed::handleInterrupt(void)
{
  uint32_t nowMicros = micros();
  _interval = nowMicros - _lastMicros;
  _lastMicros = nowMicros;
}

double FanSpeed::getSpeed()
{
  if (micros() - _lastMicros < 1000000UL) // has rotated in the last second
  {
    return _timeConstant / _interval;
  }
  else
  {
    return 0;
  }   
}

// PROGRAM START

FanSpeed* fan1;
uint8_t fan1pin = 2;
FanSpeed* fan2;
uint8_t fan2pin = 3;

void setup()
{
  Serial.begin(115200);
  pinMode(fan1pin, INPUT_PULLUP);
  pinMode(fan2pin, INPUT_PULLUP);
  fan1 = new FanSpeed();
  fan1->setConstant(30000000.0);
  fan1->setup(fan1pin, []{fan1->handleInterrupt();}, FALLING);
  fan2 = new FanSpeed();
  fan2->setConstant(60000000.0);
  fan2->setup(fan2pin, []{fan2->handleInterrupt();}, FALLING);
}

void loop()
{
  static uint32_t lastMillis = 0;
  if (millis() - lastMillis > 1000UL)
  {
    Serial.print(F("Fan one speed = ")); Serial.print(floor(fan1->getSpeed() + 0.5), 0);Serial.println(F(" RPM"));
    Serial.print(F("Fan two speed = ")); Serial.print(floor(fan2->getSpeed() + 0.5), 0);Serial.println(F(" RPM"));
    Serial.print('\r');
    lastMillis = millis();
  }
}

I hope that helps...

1 Like

BulldogLowell thank you so much for your reply. I was wondering if you could help me with my issue. I was trying to make rpm and speed gauge for my boat, and your program works great except one issue. When I start the boat rpm start reading and I am getting value on my rpm screen but for some reason I am also getting some values on my speed screen even my boat is not moving. When is start to move I am getting correct reading on speed screen. I cant figure out how this signals are interfering. Is this something to do with program or maybe something with signals

So you don't have two RPM sensors? You have a RPM sensor and some kind of speed sensor?

Post your code that you describe and the kind of sensor you have.