PDA

View Full Version : Please look over my code



Sam
- 27th March 2016, 00:08
I'm using a 12F675 with 4mhz ceramic osc to control my homebuilt gate opener. I'm activating it with a wireless digital remote unit that has it's own relay, when signal is rx'd the relay simply closes and provides a high (+5v) to GPIO.3. This pin is also held low via a 10k resistor. This then toggles GPIO.0 which I have 2 status LED's hooked cathode to cathode.

The problem is, all will work fine for days then suddenly it will start "toggling". That is, the gate will open, stop for a while then close over and over then simply go back to normal. Very randomly ! My PS is simply a sealed lead acid 12V battery with nothing else connected as of now. I thought the problem might be RF activating the wireless relay so i put a 3 second routine in, same problem so I disconnected the remote completely from the circuit and it happened again today. I currently have the board on my workbench powered by the same battery and it's stable for now, of course.

So if you will please look at my code and see if it's something in there ? I know I'm still not real good at PBP but I've actually had a lot of success with many other projects using PBP and I love it.

Thanks very much for your time,

Sam


'************************************************* ***************
'* Name : This is the one used for the gate opener !!! *
'* Author : SD *
'* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 3/15/2016 *
'* Version : 1.0 *
'* Notes : THIS WORKS MUST HOLD DOWN FOR 3 SECONDS TO TOGGLE*
'* : *
'************************************************* ***************
CMCON=%00000111
ANSEL=%00000000


@ DEVICE pic12F675, XT_OSC
_NOCLKOUT
@ DEVICE pic12F675, WDT_ON
@ DEVICE pic12F675, PWRT_ON
@ DEVICE pic12F675, MCLR_OFF
@ DEVICE pic12F675, BOD_ON

DEFINE OSC 4
INCLUDE "modedefs.bas"

btn var gpio.3
LoopTime var word

'low gpio.0
low gpio.1
low gpio.2
'high gpio.3
low gpio.4
low gpio.5

InputButton:
pause 20
if btn = 1 then Check4Button
goto InputButton

Check4Button:
for LoopTime = 0 to 3000 'Set time button must be down before toggle happens. 50= 50ms, 3000= 3 sec
pause 1
'if btn = 0 then close 'Do not use this line for gate opener
next LoopTime
if btn = 1 then tgl
goto InputButton

tgl:
toggle gpio.0
if gpio.0=1 then
gosub close
endif

if gpio.0=0 then
gosub open
endif
goto InputButton





open
pause 1000 'Orange LED on
high gpio.1
pause 18500
low gpio.1
goto InputButton

close
pause 1000 'Blue LED on
high gpio.2
pause 19000
low gpio.2
goto InputButton

richard
- 27th March 2016, 03:45
three things
1. these two pieces don't have proper labels ,relying on the good nature of the compiler is probably not a good idea




open
pause 1000 'Orange LED on
high gpio.1
pause 18500
low gpio.1
goto InputButton

close
pause 1000 'Blue LED on
high gpio.2
pause 19000
low gpio.2
goto InputButton

2 spaghetti code like that is very difficult to debug or follow the logic of

3 rmw issue possibilities abound

for what its worth try it this way .it may look more complicated but it compiles to smaller code that's more predictable imo
ps not sure what you are doing with gpio.0 , if it is a sensor indicating gate open/closed or moving state you need to add it back in to the code






CMCON=%00000111
ANSEL=%00000000

@ DEVICE pic12F675, XT_OSC
_NOCLKOUT
@ DEVICE pic12F675, WDT_ON
@ DEVICE pic12F675, PWRT_ON
@ DEVICE pic12F675, MCLR_OFF
@ DEVICE pic12F675, BOD_ON

DEFINE OSC 4

trisio= %111001
btn var gpio.3 ; assume low is active
gate_state var byte ; 0=closed ,1= open , 2=moving
open_gate var gpio.1
close_gate var gpio.2
button_count var byte ;counter to bebounce btn and ensure hold time
gpio_shadow var byte ;shadow gpio to eliminate rmw issues
'initialise
open_gate = 0
close_gate = 0
gate_state = 0 ;assume closed on power up
button_count=0
gpio_shadow=0

mainloop:
gosub Check4Button
if (button_count > 30) and (gate_state.1 != 1) then gosub move_gate
pause 100
goto mainloop
Check4Button:
if btn=0 then
button_count=button_count+1 ;if button is active add to count
else
button_count=0 ;reset count
endif
return

move_gate:
pause 1000 ; not sure if this is required
gate_state.1=1 ;gate now moving
if gate_state.0 = 0 then ;its closed so open the gate
gpio_shadow=gpio_shadow | 2 ; high gpio.1 Orange LED on
; same as gpio_shadow.1=1 if you prefer
gate_state.0 = 1
else ; close the gate
gpio_shadow=gpio_shadow | 4 'high gpio.2 Blue LED on
;same as gpio_shadow.2=1 if you prefer
gate_state.0 = 0
endif
gpio=gpio_shadow
pause 18500
gpio_shadow=gpio_shadow & !6
;same as gpio_shadow.1=0 : gpio_shadow.2=0 if you prefer
gpio=gpio_shadow
'while ! btn ; wait for button release if needed
'wend
button_count=0
gate_state.1=0
return

richard
- 27th March 2016, 05:30
just can't help myself
now have flashing led gpio.0 when gate in motion


CMCON=%00000111
ANSEL=%00000000

@ DEVICE pic12F675, XT_OSC
_NOCLKOUT
@ DEVICE pic12F675, WDT_ON
@ DEVICE pic12F675, PWRT_ON
@ DEVICE pic12F675, MCLR_OFF
@ DEVICE pic12F675, BOD_ON

DEFINE OSC 4
trisio= %111000
btn var gpio.3 ; assume low is active
gate_state var byte ; 0=closed ,1= open , 2=moving
open_led var gpio.0
open_gate var gpio.1
close_gate var gpio.2
button_count var byte ;counter to bebounce btn and ensure hold time
RUN_COUNT VAR BYTE
gpio_shadow var byte ;shadow gpio to eliminate rmw issues
'initialise
open_gate = 0
close_gate = 0
gate_state = 0 ;assume closed on power up
button_count=0
gpio_shadow=0
open_led =0
RUN_COUNT=0
mainloop:
gosub Check4Button
if (button_count > 30) and (gate_state.1 != 1) then gosub move_gate ;has button been on for 3 seconds

IF gate_state.1=1 THEN ;is the gate in motion
open_led =! open_led ;flash led while gate moving
IF RUN_COUNT THEN ;should the motion continue ?
RUN_COUNT = RUN_COUNT -1
ELSE
GOSUB STOP_GATE
ENDIF
ENDIF
pause 100
goto mainloop
Check4Button: ; when button_count gets to 30 (3seconds ) we act on gate
if btn=0 then
button_count=button_count+1 ;if button is active add to count
else
button_count=0 ;reset count
endif
return

move_gate:
pause 1000 ; not sure if this is required
gate_state.1=1 ;gate now moving
if gate_state.0 = 0 then ;its closed so open the gate
gpio_shadow.0=1 ;WILL SET open_led = ON
gpio_shadow=gpio_shadow | 2 ; high gpio.1 Orange LED
; same as gpio_shadow.1=1 if you prefer
gate_state.0 = 1
else ; close the gate
gpio_shadow=gpio_shadow | 4 'high gpio.2 Blue LED on
;same as gpio_shadow.2=1 if you prefer
gate_state.0 = 0 ;show closed gate open_led = Off
gpio_shadow.0=0 ; WILL SET open_led = FF
endif
gpio=gpio_shadow ;apply to gpio
RUN_COUNT=185;0 ;set 18.5 second timer for movement
return

STOP_GATE:
gpio_shadow=gpio_shadow & ~6 ;kill movement
;same as gpio_shadow.1=0 : gpio_shadow.2=0 if you prefer
gpio=gpio_shadow ;apply to gpio
'while ! btn ; wait for button release if needed
'wend
button_count=0 ;reset everything ready for next button press
gate_state.1=0; NOW no moving
return

Sam
- 27th March 2016, 14:30
WOW! Thanks for all your help and work Richard!

I'll study it and try it out. I should have done a "block flow" for what I want to happen...


Wait for button press (GPIO.3 is button sense input)

Require button pressed for 3 seconds (GPIO.0 toggles) (orange and blue LEDs hooked cathode to cathode as status)

Energize relay 1 for 18.5 seconds to open gate (GPIO.2)

Wait for button press

Require button pressed for 3 seconds

Energize relay 2 for 19 seconds to close gate (GPIO.1)

Start over

The movement is controlled only by timing, I have no external sensors/limit switches or encoders.

What do these mean in your code ? (!) and (;) I've not used or seen those.

Thanks again, going to try it on the bench this morning.

Heckler
- 27th March 2016, 14:42
Sam,

the ";" simply denotes a comment. Any code after the ";" has no effect on the program other than to provide a comment anyone trying to figure out what the code is supposed to be doing.

the "!" is used in combination with the "=" and means "not equal".

From the PBP manual...
NOT EQUAL TO you can use either "<>" or "!="
so where he has

open_led != open_led
simply means open_led "is not equal to" open_led.
It causes the state of "open_led" to go to the opposite state. Similar to a "Toggle" command.

A couple of other things to consider...
Is there any chance of moisture accumulating on your PCB that would cause it to be erratic??
Is your power supply good and stable?
Why do you use an external ceramic resonator when the PIC has an internal 4MHz oscillator (not that this would cause you problems but it does reduce the I/O pins you have available.)
You might want to consider incorporating a gate open/closed sensor for positive indication of gate position.



dwight

Sam
- 27th March 2016, 15:10
Thanks Dwight, I've always used (') to comment out notes and have used (<>= NOT) but I do now see these in the manual, I just never noticed them before. Good to know, always learning.


A couple of other things to consider...
Is there any chance of moisture accumulating on your PCB that would cause it to be erratic??
Is your power supply good and stable?
Why do you use an external ceramic resonator when the PIC has an internal 4MHz oscillator (not that this would cause you problems but it does reduce the I/O pins you have available.)
You might want to consider incorporating a gate open/closed sensor for positive indication of gate position.


The PCB is in a gasketed weatherproof enclosure and has been totally dry
Power supply is a brand new 12v SLA battery that has been at 12+ volts consistently during this time, I use a to220 7805 with caps
I use the XT OSC because of timing only control and temperature differences
I did consider limit switches or better, IR limit sensors but wanted to keep it simple as possible. But that would be more precise and reliable

Sam
- 27th March 2016, 23:39
Richard,

I loaded your code, I only had to change one thing...

Check4Button:
if btn=0 then 'had to change =0 to =1

And it works great ! I like the flashing LED while the gate is moving. I'll put it back in service and see how it goes, I expect it to be fine now.

You did a lot of work and helped me a lot and I've learned much from your work and I'll continue to refer to how you've done it for my future coding.

You're very much appreciated ! Thanks !

Sam

richard
- 28th March 2016, 00:01
thanks for the feedback and kind words ,but I must confess its a bit fluky I was working on replacing my roller door pgm as you posted your code . I'm also using the exact relay setup you posted in the other thread

went from this rather vague uncommented spaghetti code written 10+ years ago




up VAR gpio.1
lm VAR gpio.4
dwn var gpio.2
cl var gpio.3
tr var gpio.0
b1 var byte
option_reg.5=0 ' gpio 2 not tock
option_reg.6=1 ' weak pullups ?
trisio = %100111 '1,2 output rest i/p
low up ; motor off
low dwn

main:
if tr=1 then main
pause 80
if tr= 1 then main
b1=0
input gpio.4
if lm=0 then
high dwn
b1=3
pause 1000
else
high up
endif

move:
pause 250
b1 = b1 +1
if cl=0 or lm=0 then still
if b1 >100 then still 'taken too long just give up
goto move
still:
low dwn
low up
if tr=0 then still
pause 5000
goto main
end


to this ( with plenty of comments for my future self)
in order to make a door open indicator to feed into the auto light on off switch and the alarm system.
it bench tests ok but its not installed yet , its not a direct replacement of the old chip might need a new pcb




;pic12f683
#CONFIG
__config _INTOSCIO & _WDT_ON & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_ON & _IESO_ON & _FCMEN_ON
#ENDCONFIG
DEFINE OSC 4
' up VAR gpio.1
' lm up VAR gpio.4 || cl
' lm down VAR gpio.5
' dwn var gpio.2
' cl var gpio.4 over current
' tr var gpio.3
maxrun con 2000 ; 2000 = 100 sec
liftoff con 500 ; .5 sec time to move off limit sw
settle con 1500; 1.5 sec time to let door settle before checking closed state
; lets current overload signal deactivate if that stopped door
press_threshold con 20 ; 1 sec
long_press_threshold con 60 ;3 sec

CMCON0=%00000111
ANSEL=%00000000
wpu=48 ;pullups
OPTION_REG.7=0 ;pullups
trisio= %111000
trigger var gpio.3 ; low is active from button or wireless
door_state var byte ; 0=closed ,1= open , 2=moving
open_led var gpio.0 ;lit when door open , flashes when moving
open_door var gpio.1 ;relay up
close_door var gpio.2 ;relay down
up_lim VAR gpio.4 ; low is active limit switches current overload is wire nor'ed to this pin too
dn_lim VAR gpio.5 ; low is active
trigger_cnt var byte ;counter
TR_ACT VAR BYTE
RUN_COUNT VAR word
gpio_shadow var byte ;shadow gpio to eliminate rmw issues
'initialise
open_door = 0
close_door = 0
TR_ACT=0
gosub chk_door
trigger_cnt=0
RUN_COUNT=0


mainloop:
gosub Chk_trigger
if TR_ACT and (door_state.1 != 1) then gosub move_door ;has button been on for 3 seconds
IF door_state.1=1 THEN ;is the DOOR in motion
open_led =! open_led ;flash led while DOOR moving ****** this violates gpio shadow and may cause rmw error
IF(gpio&48) != 48 then RUN_COUNT=0
IF RUN_COUNT THEN ;should the motion continue ?
RUN_COUNT = RUN_COUNT -1
ELSE
GOSUB STOP_door
ENDIF
else
gosub chk_door ; has door been opened or closed manually
ENDIF
pause 50
goto mainloop

Chk_trigger: ; after trigger_count gets to press_threshold we act on trigger release or when long_press_threshold reached
if trigger=0 then
Trigger_cnt=trigger_cnt+1 ;if trigger is active add to count
IF trigger_cnt > long_press_threshold THEN TR_ACT= 2
ELSE
if trigger_cnt > press_threshold THEN ;press_threshold met
IF trigger_cnt > long_press_threshold THEN
TR_ACT= 2 ;FORCE CLOSE ACTION WITH LONG TRIGGER >3 SEC
ELSE
TR_ACT= 1
ENDIF
ELSE ;press_threshold not met
TR_ACT= 0
trigger_cnt=0 ;reset count
ENDIF
endif
return

move_door:
IF TR_ACT=2 THEN door_state.0 = 1 ;FORCE CLOSE ACTION
door_state.1=1 ;door now moving
if door_state.0 = 0 then ;its closed so open the door
gpio_shadow.0=1 ;WILL SET open_led = ON
gpio_shadow=gpio_shadow | 2
door_state.0 = 1
else ; close the door
gpio_shadow=gpio_shadow | 4
door_state.0 = 0 ;show closed door open_led = Off
gpio_shadow.0=0 ; WILL SET open_led = FF
endif
TR_ACT= 0
gpio=gpio_shadow ;apply to gpio
pause liftoff ;get door off limit sw
RUN_COUNT=maxrun;0 ;set timer for movement
return


STOP_door:
gpio_shadow=gpio_shadow & ~6 ;kill movement
gpio=gpio_shadow ;apply to gpio
trigger_cnt=0 ;reset everything ready for next TRIGGER
door_state.1=0; NOW not moving
pause settle ;let door settle
chk_door:
door_state.0 = dn_lim ; see if its closed
open_led = dn_lim
gpio_shadow = gpio
return

Sam
- 1st April 2016, 21:35
UPDATE:

First, thanks for posting all that additional code too Richard. I've saved your 2nd code as "Richard's Gate Controller" on my programming PC and it is running my gate.

On to my update...

It appears I've located the cause of the erratic operation, I use sockets for PIC's and did on this project too. It looks like it's the socket causing the problems, that is, when strange things start happening, I remove and re-seat the PIC in the socket or even just press down firmly on the PIC and it's all good again.

I think there is some oxidation on my socket and GPIO.3 (input pin) starts loosing contact and picking up random noise.

I need to find some type of cleaner to use (vinegar ?) to clean the socket real good then maybe use some silicone grease to keep air and any moisture from getting to them. even though it's in a sealed enclosure. Any suggestions anyone ?

thanks

richard
- 2nd April 2016, 03:06
generally
machined pin IC sockets are used in high reliability applications, I use them in my solar trackers successfully . none have failed yet [touching wood he says]

ruijc
- 2nd April 2016, 11:38
machined pin IC sockets are used in high reliability applications, I use them in my solar trackers successfully . none have failed yet [touching wood he says]

I agree with Richard but they are much more expensive.
If the project has moved from prototype to final version, it's best to solder the mcu and use programming pins to update firmware when needed.

Regards