PDA

View Full Version : Newbie - 16F628A and switch latching



malc-c
- 14th May 2006, 00:42
Hi all,

My first post so be gentile with me :)

My first project using PBP is for my 12 year old son's model railway. I'm using a 16F628A with the internal 4Mhz OSC as timing is not an issue (and the internal OSC is claimed to be very precise anyway). The project is not rocket science, simply to detect a train via the momentarly activation of a reed switch. This pulse then turns on an LED which is latched on until the same reed switch is activated again.

I have two problems:

1) - The latching is not clean, in that sometimes the LED brightens and remains on when it should be off, or when off it is turned on by the reed switch, but fails to latch

2) - I'm using WinPIC pro to program the PIC. I have set the PIC up for internal OSC no clock out in the code, but I have to change the settings from XT to RC noClockout in the Winpic application. Is the an issue with the Winpic application, or the code (which compiles OK)

Anyway, here is my code.



@INTRC_OSC_NOCLKOUT
@WDT_ON
@PWRT_ON
@MCLR_OFF
@BOD_ON
@LVP_OFF
@CPD_OFF
@PROTECT_OFF

CMCON=7
TRISB=%11101111 'set RB6 as output and the rest input

SW var PORTB.0 'switch input pin 6 (RB0)
LED1 var PORTB.4 'LED1 on pin 10 (RB4)
Swset var bit

low led1 'RB4 set to LOW (LED1 is off)
Swset=0 'Var swset is set low

Main:
if SW=0 then 'If switch is LOW (Grounded) then
Toggle Swset 'change swset from 0 to 1
pauseus 200 'debounce delay
endif

If Swset=1 then 'if swset is 1
high led1 'then turn on RB4 (and hence the LED)
else
low led1 'else, LED is off
endif

Goto Main 'go back and keep checking

End

The reason I've only configured one output on port B is purely for testing..once I have this sorted, RB0, RB1, RB2 and RB3 will all be switch inpts, with RB4 - RB7 their coresponding outputs (we have 4 sidings to monitor )

TIA


Malcolm

Melanie
- 14th May 2006, 01:18
Your debounce delay is too short... swap PAUSEUS for a straight PAUSE. 200mS is neither here nor there in the great scheme of a train moving past your reed switch, whereas in 200uS which you have currently, the train would barely have moved a fraction of a millimetre... With some experimentation, you might find that PAUSE 50 will do...

malc-c
- 14th May 2006, 10:42
Thanks for the reply,

I had played with the debounce pause time, but only by a 100's of a uS

I'll increase the delay and see how I get on.

Many thanks

Malcolm

peterdeco1
- 14th May 2006, 11:20
Hi Malcolm. One suggestion is to make all unused ports as outputs. This helps in noisy environments as electric motors drive PIC's crazy even with a separate supply. Make sure portb.0 is held high with a resistor not too high in value. I once had a small hobby motor drive my PIC crazy until I went down to a 1K resistor as a pullup.

CMCON = 7
TRISA = 0
TRISB = 0 'MAKE ALL OUTPUTS
PORTA = 0
PORTB = 0 'ALL OUTPUTS LOW
INPUT PORTB.0 'RB0 SWITCH INPUT

MAIN:
NAP 0 'REDUCE CURRENT DRAIN ON BATTERY
IF PORTB.0 = 0 THEN CHANGELED 'IF REED SWITCH CLOSED CHANGE LED STATE
GOTO MAIN

CHANGELED:
TOGGLE PORTB.4 'CHANGE LED STATE

WAITFORRELEASE:
PAUSE 1000 'WAIT A SECOND
IF PORTB.0 = 0 THEN WAITFORRELEASE 'WAIT HERE FOR REED TO OPEN
GOTO MAIN

malc-c
- 14th May 2006, 13:34
Hi Peter,

Thanks for the advice and I'll make port A all output as I'm only using port B. Oh and yes the inputs on the switches are tied high via a 10K resistor.

Acetronics2
- 14th May 2006, 13:49
Hi,Malc

Have a look to the " BUTTON " command ...it is really very powerful for such application.

Add a DEFINE BUTTON_PAUSE 200 at the top of your program if you want a debounce time of 200 ms ( max 255 ms ...) ... that's all !

read you soon !!!

Alain

PS; if not already done, download this : http://www.melabs.com/downloads/pbpm304.pdf
THE reference manual !!!
Microcode studio : http://www.melabs.com/downloads/mcs2300.zip

malc-c
- 14th May 2006, 14:15
Hee hee - fancy seeing you here ;)

Yes I have downloaded the manual, and had it open last night whilst I was developing the program, and as manuals go its really good to get newbies like myself up and running.

Must admit, that I'm having more fun (and luck) with PBP than I did with JAL. PBP seems more logical in its commands and the structure of using them.

Alain, let me into a secret, is that Melanie in her avitar... brains as well as beauty - wow !!

Acetronics2
- 14th May 2006, 14:33
Hee hee - fancy seeing you here ;)

Alain, let me into a secret, is that Melanie in her avitar... brains as well as beauty - wow !!

In fact, Mel is some like Charly in the "Charly's girls" TV series ... I do not think anyone on this forum knows her real appearance ...

We only know she says she likes to wear leather clothes at night, and is a bit bored about charming guys hoping to get something from her brain ...

May be she'd love to find a bunch of red roses and some Champagne at her door rather than the New up to date Compiler ....

Talk to her gently, and she'll give you the best from her ...

That's part of what I understood here ... not to break the magic.

Alain

Melanie
- 14th May 2006, 17:21
There are those that have sent boxes of red roses...

...and there are those that have sent boxes of chocolates...

...boxes of diamonds are a little slower in coming - but I'm working on it...

...and there are those that have seen a little more of me than others (I seldom refuse an invite to dinner - especially if you're buying - but can you afford a genuine up-town girl?) *smiles*

...and Yes, that's really me in the avatar... if you're real nice I just might change it for a while to something more sophisticated - but I'm always worried that I'll distract you from your work (or play)...

mister_e
- 15th May 2006, 03:29
... if you're real nice I just might change it for a while to something more sophisticated -
I have a feeling of what it could be ;) Maybe i'm in the 3rd category ... LOL easy to start some rumor here :D

BTW Melanie, if you change your Avatar to 'something more sophisticated', i feel that some end-of-class student here could be shocked OR spam your PM! May i bet on the second one :)

Melanie
- 15th May 2006, 06:45
My PM is already spammed...

Dear Miss Whiplash... Thank you for last nights session... I won't be able to sit down for a week, but it was worth every minute... PS My PIC still doesn't work.

Now, now Steve... people might get the wrong idea on how you ended up in hospital...

malc-c
- 15th May 2006, 13:24
I'm hoping that you guys and Miss whippy, sorry Mel can tell me why the following code won't work correctly.

Having managed to sort out the delay for the debounce I had each LED bing turned on, latched and turned off by activation of the corresponding reed switch - Great !

However I now want to evolve the code so that the following happens. The siding has the buffer at the left, and trains enter from the right. A reed switch (sw1) is placed at the start of the siding (on the right), a train enters the siding and activated sw1 and LED1 is lit. The train continues to the end of the siding where it activates the second reed switch (sw2) and thus LED2 is lit, and the operator shuts off the power. So far so good.

Now the operator can re-arrange the train and place the loco at the other end ready to go back on the main layout. When it does sw1 is then activated again, but this time I need it to clear both LED1 and LED2. Ok I thought, lets simply have a new varible (swset5) that is toggled only when swset1 and swset2 are high.. but it won't work. activating sw1, then sw2, then sw1 again just turns off LED1, LED2 remains lit

Here is my code (I've yet to try the BUTTON command, but maybe that will happen when I come to tidy up the code ??)



@INTRC_OSC_NOCLKOUT
@WDT_ON
@PWRT_ON
@MCLR_OFF
@BOD_ON
@LVP_OFF
@CPD_OFF
@PROTECT_OFF

CMCON=7
TRISB=%00000011 'set RB0 & 1 as input and the rest output

SW1 var PORTB.0 'switch input pin 6 (RB0)
SW2 var PORTB.1 'switch input pin 7 (RB1)


LED1 var PORTB.4 'LED1 on pin 10 (RB4)
LED2 var PORTB.5 'LED1 on pin 11 (RB5)

Swset1 var bit
Swset2 var bit

Swset5 var bit

low led1
low led2

Swset1=0
Swset2=0

swset5=0 'Var swset is set low

Main:
if SW1=0 then 'If switch is LOW (Grounded) then
Toggle Swset1 'change swset1 from 0 to 1
pause 500 'debounce delay
endif

if SW2=0 then 'If switch is LOW (Grounded) then
Toggle Swset2 'change swset2 from 0 to 1
pause 500 'debounce delay
endif

If Swset1=1 then 'if swset1 is 1
high led1 'then turn on RB4 (and hence the LED)
else
low led1 'else, LED is off
endif

If Swset2=1 then 'if swset2 is 1
high led2 'then turn on RB5 (and hence the LED)
else
low led2 'else, LED is off
endif

If swset1=1 and swset2=1 then
toggle swset5
endif
if swset5=1 and sw1=0 then
low led1
low led2
else
high led1
high led2
endif

End


I have even tried removing the "else" part at the end of the code so it reads


If swset1=1 and swset2=1 then
toggle swset5
endif
if swset5=1 and sw1=0 then
low led1
low led2
endif


But that still fails to work correctly.

Any advice guys and gals ??

Acetronics2
- 15th May 2006, 13:49
Hi, Malc

as SWset5 is tested AFTER the swset1 ... your condition never can happend, or during so little time, it can't work properly.

Alain

malc-c
- 15th May 2006, 14:04
So are you saying its the logic of PBP or my program logic that's not right ;)

I modified the code to add in a new var for LED3 to test for the condition "swset1=1 and swset2=1 then swset5=1 and it didn't work either



If swset1=1 and swset2=1 then
swset5=1
else
swset5=0
endif
if swset5=1 then
high led3

endif



When swset1=1 and LED1 is lit, and swset2=1 and LED2 is lit, LED3 fails to light, ergo swset5 can't =1

So any ideas on how to do what I want it to do ??

Acetronics2
- 15th May 2006, 14:27
YOUR Logic is wrong ...

Alain

malc-c
- 15th May 2006, 14:30
You ain't going to make this easy for me are you !

A hint in the right direction would help !!

malc-c
- 15th May 2006, 15:01
OK following your advice I RTFM and it states



If (B0 = 10) And (B1 = 20) Then loop


So I applied the same logic to the code



If swset1=1 and swset2=1 then occ
occ:
high led3


ie if swset1 and swset2 both =1 then jump to occ, occ simply turns on LED3

This didn't work. It seems that its ignoring the "and" part of the statement :(

I mean this ain't exactly rocket (or should I say space shuttle ;) ) science

dhouston
- 15th May 2006, 15:26
It seems that its ignoring the "and" part of the statementPerhaps because you ignored the parentheses?

Acetronics2
- 15th May 2006, 15:33
Hi, Malc

try this:

CMCON=7
TRISB=%00000011 'set RB0 & 1 as input and the rest output

SW1 var PORTB.0 'switch input pin 6 (RB0)
SW2 var PORTB.1 'switch input pin 7 (RB1)


LED1 var PORTB.4 'LED1 on pin 10 (RB4)
LED2 var PORTB.5 'LED1 on pin 11 (RB5)

Swset1 var bit
Swset2 var bit

Swset5 var bit


low led1
low led2

Swset1=0
Swset2=0

swset5=0 'Var swset is set low

Main:

if SW1=0 then
'If switch is LOW (Grounded) then

IF swset5 =1 THEN

swset1 = 0
swset2 = 0
swset5 = 0

loop: IF sw1=0 then loop 'wait for button release ... Yessss !!!

GOTO jump

ENDIF

Toggle Swset1 'change swset1 from 0 to 1
pause 500 'debounce delay
endif


if SW2=0 then 'If switch is LOW (Grounded) then
Toggle Swset2 'change swset2 from 0 to 1
pause 500 'debounce delay
endif

Jump:

If Swset1=1 then 'if swset1 is 1
high led1 'then turn on RB4 (and hence the LED)
else
low led1 'else, LED is off
endif

If Swset2=1 then 'if swset2 is 1
high led2 'then turn on RB5 (and hence the LED)
else
low led2 'else, LED is off
endif

If swset1=1 and swset2=1 then
toggle swset5
endif

Goto Main
End

And now try to understand WHY !!!

Alain

mister_e
- 15th May 2006, 16:41
... I won't be able to sit down for a week, but it was worth every minute...

Now, now Steve... people might get the wrong idea on how you ended up in hospital...

How dare you post our private stuff in public :D

LOL! yeah maybe you're right... but damn you should be really strong to break my arms, legs and spinal cord. Guys, be aware of that!

LOL Melanie, at least i wish it could be true ;)

Ok let's stop it here.. there's somebody who need help here, but Alain give some great tips.

Acetronics2
- 15th May 2006, 17:09
Ok let's stop it here ...

Thanks to Luciano, ve've a good idea of uptown girls at night ...

cool, Malc ... cool !!!

Alain

malc-c
- 15th May 2006, 17:22
Hi, Malc

try this:



Thanks, and yes it compiles OK and in tests works as required approx 70% (ie 7 out of 10) of the time. On three attepts LED2 remained lit, but its a lot better than my 0% success rate :)




And now try to understand WHY !!!


OK I'll have a go...




CMCON=7
TRISB=%00000011 'set RB0 & 1 as input and the rest output

SW1 var PORTB.0 'switch input pin 6 (RB0)
SW2 var PORTB.1 'switch input pin 7 (RB1)


LED1 var PORTB.4 'LED1 on pin 10 (RB4)
LED2 var PORTB.5 'LED1 on pin 11 (RB5)

Swset1 var bit
Swset2 var bit

Swset5 var bit


low led1
low led2

Swset1=0
Swset2=0

swset5=0 'Var swset is set low


Sets up the PIC and the varibles



Main:

if SW1=0 then
'If switch is LOW (Grounded) then

IF swset5 =1 THEN

swset1 = 0
swset2 = 0
swset5 = 0


If pin is grounded then check to see if varible bit swset5 is set high, and if so then swset 1,2 and 3 are all set low



loop: IF sw1=0 then loop 'wait for button release ... Yessss !!!


constantly loop round checking pin sw1 to see if grounded




GOTO jump

ENDIF


and if so, goto the section of the code labled jump....




Jump:

If Swset1=1 then 'if swset1 is 1
high led1 'then turn on RB4 (and hence the LED)
else
low led1 'else, LED is off
endif

If Swset2=1 then 'if swset2 is 1
high led2 'then turn on RB5 (and hence the LED)
else
low led2 'else, LED is off
endif


if the varibles swset 1 is high then turn on its corresponding LED, if low then turn off the LED, same thing for swset2



If swset1=1 and swset2=1 then
toggle swset5
endif

Goto Main



If swset1 and swset2 are both high then change the state of swset5 to high, which iwhen checked by the line above

IF swset5 =1 THEN

swset1 = 0
swset2 = 0
swset5 = 0

resets swset1, swset2 and swset5 back to 0, and conversly all LEDs are turned off




Toggle Swset1 'change swset1 from 0 to 1
pause 500 'debounce delay
endif


if SW2=0 then 'If switch is LOW (Grounded) then
Toggle Swset2 'change swset2 from 0 to 1
pause 500 'debounce delay
endif


End


Checks sw2 and changes the state of swset2 (and thus LED2)


Well how did I do ??

malc-c
- 15th May 2006, 17:26
Guys you crack me up... here am I trying to get technical and you guys are trying to put me mind off the subject by posting pictures of pussy on a public forum :) :)

mister_e
- 16th May 2006, 03:17
i hope you remember that you miss one word !

The Melanie bad hair day is back!
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=445&d=1125012225">

While we're at that... http://www.picbasic.co.uk/forum/showthread.php?t=2050

malc-c
- 16th May 2006, 15:45
That's a shame, either its my browser or the plug in, but I only get audio when viewing that clip :(

With regards to the topic of this thread (Mel, I am trying to keep this on topic !) I hooked up a test track and placed a magnet on a loco to see how it worked, as I had been using magnets passing over the switches by hand to test the code.

I don't know if it's due to the speed of the train (slower than my hand tests) but I got a 1 in 10 success rate of both LEDs being turned off when the train exited the siding :(

The other question I have, is as I need 8 inputs and 8 outputs, can I use port A in the same way as port B. The thing that concerns me is the MCLR pin... do I have to do something to configure this as a normal input as I've read that this can cause problems if not treated right ??

Cheers

Malcolm
(rapidly aging and going bald by pulling my hair out over this "issue")

Acetronics2
- 16th May 2006, 15:54
Hi, Malc

Don't you think it would be the time to test the "BUTTON" statement, instead of " if SW1=0 then ..." ???

May be we could also try more sophisticated debouncing ... but one thing after one !!!

you want to play the " Speedy Gonzalez " ... no problem this side !!!

Alain

PS: Try this : http://www.darreltaylor.com/files/ouchywhip.wav ...

malc-c
- 16th May 2006, 16:02
Yeah, I think I might have a go at the BUTTON statement...

Let me go away and RTFM first, have a play, try and get something together before bailing be out ;)

Before I start though, any comments on configuring PORTA (inc MCLR) for in/outputs ??

Malc

Acetronics2
- 16th May 2006, 16:13
Here a cutout ...

PORTA = 0 ' declare port level BEFORE port direction = safe power-on

PORTB = 0

'Pour 16F628

CMCON = 7 ' PortA Digital inputs
CCP1CON = 0 ' PWM off

' DATA @1,word 625,0,word 545,word 750 ' pre-setting EEPROM


'************************************************* *****************************
' Initialisation commutation : Vérification batterie
'************************************************* *****************************

init:
battok = 1 ' setting critical variables ...
dejavu = 0
bougie = 0
error = 0
Servo = 0
TRISA = %00000011 ' Port Direction
TRISB = %00000001

Pause 400 ' Stabilisation au branchement

GoSub verbatt ' beginning of real program ...batt testing i.e.


Cheers

Alain

malc-c
- 16th May 2006, 22:28
Ok, trying to get my head round the BUTTON statement, and failing.. bu I just love the line



In general, it is easier to simply read the state of the pin in an IF..THEN
than to use the BUTTON command as follows:
If PORTB.2 = 1 Then notpressed


which was what I was originally doing .....

Oh well ... I'll keep trying

malc-c
- 17th May 2006, 00:16
Ok after a lot of tries I finally have something that works. Here's the centre section of the code with the initialisation parts ommited for clarity ;)



LED1 var PORTB.4 'LED1 (green) on pin 10 (RB4)
LED2 var PORTB.5 'LED1 (red) on pin 11 (RB5)

SW0 var PORTB.0 'switch input pin 6 (RB0)
SW1 var PORTB.1 'switch input pin 7 (RB1)

SWFLAG1 var Byte ' counter for track 1

Swset1 var bit
Swset2 var bit

low led1
low led2

Swset1=0
Swset2=0

SWFLAG1=0

Main:

if SWFLAG1 >2 then ' if the counter is >2 then reset all
swset1=0
swset2=0
SWFLAG1=0
endif

If SW0=0 Then
swflag1 = swflag1 +1 ' increase count by 1
swset1=1
pause 500
endif

If SW1=0 Then
swflag1 = swflag1 +1 'increase count by 1
swset2=1
pause 500
endif

if swset1=1 then
high led1 'then turn on RB4 (and hence the LED)
else
low led1 'else, LED is off
endif

If Swset2=1 then
high led2 'then turn on RB5 (and hence the LED)
else
low led2 'else, LED is off
endif


Basically rather than try and compare a condition of swset1 and swset2 and SW0, I simply used SWFLAG1 as a counter to count the number of times the switches are activated, and if it is greater than 2 reset the couter and swset 1 and 2 to 0.

Now when sw0 goes low for the first time SWFLAG1 is = 1, when sw1 goes low SWFLAG1 =2 then when the loco is placed at the front of the train andis driven over SW0 for the second time SWFLAG1 =3. As the "IF SWFLAG1 > 2" condition is reached, SWFLAG1 is reset to 0, as is swset1 and swset2.

Now just have to replicate this for the other 6 inputs and outputs

I know this may seem trivial to the more experienced programmers, but its my first real program with PBP that is beyond the simple flash a LED, and I'm really pleased that I managed to figure something out, after some guidance from you guys here.

Thanks

Malcolm

Oh, and seeing that I RTFM and did my homework... do I qualify for a dozen lashes form Mel (alias Ms Whippy :) :) )

Acetronics2
- 17th May 2006, 10:33
Ok, trying to get my head round the BUTTON statement, and failing.. bu I just love the line



which was what I was originally doing .....

Oh well ... I'll keep trying

Hi,Malc

The IF THEN Statement implies your switch is an ideal switch and debouncing not tricky ...

BUTTON is more complicated and slow ... but works in very difficult situations.

The state of art is to verify the button has not changed its state BEFORE debouncing time has ended ...
Multiple IF ... THEN ... ELSE following each others reach that GOAL ...

Alain

Melanie
- 17th May 2006, 11:16
There is another way of thinking here Alain...

Once a switch has closed (as detected by the first IF/THEN) then the assumption is that whatever event caused it to close (or open) is not a False Alarm and the event intended to happen (eg a User pressing a button). You therefore need no futher IF/THEN's to see if the contacts are still closed after the debounce time period expries.

All you have to do is delay looking at that switch again for a period of time greater than any possible contact bounce to ensure you don't register that event a second time (as would happen if you used interrupts for example).

Now the delay time is really down to the application. I tend to use 100mS for Keyboard Buttons, because that gives an 'auto-repeat' of 10cps which is quite nice when viewed on a display. Naturally, if you're timing something that happens a lot quicker, then you need to reduce the bounce delay time, but if you get it too short, you'll run into the multiple contact closure problem.

It's difficult to guage and is done mainly by look/see and a bit of experience because different switches (be they contacts on a Switch, Relay or a Reed) all exhibit different closure properties and have different bounce periods. Best method I've found is to overkill the delay as much as possible.

The best method for registering an event, but discarding any False Alarms, is to see how long a switch remains closed over a period of time. That then will require multiple IF/THEN's both at the beginning and at the end of the debounce period.

malc-c
- 17th May 2006, 12:18
Melanie, you are spot on.. The issue I have here is that each time the reed is triggered it will never be the same time period as the last, as some trains will pull in to the siding slower than others. I've found that, although not probably the ideal way, having lots of IF/THEN sections for checking the switches and activation the LEDs works, and more to the point I understand what happening and how I debugged the code to get it working.

The only issue I've run into with the 628 is replicating the action on PORTA. As taking MCLR low seems to reset the PIC even when including Alain's suggestions


PORTA = 0 ' declare port level BEFORE port direction = safe power-on

PORTB = 0

'Pour 16F628

CMCON = 7 ' PortA Digital inputs
CCP1CON = 0 ' PWM off

' DATA @1,word 625,0,word 545,word 750 ' pre-setting EEPROM


Its not much of a problem as I have another 628 PIC so I could use 2 PICs to cover the four sidings, but it would seem such a waste just using half of two chips. Looking at the datasheet all inputs on PORTA are ST where as PORTB has ST and TTL, could this be part of the problem in getting PORTA to work in the same way. Is there any command to turn off the VRCON or Vref function, so that PORTA is strictly in/out and all multiplexed pin options are turned off?

malc-c
- 17th May 2006, 13:36
OK I give up,

Does anyone know of a PIC with 28 pins, internal OSC (or runs off a 4Mhz xtal if no 28pin pics have internal OSC option) that has standard TTL ports...

Having MCLR on an input which is grounded has resulted in so much distress in the household I'm almost considering using descrete logic chips to do the same function.

Acetronics2
- 17th May 2006, 14:17
Hi,Malc

The 16F876A or 877A ( 40 pins ) are the ones ( huge memory, no internal bugs ...etc ...)

BUT, as they can do lots more they do need lots more understanding of their different options ...

Why don't you try to have a good working simple circuit before building the Babel tower ... you're on the soapy side ... still time to become humble.

Alain

Melanie
- 17th May 2006, 17:06
You have of course set the Config Fuses to have MCLR as an Input Pin?

I use MCLR as an I/O in dozens of 16F628 designs without problems, so I suspect you haven't.

Acetronics2
- 17th May 2006, 17:59
Our friend MUST discover some little things by experience ...

Copy and paste is really the worst solution !!!

He surely forgot that !!!

Alain

Pic_User
- 18th May 2006, 04:19
I am new to the forum and hope not out of line...

Clues:

1) - The latching is not clean, in that sometimes the LED brightens and remains on when it should be off, or when off it is turned on by the reed switch, but fails to latch

"The LED brightens" (unintentionally) does not sound very digital.

Thanks, and yes it compiles OK and in tests works as required approx 70% (ie 7 out of 10) of the time. On three attepts LED2 remained lit, but its a lot better than my 0% success rate

I hooked up a test track and placed a magnet on a loco to see how it worked, as I had been using magnets passing over the switches by hand to test the code.
I don't know if it's due to the speed of the train (slower than my hand tests) but I got a 1 in 10 success rate of both LEDs being turned off when the train exited the siding
I wonder if there might be an interaction between the magnetics of the locomotive "engine" and the reed switch. Possible even modulating the switch as the loaded motor slowly passes over the switch. Monster size "contact bounce". Or perhaps the magnetics of the motor offsets the permanent magnet, causing it to not always trigger the reed switch.

If this is part of the problem then Melanie's suggestion would certainly apply:

There is another way of thinking here Alain...

Once a switch has closed (as detected by the first IF/THEN) then the assumption is that whatever event caused it to close (or open) is not a False Alarm and the event intended to happen (eg a User pressing a button). You therefore need no futher IF/THEN's to see if the contacts are still closed after the debounce time period expries.

All you have to do is delay looking at that switch again for a period of time greater than any possible contact bounce to ensure you don't register that event a second time (as would happen if you used interrupts for example).

Don't forget the sequence of permanent magnet and motor chatter would depend upon the direction of travel (just to make it interesting).

This may not be any part of Malcolm's problem but something we should keep in mind when using reed switches or hall effect devices. Don't ask why I thought of it.

This forum is the most useful resource, for beginners, on the entire web. Thanks to all you PIC gurus, most of the "gotchas" with PICs, can be found with a forum search. Thanks for all your hard work.

-Adam-

Acetronics2
- 18th May 2006, 09:34
There is another way of thinking here Alain...

Once a switch has closed (as detected by the first IF/THEN) then the assumption is that whatever event caused it to close (or open) is not a False Alarm and the event intended to happen (eg a User pressing a button). You therefore need no futher IF/THEN's to see if the contacts are still closed after the debounce time period expries.

All you have to do is delay looking at that switch again for a period of time greater than any possible contact bounce to ensure you don't register that event a second time (as would happen if you used interrupts for example).

Now the delay time is really down to the application. I tend to use 100mS for Keyboard Buttons, because that gives an 'auto-repeat' of 10cps which is quite nice when viewed on a display. Naturally, if you're timing something that happens a lot quicker, then you need to reduce the bounce delay time, but if you get it too short, you'll run into the multiple contact closure problem.

It's difficult to guage and is done mainly by look/see and a bit of experience because different switches (be they contacts on a Switch, Relay or a Reed) all exhibit different closure properties and have different bounce periods. Best method I've found is to overkill the delay as much as possible.

The best method for registering an event, but discarding any False Alarms, is to see how long a switch remains closed over a period of time. That then will require multiple IF/THEN's both at the beginning and at the end of the debounce period.

Hi, Mel,

Here, the problem is we do not know for how long the magnet will be close to the reed switch ...
so, how to fix a reliable debouncing time ... ???

But we know one thing : if the reed switch is triggered, say 20 or 50ms long ( real debouncing ) ... the magnet is really here !!!
So, let's consider the triggering is then real.

We do not want new triggerings before some times ( That's THE problem ), even the magnet is still here ... right ???.

Let's say we allow few seconds for the magnet to go further ... before testing it once more.

If tested close ... the train is still here, stopped or so : What to do ????

If tested Open ... let's go on our program.

.............................

Back to PicBasic programming, we see here that it's the original scenario which is wrong, cause it doesn't allow a correct work of the Hardware connected.

In primary schools, our teachers always repeated us a clearly written problem has already found half its solution ...


Alain

malc-c
- 18th May 2006, 11:50
You have of course set the Config Fuses to have MCLR as an Input Pin?

I use MCLR as an I/O in dozens of 16F628 designs without problems, so I suspect you haven't.

When programing (using WinPIC pro) I've tried setting MCLR input enabled (and disabled) and it didn't have any effect. It seems that the problem is with the config as you suggest, however as I'm a newbee it would be nice if you could tell me how to set MCLR as I/O (well I guess input only).

Anyway, I've had a think and came up with the idea of connecting the two reed switches for each track to the same pin and simply counting the times the pin is grounded, and then using the IF/THEN statement to set the condition of the two LEDs. This works for a while and then the PIC seems to stop running :(

Here's the revised code:



PORTA = 0 ' declare port level BEFORE port direction = safe power-on
PORTB = 0
CMCON = 7 ' PortA Digital inputs
CCP1CON = 0 ' PWM off
VRCON = 0 ' Voltage reference disabled
OPTION_REG.7 = 0

TRISA=%00000000 'set PORTA as all output
TRISB=%00001111 'set RB4,5,6 &7 as output and the rest input

'DATA @1,word 625,0,word 545,word 750 ' pre-setting EEPROM

@RC_OSC_NOCLKOUT
@WDT_ON
@PWRT_ON
@MCLR_OFF
@BOD_ON
@LVP_OFF
@CPD_OFF
@PROTECT_OFF

' set up outputs to drive LEDs
LED1 var PORTA.1
LED2 var PORTA.0
LED3 var PORTA.7
LED4 var PORTA.6
LED5 var PORTB.7
LED6 var PORTB.6
LED7 var PORTB.5
LED8 var PORTB.4

; set up reed switch inputs
SW0 var PORTB.0
SW1 var PORTB.1
SW2 var PORTB.2
SW3 var PORTB.3

; set up switch counters
SWFLAG1 var Byte
SWFLAG2 var Byte
SWFLAG3 var Byte
SWFLAG4 var Byte

'set all LEDs to off
low led1
low led2
low led3
low led4
low led5
low led6
low led7
low led8

'zero the switch counters
SWFLAG1=0
SWFLAG2=0
SWFLAG3=0
SWFLAG4=0

Main:
' check counters and reset if >2
if SWFLAG1 >2 then
low led1
low led2
SWFLAG1=0
endif
if SWFLAG2 >2 then
low led3
low led4
SWFLAG2=0
endif
if SWFLAG3 >2 then
low led5
low led6
SWFLAG1=0
endif
if SWFLAG4 >2 then
low led7
low led8
SWFLAG2=0
endif

'siding one operation
If SW0=0 Then
swflag1 = swflag1 +1
pause 500
endif
if swflag1=1 then
high led1
endif
If SWFLAG1=2 then
high led2
endif

'siding two operation
If SW1=0 Then
swflag2 = swflag2 +1
pause 500
endif
if swflag2=1 then
high led3
endif
If Swflag2=2 then
high led4
else
endif

'siding three opertaion
If SW2=0 Then
swflag3 = swflag3 +1
pause 500
endif
if SWFLAG3=1 then
high led5
endif
If SWFLAG3=2 then
high led6
endif

'siding four operation
If SW3=0 Then
swflag4 = swflag4 +1
pause 500
endif
if SWFLAG4=1 then
high led7
endif
If SWFLAG4=2 then
high led8
endif

Goto Main

End


When first powered up I can get it working fine, led1 lights the first time sw0 is triggered, then led2 the second time, and then both go out on the third pass of the magnets. This works for all four reed switches, for about 60 seconds and then seems to lock up in what ever state the LEDs are set at. I have 10K pull ups on all input pins, and a 10K pull up on MCLR

Any further comments ?

mister_e
- 18th May 2006, 14:33
At least, your config fuses are not declare the right way. See the following thread
http://www.picbasic.co.uk/forum/showthread.php?t=543


NOW, are you saying that if you change them manually in your device programmer software it doesn't work?

You declare to use an external RC oscillator... are the value of R and C meet the datasheet suggestion? Personnally, i would prefer to use the internal one



' PIC config fuse using MPASM to compile
@ __CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON

malc-c
- 18th May 2006, 17:48
Steve,

I've tried most of the suggestions to include the config settings within the code. The only enties that doesn't halt the compiling process are



@INTRC_OSC_NOCLKOUT
@WDT_ON
@PWRT_ON
@MCLR_OFF
@BOD_ON
@LVP_OFF
@CPD_OFF
@PROTECT_OFF


However these must me ignored by the compiler as the resulting LST file after the code has compiled shows a config setting of



__config _XT_OSC & _WDT_ON & _MCLRE_ON & _LVP_OFF & _CP_OFF


So when I come squirt the HEX file to the PIC via WinPIC pro I manually change the device config settings to RC no clockout, and have tried enabling / disabling WDT and MCLR input as well but it has no affect, the PIC seems to freeze after 60-90 seconds of running the code posted above.

Just to prove it isn't the PIC that's faulty, I programmed a simple "Flash LEDs" using JAL and that's been running for the past hour - so the issue must be somthing with either the PBP code, the communications between PBP and MPSAM or the way MPSAM compiles the files from PBP or the manual settings in WinPIC are being overlooked when the HEX is loaded.. but then why would the code run at all if that was the case ??

On the hardware front, as I'm using the internal OSC (or trying to) I have no Resistors or capacitors, or external crystal. The four reed switches are connected between ground and the first four pins of PORTB, with 10K pull-ups to +5v. The only other components are 8 LEDs and their 8 resistors.

Cheers

Malcolm

malc-c
- 18th May 2006, 20:17
Further Update...

If I keep triggering the LEDs on PORT A (via RB0 and RB1) the PIC runs fine for ages.. I can sit there triggering the reed switches until my hearts content. However if I then trigger RB2 or RB3 and thus the LEDs on RB5,6,7,&8 then it freezes...

I'll try making the last 4 pins of PORTA the inputs and PORTB all output and see what happens

Update:

Well making PORTB all outputs and A0,A1, A6 and A7 inputs (rest port A out) is worse. Now on power up all leds light up in random sequence and the extinguish and it freezes.... I'm going to try a trusty old 12F675 with just 2 inputs and see if that works - I have stack of those PICs so using 1 per pair of sidings is no real hard ship !

malc-c
- 18th May 2006, 21:37
Last update

Well, thinking that it might be the hardware, I stripped the breadboard and started from scratch making sure there was nothing left floating, or tied down to the wrong supply. Loaded the code and tested. The first two inputs (RB0 and RB1) and thier coresponding LEDs (RA1, RA0 and RA7, RA6) can be triggered until the cows come home. However triggering the any of input three or four (RB2, or RB3) causes the thing to freeze.

I'm off to try it with the 12F675's and see if that works.

malc-c
- 18th May 2006, 23:06
It turns out the problem is human error... I used the wrong varable in one of the couter checks... that will teach me to cut and paste and not pay attention ! (I blame it on the wife, kids, cat for interrupting me and thus causing me to overlook the error !)

Thanks for everyones input...

Malcolm

mister_e
- 19th May 2006, 02:35
Well don't worry dude, it happen to everybody... you can't imagine how many keyboard and laptop i must change in a year because i destroyed them by frustration after hours/days/week of hard programming/debugging session.