detect pulse signal

Dear All, i introduce myself,i'm simone and i'm a fres arduino user :slight_smile:
i would like to have some advices about a project
i need to interface arduino with an external device and read the sate of this device from the signal that i get from a led (between led and arduino board i'm plannig to put an optocoupler 4n25)
there are 3 possible states
-led off
-led blinking (aprox one second on and 1 second off)
-led on
i would like to detect these states and then switch on or of some relays on the arduino relay module
could somebody give me any advice about how could i detect these states (the first and the third are quite easy ;))
thansk a lot in advance
Simone

It's all in the timing. You say the first and third are easy but how long are you going to wait to decide whether it really is solidly on or solidly off or whether it is in the middle of blinking?

Steve

Is this an assignment?

First of all thaks for the reply, about the state change from blinking to solid (using a optocoupler i shoud get a squared wave, on for a second, then off for a second and so on) looking around i’ve found out that PulseIn function could geve me the value in time of the poulse and i was thinking to compare this value, if the timing of the pulse is more than 1500 milliseconds then the state is solid, could it work?
i could store the value in a variable and use it to compare
is it sounding good or am i far from the right path?
thanks for the patience :wink:
simone

if the timing of the pulse is more than 1500 milliseconds then the state is solid, could it work?

The pulseIn() function returns time in microseconds. 1500 milliseconds is 1500000 microseconds. The pulseIn() function times out before that, so you’ll need to supply an additional argument that provides a different timeout period.

The pulseIn() function is also blocking. Nothing else happens while the Arduino is waiting for the pin to change state appropriately.

If the LED is on for long enough, and presumably it is on for a human to detect that it is changing state, you could poll the appropriate pin, and record when it changes state (there’s an example for that). Periodically, you check how long it has been since the pin changed state. If it has been a while, the LED state is steady (off or on remains to be determined). If not, the LED is blinking.

kickflip:
there are 3 possible states
{1} -led off
{2} -led blinking (aprox one second on and 1 second off)
{3} -led on

Writing code to detect the state of the input and to record the value of millis() when it changes is straightforward.

Using that to figure out whether the system is in one of those three states is not so simple.

For example, if at some instant you detect that the the input is LOW how do you know whether that is state {1} or state {2}. It seems obvious to keep checking if the input is low for at least one second. But suppose that, before the second has elapsed, the input is found to be HIGH - does that mean that it is state {2} or in state {3}.

Keeping all that in mind, should you wait long enough for (say) 3 transition periods (6 seconds) without any transitions before declaring that the system is in state {1} or state {3}.

If your system does not change state very frequently that will be a big help for interpreting the signal.

I speak with some experience because I have a device (which I bought) which has a very slow blink rate to indicate a particular state and it is a real PITA having to wait long enough watching it to satisfy myself that it is in that state. If the manufacturer had used a fast blink rate I would only have to glance briefly at the device.

...R

I started coding the OP's project just for the heck of it, and Robin2's right it's not so simple.

This is a really excellent example of how the coding is incidental to understanding the domian. It's up to the "client" to describe how the states are defined: after that the coding's pretty simple.

If it blinks 3 times say, then we're in blink state2; up till then, it's just a sequence of blinks that might be state2 or a load of transitions between 1 & 3.

The very worst case of ambiguity here, is that there might be a case where there are transitions from states 1 to 3 and back again exactly 1 second apart. That would look like state 2, and there would be no way of telling if it was state 2 or a string of state1/3/1/3/1/3/1/3s.

(Unless the blinking state2 isn't actually a state in its own right, but a special case of transitions between 1 and 3, that happen to be 1 second long. It's up to the systems engineer to define all that....)

That there is any such ambiguity here makes the OP's project bad engineering. Each state should be identified simply and uniquely. With two lamps for example it would be simple to identify 4 states 00, 01, 10 & 11, where perhaps 00 could mean the power was off and then 01, 10 & 11 are the 3 operational states. No blinking required. The only ambiguity would be if either or both leds failed, and a post could easily blink them both a few times to indicate they were at least working at power on.

Here's a real life example of bad indicator lights. Our clothes iron has only one lamp. So starting from unplugged, the lamp is off. Plug it in, lamp comes on. It reaches operating temperature, lamp goes off. Cools a little, lamp comes on. So there is no way to tell via the lamp if the iron is off (and thus safe to leave the house) or on and hot and it's good to use but we shouldn't leave. Stupidest indicator I've ever seen.

Wouldn't a bit of debounce code ( IDE - File/examples/digital/debounce ) with the time constants adjusted work?

dougp:
Wouldn't a bit of debounce code ( IDE - File/examples/digital/debounce ) with the time constants adjusted work?

I'm not visualising that as a solution: elaborate a bit perhaps?

dear all, takeiung care of your suggestions i wrote the code below, i'm doing some tests using a button intead of the otocoupler (i'm still waiting to get it...) but it looks working what do you think?

unsigned long previousMillis = 0; // last time update
long interval = 5000; // interval at which to do something (milliseconds)
int buttonPin = 2;
int buttonState = 0;
int a = 0;
int b = 0;


void setup() {
 // put your setup code here, to run once:
Serial.begin(9600);
pinMode(buttonPin, INPUT); // initialize the pushbutton pin as an input:
}

void loop(){
 unsigned long currentMillis = millis();

 

    buttonState = digitalRead(buttonPin); //read state
    delay(300);
    Serial.println(buttonState);
    if ( buttonState ==0) a++; // if state LOW increment coulter by 1
    
    if ( buttonState ==1) b++;// if state HIGH increment coulter by 1
         
    if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;   
      
    if (a==0) Serial.println("it is always low");  
    if (b==0) Serial.println("it is always high");  
    if (a!=0 && b!=0) Serial.println("it's blinking");
    Serial.println("put counter a and b to zero value"); 
    a=0;
    b=0;
     }
     else {
 
 Serial.println(a);
 Serial.println(b);

 
 
 }
 }

Apologies, I didn't read the first post thoroughly enough. After rereading I was going to suggest what you have done, one timer to detect ON, a second timer to detect OFF. If neither is true then the signal is pulsating somewhere between those two states.

I'm not clear on your strategy here, sorry.

The way I read that code, first time into loop() and the button is low, a will increment. With that 300ms delay it will go thru loop() 17 times before the interval test at 5000ms kicks it into the part where it prints out its thoughts. By then, a will have incremented to 17 and will fail the if (a==0) test and not be deemed low always even though it was.

And with that 300ms delay, the pin may have changed low-high-low while you weren't looking, which would mean blinking, not solid on.

And that all said, it's not clear to me from a logic pov (nothing to do with coding) how you would differentiate between fast changes between states 1 and 3, and state 2.

thanks to your suggestion, it’s not so important if i miss some signals during the state change, the device that i need to interface is very sloooow during these changes, so even if for a loop ,when the led from blinking goes to solid, i detect blinking intead of solid is not a problem, the following loop will detect it correctly
but due to this solowness to the state changes i have an other question… sorry, if i would do some multitasking… the perfect result will be that if i detect state LOW for a couple of minutes then i can send a command to the relay board, i cannot use delay otherwise i add a delay to the state control …
adding an other for loop with an other counter could be a good solution or do you have a better advice?
thanks again
simone

In order to have some common ground for discussion follow the links below, especially the first three. Understanding these things will help you climb the learning curve.

pseudocode

several things at the same time

using millis() for timing

useful links

ok, i’ll be back after some reading :wink:
thanks
simone

OK this is a long post and written out of my head. This is how I see it working....

Let's say we start our observation just as the led went low. We don't know anything about what happened before, except that it was obviously high, but we don't know if that high was high in a blink state 2 or high in on state 3. Or perhaps we've just powered up, and it's low. We don't know for how long it's been low, since we we weren't looking outside at the led, so best we can assume is it's newly low.

(The success of any strategy here will, I'm sure, rely on looking for transitions.)

So it's just gone low, and we start the delay()-less clock which zooms us through loop() fast enough not to miss a transition. Let's take the easy case first: after 1000ms it's still low; we know we are in off state 1, and can announce that fact. Up till 1000ms we were in a limbo state of not knowing if we were in the low part of a blink state 2, or the off state 1.

If it goes high at exactly 1000ms (or let's say from a practical pov, between say 995 and 1005 but I'll call it 1000 for simplicity) does that mean we're in a blink though? That depends on the rules: if there is no chance that a state 1 to state 3 transition can occur at 1000ms then yes we can say the new state is blink state 2. If not, then all we know is we're high but not the state. We're in the same limbo we were in with the recently departed low.

So we need to go to the new high with a flag saying "limbo".

If we left the low case before 1000ms what do we know? Only that we were not in blink state 2 since this blink would be too short, so retrospectively we can say that was off state 1, albeit very short, but we have no idea if we are heading to the high of a blink state 2 or the high of on state 3.

To recap: if we leave the low case before 1000ms (in reality before 995) we were in off state 1 but didn't know it until we left. If we leave at 1000ms (995- 1005 or whataver) we are in limbo. If we leave after 1000ms (in reality after 1005) we were in off state 1, and knew it.

Point is we enter the next phase with the limbo flag set if we left at 1000, and otherwise clear. We save that into "prevLimbo".

Then we start the clock in the new high case, and set limbo since right fro the start we don't know what to expect. If it lasts (edit for clarity) exceeds 1000ms that's cool, we are in on state 3. Eventually leave for a low, and clear limbo.

If we leave early, also cool, clear limbo.

If we leave at 1000, that means we can't clear limbo yet (edit, correction) don't clear limbo, and we need to compare it with prevLimbo. If prevLimbo is set, ie we left there at 1000ms we have a potential blink state 2, and we are leaving on 1000 ie current limbo is still set. You need a rule about that: does two successive limbos mean blink state 2? Or do we need an array of prevPrevPrevPrevLimbos to overcome the possibility of coincidental state 1 / state 3 transitions at 1000ms?

Let's assume one generation of limbos is enough. If we came in with prevLimbo set, and leave with (new) limbo set, we know we have blink state 2. Move limbo into prevLimbo for next time (and bump the whole array down if necessary) and start over in the new low.

ps.... I see you posted while I wrote this, not surpirsing since it took me ages, so it may not gel with what you just said. I'm going with your very first post, that you need to know which of 3 states you're in. This lets you know that, except in the first 1000ms of a new low or high, since that's the limbo time.

kickflip:
thanks to your suggestion, it's not so important if i miss some signals during the state change, the device that i need to interface is very sloooow during these changes,

You have not yet told us, and it is an important part of any solution, how long the system stays in each state after a transition.

For example if it flashes once per second and continues doing that for at least 5 minutes it will be a lot easier to be sure of the state compared to the situation where it might change state again after 5 seconds.

...R

Please post a very simple example sketch to illustrate the problem.

aarg:
Please post a very simple example sketch to illustrate the problem.

I think OP's dived into the code too soon as it is. IMO her time would be better spent with a wide sheet of paper, and two horizontal lines representing the led being on and off. Then she can draw transitions with various timings and see under what circumstances she can safely declare she's in this state or that.

I'm keen to see what she makes of my reply #15.

I'll probably do the code for the heck of it. First I would need to mimic her plant with one Uno to high/low a pin to be read by another one, which will then latch on to the states off, blink and on. That may well be Sunday's fun task.

aarg:
Please post a very simple example sketch to illustrate the problem.

To whom is that addressed?

…R