Trying to get a relay to open for set period on an interrupt

I am looking to create a similar arrangement to poppet valves in an internal combustion engine but instead of driving them with a cam shaft I am looking to do it with solenoids. There are many reasons why I shouldn't do it this way but this is how I have chosen to do at this moment.

What I have is a rotating flywheel and a hall effect sensor feeding into an interrupt function to determine the cycle time/frequency. The interrupt function triggers the opening of the relay. So far so good. Where I am having a problem is holding the relay open for the required percentage of each cycle. Operating the flywheel at very low frequency the relay either flicks on and off or alternates on and off with each cycle.

The code is below. I have based it on that found on the web, but I can't remember where from now. Originally I was concerned about bounce from the hall effect sensor but realised this not an issue. The recorded revolutions match the turns of the flywheel. However I thought I could use the bounce period to open the relay. I have altered the code in a number of ways to no avail. I include the code that I have disabled.

One of the lines in the code I don't understand the purpose of, is delayRunning = !delayRunning; which is a volatile bool. As I understand it this will just toggle between false and true each time it is run which appears to defeat the purpose of the code, however when I remove it the relay vibrates as it is turned on and off or doesn't work. I have moved around so many times now I have forgotten where it originally was.

Note that all the print statements are checks to understand what is happening and will be removed once the problem is resolved and the relay open time variable DELAY_TIME will be a little more complex than that shown. The flywheel frequency will be variable and externally controlled.

There may be more appropriate code to do what want and I would be interested in that but I would also like to know where I have gone wrong to improve my understanding of ardunio coding.

#include <millisDelay.h>

volatile unsigned long DELAY_TIME = 0; // 1.5 sec -related to signal bounce delay
volatile unsigned long DELAY_INTERVAL; //1.5 sec -related to signal bounce delay
volatile unsigned long delayStart = 0; // the time the delay started -related to signal bounce delay
volatile bool delayRunning; // true if still waiting for delay to finish -related to signal bounce delay

bool RelayOn = false; // keep track of the led state

volatile unsigned long revStart = 0; // RPM variable
volatile unsigned long revStop; // RPM variable
float RPM =0.00; // RPM output
float Hz =0.00; //Hz output

volatile byte half_revolutions; //-related to signal bounce delay

int RELAY_PIN_1 = 4;  // the Arduino pin, which connects to the IN pin of relay

int interruptPin = 2;  // Hall effect sensor

void setup() {
  
  Serial.begin(9600);
  pinMode(interruptPin, INPUT_PULLUP);
  pinMode(RELAY_PIN_1, OUTPUT);   // initialize the digital pin as an output.
  digitalWrite(RELAY_PIN_1, LOW); // turn led off

  // start delay
  delayStart = millis(); //-related to signal bounce delay
  delayRunning = true;  //-related to signal bounce delay
  

  attachInterrupt(digitalPinToInterrupt(interruptPin), magnet_detect, RISING); //-related to signal bounce delay

}




void checkToggleLed() { // -related to signal bounce delay
  // check if delay has timed out
  if (delayRunning && ((millis() - delayStart) <= DELAY_TIME)) {
    delayRunning = false;
    //delayStart += DELAY_TIME;
    //Serial.println (DELAY_INTERVAL);
    //Serial.println(DELAY_TIME);
    delayRunning = !delayRunning; // this prevents drift in the delays
    }
  else { delayRunning = true;}

    //if(    delayRunning = false;
    
    //if (delayRunning = false ) {digitalWrite(RELAY_PIN_1, HIGH);
    //} else {digitalWrite(RELAY_PIN_1, LOW);}


    //toggle the led
    //RelayOn = !RelayOn;
    //if (RelayOn) {
    //  digitalWrite(RELAY_PIN_1, HIGH); // turn led on
    //} else {
    //digitalWrite(RELAY_PIN_1, LOW); // turn led off
    //}
  
  //if (delayRunning = true) {digitalWrite(RELAY_PIN_1, HIGH);
  //}

}




void loop() {
    
   Serial.print(half_revolutions);
  checkToggleLed(); // call to toggle led based on timer
    Serial.print (", "); Serial.print(delayStart); Serial.print (", ");
    Serial.print(revStop); Serial.print (", "); Serial.print (revStart);


    RPM = (1.00/(revStop-revStart)*1024.00*60.00); // Calculating RPM
    Hz = (1024.00/(revStop-revStart)); // Calculating Hz
    // revStart = revStop; // resetting rev_start value
    Serial.print (", "); Serial.print(RPM); Serial.print (", "); // Printing RPM
    Serial.print(Hz); Serial.print (", "); // Printing Hz

    DELAY_INTERVAL= (revStop-revStart)/4;

    Serial.print (DELAY_INTERVAL); Serial.print (", ");// Printing DELAY_INTERVAL
    Serial.print (DELAY_TIME); Serial.print (", ");
    Serial.print (millis()); Serial.print (", ");



       if (delayRunning == false ) {digitalWrite(RELAY_PIN_1, HIGH); Serial.println ("False");
    } else {digitalWrite(RELAY_PIN_1, LOW); Serial.println ("True");}



  
}

 void magnet_detect() //This function is called whenever a magnet/interrupt is detected by the arduino -related to signal bounce delay
 
    {half_revolutions++;
    //delayRunning = !delayRunning;
    delayStart = millis();
    revStart = revStop;
    revStop = delayStart; // Part of RPM calculation -matches rev count sart with bounce start
    //DELAY_TIME = DELAY_TIME + DELAY_INTERVAL;
    DELAY_TIME = delayStart + DELAY_INTERVAL;
   
 }

look this over
assume the relay is opened 10% of a cycle
ask questions about what you don't understand

const byte PinRelay  = 4;
const byte PinSensor = 2;
enum { Close = LOW, Open = HIGH };

byte sensorLast;

unsigned long msecPeriod;
unsigned long msecPulse;
unsigned long msecLast;
bool state = 0;

float DutyCycle = 0.1;

char s [80];

// -----------------------------------------------------------------------------
int
trig (void)
{
    byte sensor = digitalRead (PinSensor);
    if (sensorLast != sensor)  {
        sensorLast = sensor;
 //     delay (20);             // debounce mechanical switch

        if (HIGH == sensor)
            return 1;
    }

    return 0;
}

// -----------------------------------------------------------------------------
void loop ()
{
    unsigned long msec = millis ();

    if (state && msec - msecLast >= msecPulse)  {
        digitalWrite (PinRelay, Close);
        state = 0;
    }

    if (trig ())  {
        digitalWrite (PinRelay, Open);
        state = 1;

        msecPeriod = msec - msecLast;
        msecPulse  = msecPeriod * DutyCycle;
        msecLast   = msec;

        int rpm =  60L * 1000 / msecPeriod;

        sprintf (s, " %3lu ms, %4d rpm", msecPeriod, rpm);
        Serial.println (s);
    }
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);

    pinMode      (PinRelay, OUTPUT);
    digitalWrite (PinRelay, Close);

    pinMode (PinSensor, INPUT_PULLUP);
    sensorLast = digitalRead (PinSensor);

    Serial.println ("ready");

    // wait for first cycle
    while (! trig ())
        ;
    msecLast = millis ();
    Serial.println ("run");
}

Thanks it works. A few bits of code that I had to look up and bettered my understanding. However I am struggling to understand

int
trig (void)
{

why the int and why is the void in brackets?

int is the return type, 1 or 0 in the case
void means there are no arguments to the function

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