Interrupt vs. Delay - who wins?


#21

Reading the SMS is not so bad and you can even create a priority list of senders to which your device responds.


#22

Latching things do indeed open up several other cans of worms when you need to verify their current state make sure they fail safe etc. Many types of latching relays circuits and FETs exist out there you could certainly have fun investigating them.


#23

Going back to @BulldogLowell’s comments, an FSM in loop() is the best way to control your pump. Loop will run every millisecond and with non-blocking delays (using millis()), a properly written FSM will step through the pump activities regardless of interrupts. Your ISR and callbacks need to be written short and non-blocking. If you have any concerns with SMS messages arriving asynchronously, queue them in a buffer (circular or otherwise), set a flag and deal with them synchronously in loop(). :wink:


#24

@Cameron,

I was “nerd sniped” too, thinking about your pump program driving my kids to school…

here is an example of your process using Timers in a class object. You can try it by sending it a “1” via Particle function. your function will return -99 if the process is underway…

Non-blocking and should be pretty accurate as to the dwell times.

have fun with it! :slight_smile: :smile: :laughing:

//#include "Particle.h"

class PumpManager
{
  public:
    PumpManager(const int &_pumpPin, const int &_numCycles, const int &_dwellTime);  // Pump Output Pin, Number of Startup Attempts, Pulse time in milliseconds
    void begin() const;
    bool startPump(void);
    bool isStarting(void) const;
  private:
    Timer* timer;
    enum State{
      PUMP_INACTIVE,
      PUMP_ACTIVE
    };
    State pumpState = PUMP_INACTIVE;
    int numCycles;
    int remainingCycles;
    int pumpPin;
    void callback(void);
};

PumpManager::PumpManager(const int &_pumpPin, const int &_numCycles, const int &_dwellTime)
{
  pumpPin = _pumpPin;
  numCycles = _numCycles;
  timer = new Timer(_dwellTime, &PumpManager::callback, *this);
}

void PumpManager::callback(void)
{
   if(pumpState == PUMP_INACTIVE)
    return;
   if(digitalRead(pumpPin) == LOW)
   {
     digitalWrite(pumpPin, HIGH);
   }
   else
   {
     digitalWrite(pumpPin, LOW);
     remainingCycles--;
   }
   if(!remainingCycles)
   {
     pumpState = PUMP_INACTIVE;
     remainingCycles = numCycles;
     timer->stop();
   }
}

void PumpManager::begin(void) const
{
  pinMode(pumpPin, OUTPUT);
  digitalWrite(pumpPin, LOW);
}

bool PumpManager::startPump(void)
{
  remainingCycles = numCycles;
  digitalWrite(pumpPin, HIGH);
  pumpState = PUMP_ACTIVE;
  timer->reset();
}

bool PumpManager::isStarting(void) const
{
  return (pumpState == PUMP_ACTIVE);
}

/***********************************************/
/*************** Main Program ******************/
/***********************************************/

PumpManager pump1(D7, 3, 1000);  // Pump Output Pin, Number of Startup Attempts, Pulse time in milliseconds

bool isStarting;

void setup(void)
{
  Particle.function("RunPump", runPump);
  Particle.variable("PumpStarting", isStarting);
  pump1.begin();
}

void loop(void)
{
  isStarting = pump1.isStarting();
  // waiting for Sleep Dragons...
  // I'm free, to do what I want, any old time...
}
int runPump(String command)
{
  if(command.toInt() == 1)
  {
    if(pump1.isStarting())
      return -99; // rejected the command
    pump1.startPump();  // otherwise go ahead and start the pump
    return 1;
  }
  return 0;
}

you could easily add functions to allow the setting of your pump times and attempts…

Keywords: Timer class member function callback non-blocking


#25

Thank you! @BulldogLowell & @peekay123 - it is a bit late here, I’m going to try and wrap my head around this tomorrow and start testing. :smiley:

Will let you know how I go!


#26

I must admit, I will have to claim a lack of knowledge here - how does that work? Do you have a link or example that might be able to point me in the right direction? Is that similar to Bulldog’s code above?


#27

@Cameron, perhaps the first question should be how are you handling them now?