Code:
'****************************************************************
'* Name : MSP to PIC Nixie clock.BAS * *
'* Author : [Dwight Merkley] *
'* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 1/2/2016 *
'* Version : 1.0 *
'* Notes : *
'* : *
'****************************************************************
#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_25 & _LVP_OFF
#endconfig
DEFINE OSC 8
include "ALLDIGITAL.Pbp"
'==================================================
H10 VAR PortC.0 'hours tens digit enable
H1 var PortC.1 'hours ones digit enable
M10 var PortC.2 'minutes tens digit enable
M1 var PortC.3 'minutes ones digit enable
symbol PORT_PIN = PORTC 'used to sequentially enable portC.0-3 nixie tubes
res var PortC.4 '0-9 digit reset
clk var PortC.6 '0-9 digit counter input
ena var PortC.7 'ENA on nixie decade counter
led var LATC.5 'pwm led backlight
sw1 var portA.2 'input upper switch
sw2 var portA.1 'input lower corner switch
swflg var bit 'bit used to debounce switch pushes
ts var portB.4 'OneWire Temperature sensor
rxE var portB.5 'input rx data from esp8266
txE var portB.7 'tx data to esp8266
fet var portB.6 'High Voltage shutdown
tube var byte 'refrence tube 0-3 [hh h mm m]
hh var byte 'variable holding hours
h12 var byte
mm var byte 'variable holding minutes
ss var byte 'variable holding seconds
d1 var byte
d2 var byte
d3 var byte
d4 var byte
s1 var byte
s0 var byte
mode var byte '12 to 24 hour conversion flag'
num var byte 'current digit's pulse count
x var byte 'general purpose variable
y var byte 'counter to track time between esp serial request output
dgt var byte
temp var byte 'temporary lcd display data
IntCnt var word
IntFlag var bit
dispflag var bit 'flag to indicate if display should be off
temptime var byte 'var to determine if time to check temperature
'the following var's are used in the anti-cathode poisoning routine
position var byte
numx var byte
cath var byte
index var byte
'-------------[variables and constants for temperature routine]--------------
DS18B20_9bit CON %00011111 ' set resolution on DS18B20 93.75ms, 0.5 C
DQ VAR PortB.4 ' One-wire Data-Pin "DQ" on PortB.4
Busy VAR BIT ' Busy Status-Bit
Raw VAR WORD ' RAW Temperature readings
TempF VAR WORD ' Temp in deg F
Cold_Bit VAR Raw.BIT11 ' Sign-Bit for +/- Temp. 1 = Below 0 deg C
Sign VAR BYTE[1] ' +/- sign for temp display
TempH var word ' var for highest temp
TempL var word ' var for lowest temp
SignH var byte[1]
SignL var byte[1]
C VAR WORD ' Celsius
F VAR WORD ' Fahrenheit
INCLUDE "Temp_Convert.pbp"
'===================================================
'===================================================
TRISA = %00000110
TRISB = %00100000
TRISC = %00000000
WPUA = %00000110
OSCCON = %01110000 'set internal osc to 8 mhz
'====================================================
espbaud con 84
hh = 99
mm = 00
ss = 00
mode = 2 'modes
'0=24 hour only display
'1=12 hour only display
'2=24 hour with alternating 12 hour
' for dummies who don't know 24 hour time
IntCnt = 0
temp = 0
' -----[ Timer setup ]------------------------------
disable interrupt
On Interrupt goto MyInt 'define where interrupts should go
INTCON = %11000000 'now enable GIE,PEIE,x,x,GPIE,x,x,x
T1CON = %00110101 'Enable Timer1 with 1:8 prescaler
PIE1 = %00000001 'Enable Timer1 overflow interrupt
PIE2 = %00000000
PIR1.0=0 'clear the timer1 interupt flag
txe=1 'high the serial output pin, needs to start high
'***************************************************
'======== MAIN ===========
'***************************************************
Enable Interrupt
Main:
if swflg = 1 and sw1=1 then swflg = 0 '(sw debounce) clear swflg when switch released
if swflg = 0 and sw1=0 then
swflg = 1
if mode = 0 then
mode = 1 'switch to 12 hr mode
goto SkipSw
endif
if mode = 1 then
mode = 2 'switch to 24 hrr mode with 12 hr flash
goto SkipSw
endif
if mode = 2 then
mode = 0 'switch to 24 hr mode
endif
endif
SkipSw:
'an interrupt is generated every .005 sec
'so clear the IntFlag and cycle to the next nixie tube
if IntFlag=1 then
IntFlag=0
IntCnt = IntCnt + 1
gosub Tubes
endif
if IntCnt > 199 then gosub NextSec 'time to increment seconds
'this next routine fires every 15 minutes between 55 and 58 seconds
'it causes all digits in each nixie to be cycled to prevent
'cathode poisioning
if mm//15=0 and (ss >54 and ss<58) then
if intcnt//10 = 0 then gosub NixieBurn
endif
'this routine blanks the display between 2200 and 0600
if (hh>21) or (hh<6) then 'turn display off between 2200 and 0600
dispflag = 0
else
dispflag = 1
endif
'this routine only runs on startup and waits for 30 sec
'then it goes and reads the time from the ESP module
if hh = 99 then
d1=s0
d2=s1
dispflag = 1
if ss=30 then gosub GetTime
endif
'this routine sets the clock once a day at 0500
if hh=5 and mm=0 and ss=0 then gosub GetTime
toggle led 'for backlight brigtness at 50%
' use O-Scope to determine Main loop timing
goto Main
'***************************************************
' interrupt every 5 msec
'***************************************************
disable interrupt
MyInt:
IntFlag=1 ' INT has fired so set this flag for Main code usage
'>H & L size determine INT timing, INT every .005 seconds
TMR1H = $FB ' reset timer1h
TMR1L = $1F ' reset timer1l
PIR1.0 = 0 ' clear timer1 overflow flag
resume 'to Main
enable interrupt
'=============================================================
' increment seconds and trickle down time
'=============================================================
NextSec:
intCnt = 0
ss = ss +1
if ss = 60 then
ss = 00
mm = mm + 1
endif
if mm = 60 then
mm = 0
hh = hh + 1
endif
if hh = 24 then
hh = 0
endif
if hh>12 then
h12=hh-12
else
h12=hh
endif
d1=mm//10
d2=mm/10
d3=hh//10
d4=hh/10
s1=ss/10
s0=ss//10
if mode=1 then '12 hr only mode
d3=h12//10
d4=h12/10
endif
'this routine causes the display to alternate between 24 and 12 hr display
if mode = 2 and (s0=0 or s0=5) then '24 hr mode with
d3=h12//10 '12 hr overlay at 0 & 5 sec
d4=h12/10
endif
return
'=================================================
'--- Routine to cycle all digits on all tubes ---
'--- to prevent cathode poisoning (look it up) ---
'=================================================
NixieBurn:
numx=numx+1
if numx=10 then numx=0
for position=0 to 3
index=numx+position
if index>9 then
index=index-10
endif
lookup2 index,[1,6,2,7,5,0,4,9,8,3],cath
if position = 0 then d1=cath
if position = 1 then d2=cath
if position = 2 then d3=cath
if position = 3 then d4=cath
next position
return
'=============================================================
' display next NIXIE digit
'=============================================================
Tubes:
PORT_PIN.0[tube] = 0 'Turn OFF the current tube
if dispflag = 0 then
led = 1
return 'display is off so skip tubes
endif
tube=tube + 1
if tube > 3 then tube = 0
Digit:
high res 'reset the decade counter
@ nop
low res 'release the reset
lookup2 tube,[d4,d3,d2,d1],num
for x = 1 to num 'pulse the clock for "num" counts
high clk
@ nop
low clk
next x
PORT_PIN.0[tube] = 1 'Turn ON the next tube
return
'=============================================================
' Get TIME from ESP8266-01 NTP Time Server
'=============================================================
Disable Interrupt
SerTmout:
led=0
pause 200
led=1
pause 200
led=0
pause 200
led=1
pause 200
GetTime:
PORT_PIN.0[tube] = 0 'Turn OFF the current tube
' Wait for >,CR,LF from ESP module
serin2 rxe,espbaud,3000,SerTmout,[wait(">"),wait(13),wait(10)]
' ESP module expects "Time?" before it will give hhmmss
' to change this modify the ESP code
serout2 txe,espbaud,["Time?"]
serin2 rxe,espbaud,3000,SerTmout,[dec2 hh,dec2 mm, dec2 ss]
' set NIXIE tube positions for their
' respective h h m m, d4,d3,d2,d1
d4=hh/10
d3=hh//10
d2=mm/10
d1=mm//10
s1=ss/10 ' s0 & s1 only gets used when displaying seconds
s0=ss//10 ' untill time retreval from ESP module at 30 sec
Return
Enable Interrupt
'=============================================================
' Read Temp Sensor and convert to deg F
'=============================================================
disable interrupt
GetTemp:
PORT_PIN.0[tube] = 0 'Turn OFF the current tube
OWOUT DQ,%001,[$CC, $4E, 0, 0, DS18B20_9bit] 'set resolution of sensor
Start_Convert:
OWOUT DQ,%001,[$CC, $44] ' Skip ROM search & do temp conversion
Wait_Convert:
OWIN DQ,%100,[Busy] ' Read busy-bit
IF Busy = 0 THEN Wait_Convert ' Still busy..?, Wait_Convert..!
OWOUT DQ,%001,[$CC, $BE] ' Skip ROM search & read scratchpad memory
OWIN DQ,%010,[Raw.byte0, Raw.byte1]' Read two bytes / end comms
'-------------- Convert_Temp: -----------------------
Sign="+"
IF Cold_Bit = 1 THEN 'it's below zero Celsius
C=(ABS Raw>>4)*-10 'so shift the ABS value right and mult X -10
ELSE
C=(Raw>>4)*10 'else shift value right and mult X 10
ENDIF
@ CtoF _C, _F ; Convert Celsius to Fahrenheit
'converted value will be X 10, ie. 756=75.6 deg F
'so devide by 10 to get whole degrees
IF f.15=1 THEN Sign="-" 'if converted value is below zero F then sign is "-"
TempF = (ABS f)/10 'take tha ABS value and /10
IF f//10 >4 THEN TempF=TempF+1 'check remainder, if >4 then round up
PIR1.0 = 0 ' clear timer1 overflow flag
return 'with TempF containing current temperature
enable interrupt
'===========================================
end
and here is the code that runs on the ESP8266-01 module
Code:
memclear
cls
timesetup(-7,0)
baudrate 9600
serialtimeout 2000
delay 1000
button "Exit " [Exit]
[Main]
timer 100 [PicSer]
wait
'
[PicSer]
serialflush
input picIN
picIN = mid(picIN,1,5)
if picIN == "Time?" then gosub [gettime]
wait
'
[gettime]
bla = time()
hh = mid(bla,12,2) 'hour
mm = mid(bla,15,2) 'min
ss = mid(bla,18,2) 'sec
'
picOUT = hh & mm
picOUT = picOUT & ss
serialprint picOUT
'
return
'
[Exit]
end
this has been fun and a real challenge
Bookmarks