EASY, issue with if statement and RPM range

Hello, I have an issue and can't figure out a solution. This is a code that I'm writing for a hybrid system, when the gas engine goes below a given range (545-550) nothing happens until the RPM are lower or equal to 530, in that case I would need the electric motor to run until RPM are back to the lowest value of the range (545) but cant go higher than the second value (550), so it would need to stop spinning the electric motor at 545

N.B. In the final code the 2 values for the range are given by a potentiometer where:
545 = pot_val - 5
550 = pot_val (pot val are obtained trought the map function since the max val can be 550)
530 = pot_val2 (another potentiometer for the RPM value where the electric motor activates)

the variables are these:

Kelly_PWR = relay activating to make electric motor spin
em_led = Emergency LED showing the electric motor is spinning
loosing_rpm_led = LED that shows that RPM are decreasing from 545 to 530

I can't manage to code the part where if RPM <= 530; Kelly_PWR = HIGH until the RPM are back in the 545 - 550 range.
The problem with my code is that it activates the electric motor (Kelly_PWR) only until RPM are = 530 , and when that condition is true, the electric motor turns off without bringing the RPM back to 545 which is what I would need

this is the code:

if (RPM >= 545 && RPM <= 550)  {

  Serial.println("RPM ARE OKAY");
  digitalWrite(kelly_PWR, LOW);
  digitalWrite(em_led, LOW);
  digitalWrite(loosing_rpm_led, LOW);
  Serial.println(soglia1);
  Serial.println(soglia2);
}


else if (RPM <= 530) {


  digitalWrite(kelly_PWR, HIGH);
  delay(100);
  digitalWrite(em_led, HIGH);
  digitalWrite(loosing_rpm_led, LOW);
  delay(100);
    Serial.println(RPM);
    Serial.println("LOW RPM DETECTED, EM. MOTOR ACTIVATION");
    Serial.println(map_pot_value);

}

else {

  Serial.println("\tLOOSING RPM:");
  Serial.println(RPM);

while this one here is the full code:

//Konner Helicopters 
//Konner S.r.l.

// Calibration:


const byte PulsesPerRevolution = 1; //# of pulses per revolution
const unsigned long ZeroTimeout = 500000;  // to work with low RPM higher #   
const byte numReadings = 2; //# of samples per smoothing: HIGHER = SMOOTHER = SLOWER (1: no smoothing / 2: default)
volatile unsigned long LastTimeWeMeasured;
volatile unsigned long PeriodBetweenPulses = ZeroTimeout + 1000;

volatile unsigned long PeriodAverage = ZeroTimeout + 1000;
unsigned long FrequencyRaw;
unsigned long FrequencyReal;
unsigned long RPM;
unsigned int PulseCounter = 1;
unsigned long PeriodSum;
unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;
unsigned long CurrentMicros = micros();
unsigned int AmountOfReadings = 1;
unsigned int ZeroDebouncingExtra;
unsigned long ramp_value;
unsigned long buttonState;
unsigned long readings[numReadings];
unsigned long readIndex;
unsigned long total;
unsigned long average;
int em_led = 13; //emergency led pin
int loosing_rpm_led = 12;
int kelly_PWR = 11; //5v to kelly pin (rele)
int pot = A0; //pot1 MIN VALUE RPM
int pot2 = A1; //pot2 RANGE VALUE RPM to reach 
int BTT = 7; //emulator button for testing








void setup()  // Start of setup:
{

  Serial.begin(9600);  
  attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, RISING);  // Enable interruption pin 2 when going from LOW to HIGH.
  pinMode(kelly_PWR, OUTPUT);
  pinMode(em_led, OUTPUT);
  pinMode(loosing_rpm_led, OUTPUT);
  pinMode(pot, INPUT);
  pinMode(pot2, INPUT);
  pinMode(BTT, INPUT);
    delay(1000);

}  // End of setup.

void loop()  // Start of loop:
{


  LastTimeCycleMeasure = LastTimeWeMeasured;
  CurrentMicros = micros();  // Store the micros() in a variable.

  if (CurrentMicros < LastTimeCycleMeasure)
  {
    LastTimeCycleMeasure = CurrentMicros;
  }

  // Calculate the frequency:
  FrequencyRaw = 10000000000 / PeriodAverage;

  if (PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra)
  {
    FrequencyRaw = 0;
    ZeroDebouncingExtra = 2000;
  }
  else
  {
    ZeroDebouncingExtra = 0;
  }

  FrequencyReal = FrequencyRaw / 10000;  // Get frequency without decimals.

  //Calculate the RPM:  --> !!Must bypass to test with button. Find RPM in "if" statement below
  RPM = FrequencyRaw / PulsesPerRevolution * 60;
  RPM = RPM / 10000;


 // Smoothing RPM:
  total = total - readings[readIndex];
  readings[readIndex] = RPM;
  total = total + readings[readIndex];
  readIndex = readIndex + 1;

  if (readIndex >= numReadings)
  {
    readIndex = 0;
  }

  // Calculate the average:
  average = total / numReadings;


  
// buttonState = digitalRead(BTT);  if (buttonState == LOW) { RPM = 550;} else { RPM= 530; }   //BUTTON RPM SIMULATOR

  Serial.print("Period: ");
  Serial.print(PeriodBetweenPulses);
  Serial.print("\tReadings: ");
  Serial.print(AmountOfReadings);
  Serial.print("\tFrequency: ");
  Serial.print(FrequencyReal);
  Serial.print("\tRPM: ");
  Serial.print(RPM);
  Serial.print("\tTachometer: ");
  Serial.println(average);


int pot_value = analogRead(pot);
int pot_value2 = analogRead(pot2);

int map_pot_value = map(pot_value, 0, 1028, 0, 550); //MIN RPM 
int map_pot_value2 = map(pot_value2, 0, 1028, 250, 540); //RANGE RPM

int soglia1 = map_pot_value2 - 5;
int soglia2 = map_pot_value2;


Serial.println(map_pot_value);
Serial.println(map_pot_value2);
Serial.println(soglia1);
Serial.println(soglia2);
delay(100);

if (RPM >= soglia1 && RPM <= soglia2)  {

  Serial.println("RPM ARE OKAY");
  digitalWrite(kelly_PWR, LOW);
  digitalWrite(em_led, LOW);
  digitalWrite(loosing_rpm_led, LOW);
  Serial.println(soglia1);
  Serial.println(soglia2);
}


else if (RPM <= map_pot_value) {


  digitalWrite(kelly_PWR, HIGH);
  delay(100);
  digitalWrite(em_led, HIGH);
  digitalWrite(loosing_rpm_led, LOW);
  delay(100);
    Serial.println(RPM);
    Serial.println("LOW RPM DETECTED, EM. MOTOR ACTIVATION");
    Serial.println(map_pot_value);

}

else {

  Serial.println("\tLOOSING RPM:");
  Serial.println(RPM);


}


} //voidloop end



void Pulse_Event()  // The interrupt runs this to calculate the period between pulses:
{

  PeriodBetweenPulses = micros() - LastTimeWeMeasured;

  LastTimeWeMeasured = micros();


  if (PulseCounter >= AmountOfReadings)
  {
    PeriodAverage = PeriodSum / AmountOfReadings;
    PulseCounter = 1;
    PeriodSum = PeriodBetweenPulses;

    int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);

    RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);
    AmountOfReadings = RemapedAmountOfReadings;
  }
  else
  {
    PulseCounter++;
    PeriodSum = PeriodSum + PeriodBetweenPulses;
  }
  

}  // End of Pulse_Event.


//Konner s.r.l  -- Hybrid Fligh Assistant H.F.A.

It looks like you are missing a test and actions for when RPM is greater than 530 and less than 545

1 Like

in that case the third "else" should activate saying that RPM are lowering, which is okay if we are loosing rpm and going from 545 -> 530, but not okay if viceversa, IDK how to write that part of the code i definetly need some help

You can determine whether the RPM is falling by comparing successive readings. If the latest reading is less than the previous one then the RPM is falling

yes exactly Bob that's what I thought I should implement in the code too, but I'm new to coding and have no idea how to compare a previous value and the current one

how about this:

if (RPM <= 530) {

	KELLY = ON

}

else if (RPM >= 545) {

	KELLY = OFF

}

else {

	Serial.println("\tCheck RPM")
	Serial.println(RPM)

}

its easier but it should work okay activating the electric motor if RPM <= 530 and shutting it off once RPM >= 545 (KELLY =ON/OFF are not correct sintax, but it helps me visualize things quicker)

Before you take a reading save the previous value to a variable. After taking the reading you have the two values to compare

could you write a brief code for that if you have 5 min so i can learn from it? im not sure how to do that

An example

const byte potPin = A7;
int previousPotValue;
int currentPotValue;
const byte deadBand = 50; //ignore small changes

void setup()
{
  Serial.begin(115200);
  pinMode(potPin, INPUT);
  previousPotValue = analogRead(potPin);  //set initial values
  currentPotValue = analogRead(potPin);
}

void loop()
{
  previousPotValue = currentPotValue; //save the old value
  currentPotValue = analogRead(potPin); //get the new value
  if (currentPotValue - previousPotValue > deadBand)
  {
    Serial.println("rising");
  }
  else if (previousPotValue - currentPotValue >= deadBand)
  {
    Serial.println("falling");
  }
  delay(100);
}

NOTE:

  • the deadBand value sets how much change is significant
  • the delay() is not the best way to set the time between readings

might need some help, still doesnt work :frowning:


const byte PulsesPerRevolution = 1; //# of pulses per revolution
const unsigned long ZeroTimeout = 500000;  // to work with low RPM higher #   
const byte numReadings = 2; //# of samples per smoothing: HIGHER = SMOOTHER = SLOWER (1: no smoothing / 2: default)
volatile unsigned long LastTimeWeMeasured;
volatile unsigned long PeriodBetweenPulses = ZeroTimeout + 1000;

volatile unsigned long PeriodAverage = ZeroTimeout + 1000;
unsigned long FrequencyRaw;
unsigned long FrequencyReal;
unsigned long RPM;
unsigned int PulseCounter = 1;
unsigned long PeriodSum;
unsigned long LastTimeCycleMeasure = LastTimeWeMeasured;
unsigned long CurrentMicros = micros();
unsigned int AmountOfReadings = 1;
unsigned int ZeroDebouncingExtra;
unsigned long ramp_value;
unsigned long buttonState;
unsigned long readings[numReadings];
unsigned long readIndex;
unsigned long total;
unsigned long average;
int em_led = 13; //emergency led pin
int loosing_rpm_led = 12;
int kelly_PWR = 11; //5v to kelly pin (rele)
int pot = A0; //pot1 MIN VALUE RPM
int pot2 = A1; //pot2 RANGE VALUE RPM to reach 
int BTT = 7; //emulator button for testing
int pot3 = A3;
int previousRPMValue;
int currentRPMValue;
const byte deadBand = 50; //ignore small changes









void setup()  // Start of setup:
{

  Serial.begin(9600);  
  attachInterrupt(digitalPinToInterrupt(2), Pulse_Event, RISING);  // Enable interruption pin 2 when going from LOW to HIGH.
  pinMode(kelly_PWR, OUTPUT);
  pinMode(em_led, OUTPUT);
  pinMode(loosing_rpm_led, OUTPUT);
  pinMode(pot, INPUT);
  pinMode(pot2, INPUT);
  pinMode(pot3, INPUT);
  pinMode(BTT, INPUT);
    delay(1000);

}  // End of setup.

void loop()  // Start of loop:
{


  LastTimeCycleMeasure = LastTimeWeMeasured;
  CurrentMicros = micros();  // Store the micros() in a variable.

  if (CurrentMicros < LastTimeCycleMeasure)
  {
    LastTimeCycleMeasure = CurrentMicros;
  }

  // Calculate the frequency:
  FrequencyRaw = 10000000000 / PeriodAverage;

  if (PeriodBetweenPulses > ZeroTimeout - ZeroDebouncingExtra || CurrentMicros - LastTimeCycleMeasure > ZeroTimeout - ZeroDebouncingExtra)
  {
    FrequencyRaw = 0;
    ZeroDebouncingExtra = 2000;
  }
  else
  {
    ZeroDebouncingExtra = 0;
  }

  FrequencyReal = FrequencyRaw / 10000;  // Get frequency without decimals.

  //Calculate the RPM:  --> !!Must bypass to test with button. Find RPM in "if" statement below
  /*RPM = FrequencyRaw / PulsesPerRevolution * 60;
  RPM = RPM / 10000;


 // Smoothing RPM:
  total = total - readings[readIndex];
  readings[readIndex] = RPM;
  total = total + readings[readIndex];
  readIndex = readIndex + 1;

  if (readIndex >= numReadings)
  {
    readIndex = 0;
  }

  // Calculate the average:
  average = total / numReadings;

*/
  
// buttonState = digitalRead(BTT);  if (buttonState == LOW) { RPM = 550;} else { RPM= 530; }   //BUTTON RPM SIMULATOR

int pot_value3 = analogRead(pot3);
int RPM = map(pot_value3, 0, 1023, 0, 550);


  /*Serial.print("Period: ");
  Serial.print(PeriodBetweenPulses);
  Serial.print("\tReadings: ");
  Serial.print(AmountOfReadings);
  Serial.print("\tFrequency: ");
  Serial.print(FrequencyReal);*/
  Serial.print("\tRPM: ");
  Serial.print(RPM);
  /*Serial.print("\tTachometer: ");
  Serial.println(average);
*/

int pot_value = analogRead(pot);
int pot_value2 = analogRead(pot2);


int map_pot_value = map(pot_value, 0, 1023, 0, 550); //MIN RPM 
int map_pot_value2 = map(pot_value2, 0, 1023, 0, 550); //RANGE RPM

currentRPMValue = RPM; //get the new value
 previousRPMValue = currentRPMValue; //save the old value





if (RPM <= 330) { //map_pot_value

  digitalWrite(em_led, HIGH);
  digitalWrite(kelly_PWR, HIGH);
   Serial.println("\t    - HYBRID ON, LOW RPM");

  
  }
 



else if (RPM >= 500) { //map_pot_value2

  digitalWrite(em_led, LOW);
    digitalWrite(kelly_PWR, LOW);
   Serial.println("\t    - HYBRID OFF, RPM OKAY");

}

else {
 
  if (currentRPMValue - previousRPMValue > deadBand)
  {
    Serial.println("rising");
  }
  
  else if (previousRPMValue - currentRPMValue >= deadBand)
  {
    Serial.println("falling");
  }
  delay(100);
  
}




}//voidloop end



void Pulse_Event()  // The interrupt runs this to calculate the period between pulses:
{

  PeriodBetweenPulses = micros() - LastTimeWeMeasured;

  LastTimeWeMeasured = micros();


  if (PulseCounter >= AmountOfReadings)
  {
    PeriodAverage = PeriodSum / AmountOfReadings;
    PulseCounter = 1;
    PeriodSum = PeriodBetweenPulses;

    int RemapedAmountOfReadings = map(PeriodBetweenPulses, 40000, 5000, 1, 10);

    RemapedAmountOfReadings = constrain(RemapedAmountOfReadings, 1, 10);
    AmountOfReadings = RemapedAmountOfReadings;
  }
  else
  {
    PulseCounter++;
    PeriodSum = PeriodSum + PeriodBetweenPulses;
  }
  

} 

Not helpful.
Describe what it does.

the code runs normal

if RPM >= 545 kelly_pwr is low
if RPM <= 530 kelly_pwr is high

if RPM are between 530 and 545 it just displays rpm without saying rising or falling

Aren't these the wrong way round?

  currentRPMValue = RPM; //get the new value
  previousRPMValue = currentRPMValue; //save the old value

are they?

Well that order guarantees that current and previous will always be the same, hence no rising or falling messages.

thats why it wasn't working, I'll try changing order, thanks

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