Problem with switch timing

hal8000

Member
Problem with switch timing [SOLVED]

I have an intermittent fault on a circuit with a Picaxe 18M2
It uses two manual push buttons and drives a motor that opens and controls my curtains.
There are two additional open and close stop switches, these are reed switches activated
by a moving magnet on the curtain track.
The mechanics work fine.

The problem is with the switch timing.
A short press drives the motor for 1 second, a long press drives the motor for 15 seconds.

The short press is < 100ms
The long press is > 100ms


All works well about 7 out of 10 times, When it fails pressing manual Open switch (input C.1)
or manual Close switch (input C.2) does nothing. (By nothing I mean that motor does not
drive and no display on the OLED).



Its not the greatest programming, maybe someone can spot some flaw.
I'm enclosing the program in CODE tags below:

Code:
#picaxe  18M2
; Setup   dirs %msb.......lsb, 1=o/p 0=i/p
let dirsB = %10101100
let dirsC = %00000000

symbol motorRev = B.2       ;  LT4424 to motor (B.2 output)
symbol motorFwd = B.3     
Symbol OLED = B.7
symbol manOpen = pinC.1   ; pinC.1 input
symbol manClose = pinC.2

symbol closeSw = pinC.7
symbol openSw = pinB.4
symbol ttd = b1 ; reg b1 time to drive
symbol stimer = b2


main:  ; scan inputs
if manOpen =1 then  gosub stimerOpen
if manClose =1 then  gosub stimerClose 
serout OLED,N2400,(254,1)  ' Clear  OLED
goto main	

stimerOpen:    ; determine long or short press
let stimer = 0
Do While manOpen =1
	pause 10
	inc stimer
	if manOpen = 0 then    ; switch released 
		if stimer < 100 then gosub manualOpen	
		if stimer > 100 then gosub autoOpen
	endif
loop    ; increment stimer until switch released
       return
       
stimerClose:
let stimer = 0       
Do While manClose =1
	pause 10
	inc stimer
	if manClose = 0 then
		if stimer < 100 then gosub manualClose
		if stimer > 100 then gosub autoClose
	endif
loop
	return
      

manualOpen:
if openSw=1  then
	serout B.7,N2400,(254,192,"Curtains Open") 'line 2
	pause 1500
	return
else
	serout B.7,N2400,(254,128, "Man Open") 'line 1
	let ttd =10		     ; reg b1 duration
	gosub motorOpen
endif
return	

manualClose:
if closeSw=1 then
	serout B.7,N2400,(254,192,"Curtains Closed") 'line 2
	pause 1500	
	return
else 
	serout B.7,N2400,(254,128, "Manual Closing") 'line 1
	let ttd = 10
	gosub motorClose
endif
	return
	
autoClose:
'check  stopSw (C7) else drive at .1s intervals 110 x .1 = 11sec
serout B.7,N2400,(254,128, "AutomaticClosing") 'line 1
let ttd = 150
gosub motorClose
return

autoOpen:
'check  stopSw (C7) else drive at .1s intervals 80 x .1 = 8sec
serout B.7,N2400,(254,128, "AutomaticOpening") 'line 1
let ttd = 150
gosub motorOpen
return

motorOpen:
'check stopSw  else drive motor in .1s intervals
for b0 = 1 to ttd   ; time to drive duration
	if openSw=1  then 
		serout B.7,N2400,(254,192,"Curtains Open") 'line 2
		return  ; check if openSw or torque active
	else
		high motorFwd    
		pause 100
		low  motorFwd   ' motor on 100ms then off
	endif
next b0
return	

motorClose:
for b0 = 1 to ttd
	if closeSw=1 then return
	else
		high motorRev
		pause 100
		low motorRev
	endif
next b0
return

I should add all unused inputs are ground, power to picaxe is 5V and power to LT4424 (motor driver) is 12V.
Currently assembled on a breadboard, input switches are PCB type plugged into breadboard, the reed switches
on curtain rail are twisted pair CAT5 about 4 meters. Home environment is pretty bad for EMI/RFI so not
ruling out interference yet.

Thanks in advance.
 
Last edited:

hal8000

Member
geoff07,
Thanks for a quick reply.
I'll alter my timing.

Second thoughts, less than 1 second or greater than 1 second is not too bad.
Any idea why it fails intermittently?
Sometimes a short press 1/4 second or half second does nothing.
Sometimes a long press 2 or 3 seconds does nothing.
 

AllyCat

Senior Member
Hi,

I've not checked all the logic, but you appear to have:

Code:
[B]Do While manOpen =1[/B]
	pause 10
	inc stimer
	[B]IF manOpen = 0 [/B]then    ; switch released 
		if stimer < 100 then gosub manualOpen	
		if stimer > 100 then gosub autoOpen
	endif
loop    ; increment stimer until switch released
       return
What happens if the switch opens after the IF but before the next WHILE ? Also, what if stimer is exactly 100 ? However, neither error seems serious enough to produce a 30% failure rate (but maybe 10%).

Cheers, Alan.
 

hal8000

Member
Hi,

I've not checked all the logic, but you appear to have:

Code:
[B]Do While manOpen =1[/B]
	pause 10
	inc stimer
	[B]IF manOpen = 0 [/B]then    ; switch released 
		if stimer < 100 then gosub manualOpen	
		if stimer > 100 then gosub autoOpen
	endif
loop    ; increment stimer until switch released
       return
What happens if the switch opens after the IF but before the next WHILE ? Also, what if stimer is exactly 100 ? However, neither error seems serious enough to produce a 30% failure rate (but maybe 10%).

Cheers, Alan.

Thanks Alan, good poinrs. Just realised not allowed any leeway for contact bounce either.
I suppose its possible they could all add up to some erratic behaviour.
 

sages

Member
A 100mS keypress is a pretty short duration physical action to reliably reproduce. You might want to change the logic to start the motor upon key press detected and if it is released prior to one second elapsing then stop the motor after one second has elapsed. If the key is still pressed after one second then run the motor for 15 seconds.
ie
if keypress detected
start motor
endif

if one second elapsed and key still pressed
leave motor running for 15 seconds
else
stop motor
endif
 

stan74

Senior Member
Why not use 1 switch? If the curtains are closed they can only open.If the curtains are open they can only close.
Most things have only 1 switch if you think about it.
 

techElder

Well-known member
Why not use 1 switch? If the curtains are closed they can only open.If the curtains are open they can only close.
Most things have only 1 switch if you think about it.
Which brings me to ask about the OP's stated design, "What happens when both switches are pressed at the same time?"

Logic is logical. Design your project before you start coding it.

Stan's comment on using one switch gets my vote, except that then the project needs a way to determine what the definition of "closed" and "open" is.
 

stan74

Senior Member
Hal later mentioned no de-bounce so guessed he'd nearly sorted the problem. I was going off topic sort of. Did you know hal is all 1 letter before ibm? Now I am :)
 

techElder

Well-known member
Sorry, Stan. You're late and old-fashioned. There's already a "HAL9000" that supersedes the "HAL8000". :D ;D :D
 

AllyCat

Senior Member
Hi,

Why not use 1 switch? If the curtains are closed they can only open.If the curtains are open they can only close.

The UI (User Interface) appears to allow the motor to be driven to partially open or close the curtains, so two switches are the logical choice. I suppose you could press one button twice if the motor starts in the wrong direction. However, the electric windows in my car effectively use four buttons per window. Each integrated into a single "rocker" switch (which of course avoids the "both buttons pressed" issue), but a "firm" press activates the auto mode (like a two-stage camera shutter focus/shoot button).

However, the OP UI doesn't seem well-conceived to partially open/close the curtains. Perhaps not entirely intuitive, but the way I would do it is that a "short" press would select the "automatic" mode (drive to endstop) and a "long" press drives the motor until the button is released. If you want a "nudge" mode, then introduce a delay (corresponding to the auto mode timeout) before the motor starts to drive.

A good way to avoid logical "bugs" is to KISS (Keep It SimpleS). The original issue appears to be caused by using two separate tests for a button-press (DO .. WHILE and IF .. THEN) and for stimer (< and >), which might be avoided by an IF .. ELSE .. ENDIF structure in each case.

Cheers, Alan.
 

stan74

Senior Member
I'm not posting what I would have done code cos I reckon he'll sort it. Partially open or closed (same thing) or not,it could be done with 1 button since hal's already using "continuous" press. Break it down to
button pressed
count until button released
check the count and then curtain state-short count open/close fully until limit switch or another button press
if another button press stop and reverse previous direction if a long press
 

hippy

Technical Support
Staff member
Here's a sample program which will run a motor for 1 second on a short push, 15 seconds for a long push.

Set "Symbol PUSHED = 0" for active low input.

Code:
#Picaxe 08M2

Symbol BTN        = pinC.3  ; Button input
Symbol MTR        = C.2     ; Motor output

Symbol PUSHED     = 1       ; level when BTN is pushed

Symbol pushTimer  = w0      ; How long button push is for
Symbol wantTimer  = w1      ; How long we want to run motor for
Symbol motrTimer  = w2      ; How long motor has been running

Symbol PUSH_TIME_MS = 100   ; How long a push for a long motor run (ms)
Symbol SHORT_RUN_MS = 1000  ; 1 second short motor run (ms)
Symbol LONG_RUN_MS  = 15000 ; 15 second long motor run (ms)

Symbol LOOP_MS      = 10    ; How long each loop is

Do
  If BTN Is PUSHED Then Gosub BtnPushed
Loop

BtnPushed:
  High MTR
  pushTimer = 0
  motrTimer = 0
  wantTimer = SHORT_RUN_MS
  Do While motrTimer <= wantTimer
    Pause LOOP_MS
    motrTimer = motrTimer + LOOP_MS
    If BTN Is PUSHED Then
      pushTimer = pushTimer + LOOP_MS
      If pushTimer >= PUSH_TIME_MS Then
        wantTimer = LONG_RUN_MS
      End If
    Else
      pushTimer = 0 
    End If
  Loop
  Low MTR
  Do : Loop While BTN Is PUSHED
  Return
That doesn't include 'an escape route' when the motor is running but the end-stop has been reached. That would require something inserting along the lines of ...

Code:
    If END_STOP Is REACHED Then
      Low MTR
      Do : Loop While BTN Is PUSHED
      Return
    End If
 

stan74

Senior Member
And maybe a curtain_pos in the escape routes ie fully open closed or it's High MTR with no direction.
You don't think about curtains much until you have to wash and dry them.
edit- or program them.
 
Last edited:

techElder

Well-known member
This logic problem reminds me of my microwave oven that I use to rewarm my coffee early in the morning. I've spent some time watching the timer count down and trying to open the door at just the right moment. You see, the engineer didn't foresee a consumer trying to find the holes in his logic (something I do quite regular with gadgets.)

About 10% of the tries I make, I can hit the "open door" button at just the right moment that catches the program doing something besides watching the open door switch. The "timer finished" beeper just keeps on beeping until I hit the "stop" button. :D

Your design needs just the right amount of logic to keep nuts like me from causing you pain!
 

hal8000

Member
Sorry for late delay, problem now solved, ALL very good replies.

I was using a 5V USB adapter built into a UK elctric socket to power the Picaxe.
Although the picaxe draws very little current, the supply rails were full of noise
and HF noise from the SMPS of the USB socket.

Some additional 100nF decoupling capacitors eliminated the problem, but now
scrapped the USB socket and running from a 7805 regulator.

Increased the pause for slightly longer switch debouncing.
Also changed the timing loop from 1 second to 1/2 second
with greater tha or equal to

if stimer < 100 then gosub manualClose
if stimer > 100 then gosub autoClose

If stimer = 100 then no action would be taken so:

if stimer < 50
if stimer >= 50

The addition of >= alleviates the above condition .

What happens if both switches pressed together?
Nothing bad.
Depending on which switch is pressed first or where the program is in the
input loop dictates direction.

Thanks for all the good replies.
Now as Stan suggested it could have been done with one switch except I wanted
some level of manual control, (just a short pulse to move the curatains an inch or
so if the sun is too dazzling). Hence I used two switches. However that got me thinking
and in a future version I will use ADC and work on voltage levels.

I cant seem to edit the thread title to mark as [solved]
Regards h8k
 

The bear

Senior Member
@hal8000,
Talking of ADC, it works very well. I have a system working venetian blinds. If the sun is really bright, then the ADC instructs the motor (Ex VHS recorder) to partially close the blinds. The motor works the blinds via the existing control rod, through a home made clutch.
Regards, Bear..
 

hal8000

Member
@The bear
Yes there is a couple of designs using the Arduino, and one on Instructables using the Picaxe. Not sure
if they used your code though. One version had an ephemeris mode where it could track the sun and
partially close the blinds.
Regards h8k
 
Top