BrianP Senior Member
 Joined: 30/03/2017 Location: AustraliaPosts: 292 |
| Posted: 04:42am 01 Jan 2018 |
Copy link to clipboard |
 Print this post |
|
Happy New Year shedders!
Aplogies for this longish post
Given this is the season for relaxation & idle moments - I share my current project of the door entry routine for the local public hall.
If anyone could find the time to peruse & advise of any danger lurking in the code (still in development) I would be eternally grateful.
My programming skills are anal at best - functionality beats efficient code, but I do ultimately aim for best practice (ageing brain - 75 this year. It seems a long while since the Commodore basic programming days of the 70s).
There is an original working base version of this program running on a colour Maximite (proof of concept) which was developed in a big hurry & installed as an emergency temporary fix when the existing proprietry hardware went past its use-by date & required in excess of $1100 AU to be replaced (7x5cm circuit board with a PIC & peripherals!). The Maximite is working fine, but we don't have the ability to remotely modify program code or update the entry codes database.
This current project runs on one of Grog's/Rob's marvellous E28 boards, with added power, RTC & RS232-TTL modules, plugged to a hardware interface board (done on veroboard as a once-off). We use 2 E28 ports to drive the keypad status LED & toggle the R/G LED polarity.
The hardware setup consists of an external numeric entry keypad with a R/G status LED & piezo beeper, battery backed 12v power supply, RS232 connection to an Internet connected Win 10 laptop for remote entry codes & program updates, relay interface to control the the door lock/unlock. As is commonly the case the door has its own IR entry movement detection, operational when unlocked. Once again, the interface board is a veroboard item (one-off). By the time one works out the hardware layout & interconnects it doesn't seem to be worthwhile to do a nice custom circuit board for a one-off project, although it would save heaps of jumper connects.
Before Grogs gets too nervous about Win 10 the Internet connection is cellular & doesn't do auto updates (verified to be so - at the moment).
The remote connection allows maintenance of the valid entry codes database on a dynamic basis, & and program tweaks as we all know is a never-ending feast. I have used the console connection rather than a conventional com port for the serial access so as to allow remote program updates which can only be done when the program is not running.
On the laptop we run a couple of very simple DOS MMbasic routines which allow on-demand update of the current entry codes list & a timed periodic download appended to a text file of the the current entry log.
Entry of door access codes via the external keypad is normally a 4 or 5 digit number terminated by a hash, but up to 10 digits are accepted (as in the default emergency code). This code exists in case the current codes list is not yet updated after a restart & is replaced by the current codes list.
Any questions happily answered...
B
--------------------------------------------------------------
'FWMAC.bas v.5.11 <c> BCP 2018-01-01 for Micromite MK II E28 ' 'Program to read keypad input, check against array of valid codes, lock or unlock door ' 'reserved pins unavailable for program - 1,8,11,12,13,17,18,19,20,27,28 ' 'Keypad rows 1-4 on pins 2-5, columns 1-3 on pins 6,7,9 'pin 26 = digital Door control relay out (contacts N/C - relay not energised for door locked) 'Pin 25 = digital BEEP out for beeper transistor switch 'pins 21,22 = KEYLED polarity swap outputs for green/red LED 'pins 17,18 = RTC 'pin 14 = digital oc door not closed (dnc) switch 5v 'free pins 15,16 5v tolerant, 10,23,24 3.3v only ' 'Comms: if 1st chars received are "*"+chr$(13) then next data is valid$() codes list terminated by "*" 'Comms: if 1st chars received are "%"+chr$(13) then send event log terminated by "%" 'Comms: if 1st chars received are "?"+chr$(13) then send current codes list 'Comms: if 1st chars received are "^"+chr$(13) then send door status 'Comms: if 1st chars received are "["+chr$(13) then lock door 'Comms: if 1st chars received are "]"+chr$(13) then unlock door ' option explicit:option base 0:option clocktrim -4: ''' option autorun on dim edate$, update, remotelock, sendevent, uc, padkey$, press, remoteunlock, lockstatus, delog, csec, esec dim success, logcount, invalidcount, hash, hsh$, key$, lock, firstrun, a, keycode, status$, scodes, con$ const doorlock=26, beep=25, dnc=14, led1a=21, led1b=22, led2a=23, led2b=24, cmax=999999 edate$="":update=0:remotelock=0:remoteunlock=0:sendevent=0:uc=0:scodes=0:remoteunlock=0:lockstatus=0 padkey$="":timer=0:press=0:success=0:logcount=0:InvalidCount=0:hash=0:Key$="":lock=0 pin(doorlock)=0:setpin doorlock, dout:lock=1 'door lock relay (1=open, 0=locked) pin(led1a)=0:setpin led1a, dout 'keypad LED Green (Bi-colour LED toggle) pin(led1b)=0:setpin led1b, dout 'keypad LED (Red) (Bi-colour LED toggle) 'pin(led2a)=1:setpin led2a, dout 'keypad LED Green (Bi-colour LED toggle) 'pin(led2b)=0:setpin led2b, dout 'keypad LED (Red) (Bi-colour LED toggle) pin(beep)=0:setpin beep, dout 'beep (1=beep, 0=off) pin(dnc)=0:setpin dnc, oout 'dnc switch detect dim valid$(99) length 51 'list of valid entry codes dim event$(99) length 90 'event logging & door status with date/time stamp settick 4*3600000, settime, 4 'set clock every 4 hours settick 1000, SECS, 3 'start seconds counter csec ENTRY 'call keypad enable '''''''''''''''''''''''''''''''''''''''RTC gettime 'currently not connected ' for a=0 to 99:read valid$(a):if valid$(a)="*" then valid$(a)="":a=99 'load whatever inbuilt codes exist next a ' padkey$=" | controller started | FWMAC.bas v.5.11":firstrun=1:ADDLOG :padkey$="":VALIDBEEP :LEDRED ' do 'main program loop START: CONSIN if press>10 then INVALIDENTRY :ADDLOG :timer=0:LOCKOUTBEEP :press=0:padkey$="":goto START 'too many keypresses if hash=0 or padkey$="" then goto NOPRESS 'no keypad entry - check for control codes VALIDCHECK if success then VALIDENTRY :TOGGLELOCK :ADDLOG RESET: if not success then INVALIDENTRY :ADDLOG padkey$="":success=0:hash=0 'add to log, reset ready for next attempt ' NOPRESS: 'input not 0 - 9 if press>0 and timer>5000 then press=0:success=0:goto RESET 'key press but no # for 5 sec ' other tasks not related to keypad entry if sendevent=2 then SENDLOG :sendevent=0 if scodes=2 then SENDCODES :scodes=0 if update=2 then VALIDUPDATES 'do codes update if remotelock=2 then lock=0:padkey$=" | Remote Lock Override ":TOGGLELOCK :ADDLOG :remotelock=0:padkey$="" if remoteunlock=2 then lock=1:padkey$=" | Remote Lock Override ":TOGGLELOCK :ADDLOG :remoteunlock=0:padkey$="" if lockstatus=2 then padkey$=" | Remote Lock Status Read ":ADDLOG :remotelock=0:padkey$="":lockstatus=0 if delog=2 then deletelog :delog=0 a=sendevent+scodes+update+remotelock+remoteunlock+lockstatus+delog:if a and timer>5000 then RESETVAR loop 'start over end ' sub ADDLOG if lock then status$="locked" if not lock then status$="unlocked" DATESWAP :event$(logcount)=edate$+" | "+time$ if firstrun=1 then firstrun=0:event$(logcount)=event$(logcount)+padkey$+" | door "+status$:? event$(0):logcount=1:exit sub if remotelock>0 or remoteunlock>0 or lockstatus>0 then event$(logcount)=event$(logcount)+padkey$+" | door "+status$:DOLOG :exit sub hsh$="":if not hash then hsh$=" | No hashkey" if success then event$(logcount)=event$(logcount)+" | Granted | "+padkey$+" | door "+status$ if not success then event$(logcount)=event$(logcount)+" | Denied | "+padkey$+hsh$+" | door "+status$ DOLOG 'increment log end sub ' sub CONSIN con$=inkey$:if con$=chr$(13) then CONCHK :exit sub if con$="*" then update=1:esec=csec 'start timeout count if con$="%" then sendevent=1:esec=csec if con$="?" then scodes=1:esec=csec if con$="[" then remotelock=1:esec=csec if con$="]" then remoteunlock=1:esec=csec if con$="^" then lockstatus=1:esec=csec if con$="&" then delog=1:esec=csec if con$="#" then hash=1 if asc( con$)>47 and asc(con$)<58 then padkey$=padkey$+str$(val(con$)):press=press+1 'numeric key entry timer=0 end sub ' sub CONCHK if csec-esec>2 then RESETVAR:exit sub 'more than 2 sec since last entry, ignore & cancel if update then update=2 if sendevent then sendevent=2 if scodes then scodes=2 if remotelock then remotelock=2 if remoteunlock then remoteunlock=2 if lockstatus then lockstatus=2 if delog then delog=2 end sub ' sub DATESWAP edate$=right$(date$,4)+mid$(date$,3,3)+"-"+left$(date$,2) end sub ' sub DELETELOG local a:for a=0 to 99:event$(a)="":next:? "Eventlog deleted." end sub ' sub DOLOG ? event$(logcount) if logcount<99 then logcount=logcount+1 if logcount=99 then logcount=0 'go round again & overwrite if array full end sub ' sub ENTRY keypad KeyCode, KP_INT, 2, 3, 4, 5, 6, 7, 9 ? "keypad enabled" end sub ' sub INVALIDBEEP pulse beep, 2000 end sub ' sub INVALIDENTRY invalidcount=invalidcount+1:if invalidcount>6 then LOCKOUTBEEP :pause 5000:invalidcount=0 'lockout for 5sec INVALIDBEEP :press=0:'? "INVALID ENTRY" end sub ' sub KEYBEEP pulse beep, 20 end sub ' sub KP_INT if KeyCode=11 then hash=1:if press=0 then hash=0 if keycode<10 then padkey$=padkey$+str$(KeyCode):Key$="":press=press+1:timer=0 pulse beep, 100 end sub ' sub LEDGREEN pin(led1a)=0:pin(led1b)=1 end sub ' sub LEDRED pin(led1a)=1:pin(led1b)=0 end sub ' sub LOCKOUTBEEP pulse beep, 5000 end sub ' sub PRINTLOG local a:keypad close:for a = 0 to 99:if event$(a)>"" then ? event$(a):next:ENTRY end sub ' sub RESETVAR sendevent=0:scodes=0:update=0:remotelock=0:remoteunlock=0:lockstatus=0:delog=0:esec=0 'key entry timeout end sub ' sub SECS csec=csec+1:if csec>cmax then csec=0 end sub ' sub SENDLOG local a:keypad close:for a=0 to 99:if event$(a)>"" then print event$(a):event$(a)="" next a:print "%":sendevent=0:ENTRY end sub ' sub SENDCODES local a:keypad close:for a=0 to 99:if valid$(a)>"" then ? valid$(a) next a:scodes=0:ENTRY end sub ' sub settime '''''''''''''''''''''''''''''''rtc gettime end sub ' sub TOGGLELOCK lock = not lock:pin(doorlock)=lock:if lock then LEDRED else LEDGREEN ''''if not lock then LEDGREEN end sub ' sub VALIDBEEP pause 500:pulse beep, 100:pause 150:pulse beep, 50 end sub ' sub VALIDCHECK local a:success=0:for a = 0 to 99 :if val(valid$(a))=val(padkey$) then success=1:padkey$=valid$(a):a=99 next end sub ' sub VALIDENTRY press=0:VALIDBEEP :'? "Entry Valid" end sub ' sub VALIDUPDATES keypad close 'temporarily disable keypad during codes update for uc=0 to 99:valid$(uc)="":next:uc=0:timer=0:? "Ready to receive codes..." do while valid$(uc)<>"*" if timer>10000 then uc=0:update=0:? "Codes timeout!":ENTRY :exit sub 'timeout after 10 seconds if not completed line input valid$(uc) if valid$(uc)="*" then uc=0:update=0:? "Codes receive finished":ENTRY :exit sub 'update done if uc<99 then uc=uc+1 loop end sub ' data "0356822077 Default Emergency Code","*" ' |