Sleep mode magnetic switch wake (Electron)


#1

Hello Particle community!

I’ve connected a magnetic switch (DC120) to my electron with one wire in 3v3 and the other in D3, and run the code:

void setup()
{
	pinMode(D3, INPUT_PULLDOWN);
	pinMode(D4, OUTPUT);
	digitalWrite(D4, LOW);

   attachInterrupt(sensor, alerter, FALLING);
}

void loop()
{
	if(alert == TRUE){
		digitalWrite(led, HIGH);
		alert = FALSE;
		delay(5000);
	}
	else digitalWrite(led, LOW);
}

void alerter(){
    alert = TRUE;
}

Which works like a charm.

HOWEVER… When I use the function:
Particle.sleep(D3, FALLING);
instead of the attatchInterrupt, nothing happens. It doesn’t wake at all.

It feels like I’m missing something very basic, but I don’t know what.

Help?

Thanks in advance,
Michael


#2

If I understand correctly, you are calling the sleep function in the setup()?

Try calling it in the loop like so:

void setup()
{
	pinMode(D3, INPUT_PULLDOWN);
	pinMode(D4, OUTPUT);
	digitalWrite(D4, LOW);
}

void loop()
{
	Particle.sleep(D3, FALLING); //sleep until switch output goes high->low
	digitalWrite(led, HIGH);
	delay(5000);
	digitalWrite(led, LOW);
}


#3

No i’m running the function in the loop like you did:

void setup()
{
	pinMode(D1, INPUT_PULLDOWN);
	pinMode(D4, OUTPUT);
	digitalWrite(D4, LOW);
}

void loop()
{
	System.sleep(D1, FALLING);
	digitalWrite(D4, HIGH);
	delay(5000);
	digitalWrite(D4, LOW);
}

As i was experimenting, i figured out that measuring with a multimeter at the same time as triggering the magnet switch somehow made it work. :face_with_raised_eyebrow:

I have no idea why that is, i don’t really understand the electronics behind it… But apparently a 10m Ohm resistor between the 3v3 and D1 input makes it work as intended, as the multimeter datasheet states that the norminal input impedence is about 10m Ohm.

I don’t really have a 10m Ohm resistor lying around, but an explanation would be nice :smiley:


#4

Try

pinMode(D1, INPUT_PULLUP);

and

System.sleep(D1, RISING);

I cant find a lot of the DC120 but it looks like its a normally closed switch.
I think pullup works better in this case.


#5

With the new code, it doesn’t respond at all.

When I measure with a multimeter it reads 0.3 volts when magnets are apart, I don’t know if that is enough to be registered as a HIGH in the input?

I’m gonna try another magnet switch and return with the results.


#6

Are you using the correct wires? It should have 4 wires. 2 wires should be a loop (test for continuity with your DMM). The other 2 should be the switch which should be open (so not continuous) when the magnet is not close. When the magnet is in place it should be continuous. These 2 wires are the ones you should be using.


#7

Particle.sleep(pin, ...) does overrule the pinMode() you set in setup(). When using FALLING you’ll have a pull-up resistor applied and for RISING you get a pull-down.
You need to have your wiring set up accordingly.

If you can’t do with that implicit behaviour, you could go for a CHANGE interrupt (which won’t apply any internall pull-resistors) and add your own external 10k.

I’m not sure when this will change, but there is a long standing proposal to provide an overload for the sleep functions to explicitly select the desired pull-resistors or to prevent the implicit application of pull-resistors to keep the mode set prior Particle.sleep()


#8

The new magnet switch gives the exact same reaction as the first on the electron.

Yes there is the supervisor loop wires and the alarm wires, and I use the alarm wires.
I have one wire in the 3v3 and the other in D1 as input and run with the code

void setup()
{
	pinMode(D4, OUTPUT);
	digitalWrite(D4, LOW);
}

void loop()
{
	System.sleep(D1, RISING);
	digitalWrite(D4, HIGH);
	delay(5000);
	digitalWrite(D4, LOW);
}

This appears to be somewhat working, very unstable though waking sometimes with the slightest vibration (magnets still touching) and sometimes not waking until i move the magnets back together :confused:

If i use the CHANGE interrupt, where would i connect the 10k resistor?


#9

That depends on your demand from either 3v3 or GND to D1 - but obviously opposite to the level your switch is closing to.
You need the pull-resistor to supply the logic level while the switch is open to contrast level the closed switch produces.

How long are your wires?


#10

Wires are 2.5 meters long.


#11

2.5 meters is a good antenna :wink:

You may want to add some decoupling caps and reduce the pull-resistor to 4k7.
Using a twisted-pair cable with extra shielding might also be a good idea.


#12

No matter what I do right now it doesn’t work as intended… :sweat_smile:

You’ve given me some good info, and I’m determined to try until it works perfectly!

For now, using CHANGE as wake trigger on D1, and using a 4.7k resistor to input pin D1, works as wake trigger for both falling and rising edge (obviously) but using FALLING or RISING ain’t working out YET.

Thanks!


#13

Can you just give us an update about your setup?
Can you draw a schema of your setup showing the reed switch, the pull resistor and the controller and how things are wired?


#14

void setup()
{
	pinMode(D1, INPUT);
	pinMode(D4, OUTPUT);
	digitalWrite(D4, LOW);
}

void loop()
{
	System.sleep(D1, CHANGE);
	digitalWrite(D4, HIGH);
	delay(10000);
	digitalWrite(D4, LOW);
}

#15

Try using a setup like this (it uses a photon, you get the idea though):

with this code:

void setup()
{
	pinMode(D1, INPUT);
	pinMode(D4, OUTPUT);
	digitalWrite(D4, LOW);
}

void loop()
{
	System.sleep(D1, FALLING);
	digitalWrite(D4, HIGH);
	delay(10000);
	digitalWrite(D4, LOW);
}

The resistor value isn’t critical so just grab anything you happen to have >= 220ohm.


#16

Thank you for the setup idea!

With using your code and a 10k resistor like in the scheme, it triggers with both falling and rising edge.

I don’t know if this is a debouncing issue that can be solved with decoupling caps, or if it’s something else?
i don’t really have decoupling caps in my disposal, but it could be if it solves the problem :wink:

(if i touch the led or resistor wire, it triggers also)


#17

This probably indeed is debouncing. It could be solved by adding some capacitors but it can also be solved by software debouncing. Try this (not sure if it works, can’t test atm):

unsigned long prevtime;
unsigned long endtime;
unsigned long debouncetime = 100;
void setup()
{
	pinMode(D1, INPUT);
	pinMode(D4, OUTPUT);
	digitalWrite(D4, LOW);
}

void loop()
{
	System.sleep(D1, FALLING);
	prevtime = millis();
	while (millis()-prevtime <= debouncetime && digitalRead(D1) == LOW)
	{
	    endtime = millis()-prevtime;
	}
	if(endtime >= debouncetime)
	{
	    digitalWrite(D4, HIGH);
	    delay(10000);
	    digitalWrite(D4, LOW);
	}
}

Although I can’t test, I’m doubting about the sleep routine in the loop. Might cause some issues but you’ll find it :wink:


#18

Thanks for the input!

However, i kinda need it to stay asleep until it’s triggered correctly and not wake every time and check AFTER if the trigger was correct. I did try your solution though just to check, and it still lights the LED on both rising and falling.

I’ve tried so many things, but it never wakes only on closing the magnetic switch.
With trial and error i’ve gotten it to wake on either ONLY closing the switch or both closing and opening… so very frustrating :face_with_symbols_over_mouth:

i mean isn’t it logical that i connect one end to ground and the other to input and have a pull-up resistor connected from input to 3v3, and then in the code set it to wake on RISING edge (the magnet is taken off and the contact is closed) ?

What am i missing!?


#19

I think I made a tiny mistake.

Replace this:

System.sleep(D1, FALLING);
prevtime = millis();

with this:

System.sleep(D1, FALLING);
prevtime = millis();
endtime = 0;

And try again.

If you happen to find/have/buy some capacitors try the following schematic:

Value of C1 depends on R1 and how much debouncing is required, trail and error will solve it for you.
Ceramic or electrolytic, it doesn’t matter much. Keep polarity and voltage rating in mind (use minimum 6.3V capacitors).
This will use a small amount of power when the contact is closed. I’m assuming you’re running on battery so keep this in mind. With R1 = 10k it’d add ~1.1mW. R1=220 it’d add ~50mW.

Goodluck!


#20

You can try @TheHawk1337’s suggestion.
But if it doesn’t work you may rather go for a different sensor as reed switches are notorious bouncers and any attempt to hardware debounce without a more complex circuitry may fail.

You could use a Hall effect sensor which won’t bounce.