Consistent output with arduino
Moderators: adafruit_support_bill, adafruit

Consistent output with arduino

by maceide on Wed Feb 27, 2013 4:35 pm

Hi guys!

I have a little project that i could use some help with. I am quite new to the arduino, and not that steady in the code, but im hoping on getting there!

The project im building is a litte controller that drives a relay output. The controller is connected to a photo-cell that has a two pin output. This output is shorted at various times depending on the movement in front of the photocell.
What i need is for the arduino to close the relay for the same period (say 0,5s) each time the photocell circut is closed. And maybe block a repeating signal from the photocell within 0,5s

Is this possible in some way?

Any help much appreciated!
maceide
 
Posts: 6
Joined: Wed Feb 27, 2013 4:26 pm

Re: Consistent output with arduino

by adafruit_support_bill on Wed Feb 27, 2013 6:14 pm

Yes, this should be fairly straightforward to do. The simplest way to time something like a 0.5s closure for a relay is with the 'delay()' function. http://arduino.cc/en/Reference/delay

Blocking a repeating signal can be done with a further delay (just don't read the photocell for another 0.5s). Or you can use the 'millis()' function to remember the last closure time and base your logic on that. http://arduino.cc/en/Reference/Millis
User avatar
adafruit_support_bill
 
Posts: 30685
Joined: Sat Feb 07, 2009 10:11 am

Re: Consistent output with arduino

by maceide on Sun Mar 03, 2013 9:30 am

Ok, here is what I have come up with so far;
Code: Select all | TOGGLE FULL SIZE
const int cellPin = 12; //
const int outPin = 2; //
const int ledPin = 13;

int passeringState = 0;
unsigned long Timer;

void setup()
{
pinMode(cellPin, INPUT); //
pinMode(outPin, OUTPUT); //
pinMode(ledPin, OUTPUT);
}

void loop()
{
passeringState = digitalRead(cellPin);

if (passeringState == HIGH) {
Timer = millis();
sendSignal();
}
if (millis()-Timer >= 500UL) {
digitalWrite(outPin, LOW);
digitalWrite(ledPin, LOW);
}
}

void sendSignal() {
digitalWrite(outPin, HIGH);
digitalWrite(ledPin, HIGH);

}


This works OK, but i want it to send only 0,5sec pulse even if the input signal lasts more than 0,5sec, say 2sec fx. Is that somehow possible?
maceide
 
Posts: 6
Joined: Wed Feb 27, 2013 4:26 pm

Re: Consistent output with arduino

by adafruit_support_bill on Sun Mar 03, 2013 10:31 am

Well, you do know the time that the signal went high. You can prevent the start of another pulse for at least 2 seconds. But is that what you really want?

You are getting into a tricky area where you need to precisely specify what the requirements are. Do you want to hold off for at least 2 seconds? What do you do if the signal is still high? Do you want to wait until the signal goes low again before allowing another pulse to be started? Once you clearly define the requirements, the code should be fairly straightforward.
User avatar
adafruit_support_bill
 
Posts: 30685
Joined: Sat Feb 07, 2009 10:11 am

Re: Consistent output with arduino

by maceide on Sun Mar 03, 2013 10:49 am

Sorry for beeing a bit waig in the description.
What I want is for the unit two output a 0,5 sec puls even if the photocell i blocked (constant high signal).
A new pulse can cot start until the signal has gone low again.

Is that somehow a better description?
maceide
 
Posts: 6
Joined: Wed Feb 27, 2013 4:26 pm

Re: Consistent output with arduino

by adafruit_support_bill on Sun Mar 03, 2013 11:08 am

That is better. If you add the following to the beginning of your loop, it will not send a pulse unless it sees a LOW-to-HIGH transition.

Code: Select all | TOGGLE FULL SIZE
while (digitalRead(cellPin) == HIGH)
{
  // wait for signal to go low
}
User avatar
adafruit_support_bill
 
Posts: 30685
Joined: Sat Feb 07, 2009 10:11 am

Re: Consistent output with arduino

by maceide on Sun Mar 03, 2013 11:18 am

Thanks for your rapid response!

I added your line tho the code like this;
Code: Select all | TOGGLE FULL SIZE
const int cellPin = 12; //
const int outPin = 2; //
const int ledPin = 13;

int passeringState = 0;
unsigned long Timer;

void setup()
{
pinMode(cellPin, INPUT); //
pinMode(outPin, OUTPUT); //
pinMode(ledPin, OUTPUT);
}

void loop()
{
passeringState = digitalRead(cellPin);

while (digitalRead(cellPin) == HIGH)
{}

if (passeringState == HIGH) {
Timer = millis();
sendSignal();
}
if (millis()-Timer >= 500UL) {
digitalWrite(outPin, LOW);
digitalWrite(ledPin, LOW);
}
}

void sendSignal() {
digitalWrite(outPin, HIGH);
digitalWrite(ledPin, HIGH);

}


But there is no difference.. The output stays HIGH as long as the input signal stays HIGH.
Did I misunderstand something?
Last edited by maceide on Sun Mar 03, 2013 11:59 am, edited 1 time in total.
maceide
 
Posts: 6
Joined: Wed Feb 27, 2013 4:26 pm

Re: Consistent output with arduino

by adafruit_support_bill on Sun Mar 03, 2013 11:51 am

You don't need the "else" clause. Just turn the pulse off after the delay.
User avatar
adafruit_support_bill
 
Posts: 30685
Joined: Sat Feb 07, 2009 10:11 am

Re: Consistent output with arduino

by maceide on Sun Mar 03, 2013 12:04 pm

I just realised that I had posted the wrong version of the code in my last post.
Its now edited and the correct version is there.

The signal output now stays on (high) as long as the singal input is HIGH

There output signal should go low at given time (say 0,5sec) even if the input signal stays high.

Another feature that would be nice is to be able to say that the input signal has to last at given time (say 0,1sec) for it to send the output signal.

Is that somehow possible?
maceide
 
Posts: 6
Joined: Wed Feb 27, 2013 4:26 pm

Re: Consistent output with arduino

by tldr on Sun Mar 03, 2013 1:36 pm

i would suggest a simple state machine. what follows is clearly not c++, but state machines are pretty easy to code with switch/case statements. just remember to use break statements when appropriate. you can place one at the end of the code for each state, but in the state machine below it would be okay to not use one between the on and high states. it's also important to remember to set the initial state.

Code: Select all | TOGGLE FULL SIZE
state on :
   if elapsed time >= 500ms
    led off
    state = high

state high :
  if input == low
    state = low

state low :
  if input == high
    record time
    state = pending

state pending :
  if input == high
    if elapsed time > 100ms
      record time
      led on
      state = on
  else
    state = low
Last edited by tldr on Sun Mar 03, 2013 1:41 pm, edited 1 time in total.
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: Consistent output with arduino

by maceide on Sun Mar 03, 2013 1:40 pm

Hey, that looks great!
But how do I implement this into my current code?
maceide
 
Posts: 6
Joined: Wed Feb 27, 2013 4:26 pm

Re: Consistent output with arduino

by tldr on Sun Mar 03, 2013 2:27 pm

maceide wrote:Hey, that looks great!
But how do I implement this into my current code?


you don't. this is sort of a different approach. your loop routine will become home to a switch statement. an easy way to assign values to state names is the c enum statement. f'rintsance...

Code: Select all | TOGGLE FULL SIZE
 enum state {on, high, low, pending}


will declare an integer variable state with 4 possible values.

Code: Select all | TOGGLE FULL SIZE
void loop (void) {
  switch {
    case on :
      if (millis() > expiration) {
        sendSignal (LOW);
        state = high;
      }
      break;
    case high :
      if (!digitalRead(cellPin)) {
        state = low;
      }
      break;
    case low :
      if (digitalRead(cellPin)) {
        expiration = millis() + 100;
        state = pending;
      }
      break;
    case pending :
      if (digitalRead(cellPin)) {
        if (millis() > expiration) {
          expiration = millis() + 500;
          sendSignal (HIGH);
          state = on;
        }
      }
      else {
        state = low;
      }
      break;
    default :
      // oh, no!  something has gone terribly wrong
  }
}       


that might work. needs a slight modification to sendSignal, a declaration for expiration and an initialization of state in setup.
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: Consistent output with arduino

by tldr on Sun Mar 03, 2013 4:25 pm

this is me apologizing for some typos and omissions.

Code: Select all | TOGGLE FULL SIZE
const int cellPin = 12; //
const int outPin = 2; //
const int ledPin = 13;

unsigned long expiration;
enum {on, high, low, pending} state;

void setup()
{
pinMode(cellPin, INPUT); //
pinMode(outPin, OUTPUT); //
pinMode(ledPin, OUTPUT);
state = low;
}


void sendSignal(int value) {
digitalWrite(outPin, value);
digitalWrite(ledPin, value);

}

void loop (void) {
      switch (state) {
        case on :
          if (millis() > expiration) {
            sendSignal (LOW);
            state = high;
          }
          break;
        case high :
          if (!digitalRead(cellPin)) {
            state = low;
          }
          break;
        case low :
          if (digitalRead(cellPin)) {
            expiration = millis() + 100;
            state = pending;
          }
          break;
        case pending :
          if (digitalRead(cellPin)) {
            if (millis() > expiration) {
              expiration = millis() + 500;
              sendSignal (HIGH);
              state = on;
            }
          }
          else {
            state = low;
          }
          break;
        default :
          break;
          // oh, no!  something has gone terribly wrong
      }
    }       
"If I had known it was harmless, I would have killed it myself." - Phillip K. Dick, A Scanner Darkly
User avatar
tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am