richard
- 27th September 2022, 12:22
i knocked up this simple example to test a few ideas on fram algorithms while waiting for my pcbs to to arrive. it reads the temp every 30 seconds and once every 6 minutes logs it to a circular buffer in fram with 256 elements of depth. that just over 24 hours worth, the head and tail are also stored in fram so it can resume where it left off when interrupted.
the as6221 temp sensor is the bees knees of temperature sensors , super accurate and no detectable self heating at all
'************************************************* ***************
'* Name : FRAM.BAS *
'* Author : richard *
'* Notice : Copyright (c) 2022 caveat emptor *
'* : All Rights Reserved *
'* Date : 23/09/2022 *
'* Version : 1.0 *
'* Notes : as6221 + MB85RC256V 24HR TEMPERATURE DATA LOGGER *
'* : 256 BYTE CIRCULAR BUFFER IN FRAM PIC12F1822 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
__config _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG
DEFINE INTHAND disp
DEFINE I2C_SLOW 1 ; for high speed osc
DEFINE I2C_HOLD 1 ; chip employs clock stretching
as6221_ADDRESS CON 144
fram__ADDRESS CON 160
OSCCON = $70
DEFINE OSC 32
LATA.0 = 1 ;debug
trisa = %11111111 ;debug
ANSELA = 0
RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $24 ' Enable transmit, BRGH = 1
SPBRG = 64 ' 9600 Baud @ 32MHz, 0.04%
SPBRGH = 3
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
'SEND C TO CLEAR P TP PRINTOUT
clear
PAUSE 2000
hserout [ "READY" ]
SDA VAR PORTA.5
SCK VAR PORTA.4
timer1_reload con 45537 '10mS
millies var word BANK0
rxbuff VAR BYTE[6] BANK0 ;5 CHR + NULL
rxinx VAR BYTE BANK0
rxflg VAR BYTE BANK0
NOW VAR WORD
dTIME VAR WORD
readtime VAR WORD
REG VAR BYTE
Temp var word
dc var word
head_fs VAR BYTE ;fram shadow var
tail_fs VAR BYTE ;fram shadow var
rd_ptr VAR BYTE
inx var word
;fram addr pointers
fram_ptr_t con $100 ;to temperature data store
fram_ptr_v con 0 ;to variable data store
head con 0 ;head_fs
tail con 4 ;tail_fs
inx = RCREG ;DUMMY READ CLR RCIF
T1CON = $21
PIR1 = 0
intcon = $C0
pie1.0 = 1
PIE1.5 = 1
;init fram
inx = fram_ptr_v
I2CREAD SDA,SCK,fram__ADDRESS,inx + head,[head_fs]
I2CREAD SDA,SCK,fram__ADDRESS,inx + tail,[tail_fs]
hserout [ 13,10,"init H/T ",dec head_fs,"/",dec tail_fs]
main:
GOSUB GET_NOW
if ((NOW-readTIME)>3000) then '30 sec ie 3000*10Ms
GOSUB GET_tmp
readTIME = now
endif
if ((NOW-dTIME )>36000) then '6 min LOG READING
GOSUB FWR_tmp
dTIME = now
endif
if rxflg then 'SEND C TO CLEAR P TO PRINTOUT WITH A CR [/R] TERMINATION
hserout [13,10, str rxbuff,13,10 ]
IF rxbuff[0]== "C" THEN
head_fs=tail_fs
I2cwrite SDA,SCK,fram__ADDRESS,inx + head,[head_fs]
ELSEIF rxbuff[0]== "P" THEN
GOSUB fram_read_t
endif
rxflg=0
rxinx=0
endif
goto main
GET_NOW: ;millies x 10
pie1.0 = 0
NOW = MILLIES ;millies x 10mS
pie1.0 = 1
RETURN
GET_tmp: ;READ AND PRINT TEMPERATURE H/T
REG = 0
I2CREAD SDA,SCK,as6221_ADDRESS,REG,[temp.highbyte,temp.lowbyte];
dc = temp*100
dc = div32 128
hserout [ 13,10,"temp c#",9,dec dc/100,".",dec2 dc//100,9,dec head_fs,9,dec tail_fs ]
return
FWR_tmp: ;WRITE "temp" TO BUFFER @HEAD
I2cwrite SDA,SCK, fram__ADDRESS,fram_ptr_t + head_fs*2 ,[dc]
head_fs = head_fs+1
inx = fram_ptr_v
I2cwrite SDA,SCK,fram__ADDRESS,inx + head,[head_fs]
if head_fs=tail_fs then
tail_fs = tail_fs + 1 ;CIRCLE ovrflw
I2cwrite SDA,SCK,fram__ADDRESS,inx + tail,[tail_fs]
endif
return
fram_read_t: 'PRINTOUT BUFFER
inx = fram_ptr_v
I2CREAD SDA,SCK,fram__ADDRESS,inx + tail,[rd_ptr]
hserout [ 13,10,"DATA :-",13,10]
while (head_fs-rd_ptr)
I2CREAD SDA,SCK, fram__ADDRESS, fram_ptr_t + rd_ptr*2,[dc]
hserout [ 13,10,dec3 rd_ptr," temp",9,dec dc/100,".",dec2 dc//100 ]
rd_ptr = rd_ptr + 1
wend
return
asm
disp
BANKSEL 0
BTFSS PIR1,5 ;RXISR
goto t01 ;NEXT ISR
BTFSC _rxflg ,0 ;BUFF full
GOTO SFT
movlw high(_rxbuff+1)
movwf FSR0H
movlw LOW(_rxbuff)
movwf FSR0L
MOVF _rxinx,W
ADDWF FSR0L ,F
INCF _rxinx,F
movlw 6 ;BUFF SIZE
SUBWF _rxinx,W ;full UP ?
BTFSS STATUS ,Z
GOTO NB
CLRF _rxinx ;ROLL OVER
SF
INCF FSR0L,F
CLRF INDF0 ;NULL TERMINATE
BANKSEL 0
BSF _rxflg,0 ;full UP / SET FLAG
SFT
BANKSEL RCREG
MOVF RCREG,W ;JUST CLR FLG
GOTO t01 ;NEXT ISR TO SERVICE
NB
BANKSEL RCREG
MOVF RCREG,W
MOVWF INDF0 ;SAVE CHR
movlw 13 ;TERMINATE ON '/r'
SUBWF INDF0,W
BTFSC STATUS ,Z
GOTO SF ;SET FLAG
;GOTO disp ;RECHECK FIFO
t01 ;tmr1 isr
BANKSEL 0
BTFSS PIR1 ,0
goto ex
BCF T1CON,0 ;stop timer
MOVLW HIGH (_timer1_reload)
ADDWF TMR1H,F
MOVLW LOW (_timer1_reload) ;Add TimerReload to the_
ADDWF TMR1L,F ; value in Timer1
BTFSC STATUS,C
INCF TMR1H,F
BSF T1CON,0 ;START timer
BCF PIR1 ,0
MOVLW 1
ADDWF _millies,F
BTFSC STATUS,C
INCF _millies+1,F
ex
RETFIE
endasm
printout
READY
init H/T 156/132
temp c# 22.63 156 132
temp c# 22.60 156 132
P
DATA :-
132 temp 22.91
133 temp 22.91
134 temp 22.90
135 temp 22.96
136 temp 22.98
137 temp 23.10
138 temp 23.05
139 temp 22.67
140 temp 22.54
141 temp 22.46
142 temp 22.38
143 temp 22.26
144 temp 22.26
145 temp 22.73
146 temp 22.77
147 temp 22.83
148 temp 22.73
149 temp 22.71
150 temp 22.81
151 temp 22.76
152 temp 22.74
153 temp 22.57
154 temp 22.66
155 temp 22.67
the as6221 temp sensor is the bees knees of temperature sensors , super accurate and no detectable self heating at all
'************************************************* ***************
'* Name : FRAM.BAS *
'* Author : richard *
'* Notice : Copyright (c) 2022 caveat emptor *
'* : All Rights Reserved *
'* Date : 23/09/2022 *
'* Version : 1.0 *
'* Notes : as6221 + MB85RC256V 24HR TEMPERATURE DATA LOGGER *
'* : 256 BYTE CIRCULAR BUFFER IN FRAM PIC12F1822 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
__config _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG
DEFINE INTHAND disp
DEFINE I2C_SLOW 1 ; for high speed osc
DEFINE I2C_HOLD 1 ; chip employs clock stretching
as6221_ADDRESS CON 144
fram__ADDRESS CON 160
OSCCON = $70
DEFINE OSC 32
LATA.0 = 1 ;debug
trisa = %11111111 ;debug
ANSELA = 0
RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $24 ' Enable transmit, BRGH = 1
SPBRG = 64 ' 9600 Baud @ 32MHz, 0.04%
SPBRGH = 3
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator
'SEND C TO CLEAR P TP PRINTOUT
clear
PAUSE 2000
hserout [ "READY" ]
SDA VAR PORTA.5
SCK VAR PORTA.4
timer1_reload con 45537 '10mS
millies var word BANK0
rxbuff VAR BYTE[6] BANK0 ;5 CHR + NULL
rxinx VAR BYTE BANK0
rxflg VAR BYTE BANK0
NOW VAR WORD
dTIME VAR WORD
readtime VAR WORD
REG VAR BYTE
Temp var word
dc var word
head_fs VAR BYTE ;fram shadow var
tail_fs VAR BYTE ;fram shadow var
rd_ptr VAR BYTE
inx var word
;fram addr pointers
fram_ptr_t con $100 ;to temperature data store
fram_ptr_v con 0 ;to variable data store
head con 0 ;head_fs
tail con 4 ;tail_fs
inx = RCREG ;DUMMY READ CLR RCIF
T1CON = $21
PIR1 = 0
intcon = $C0
pie1.0 = 1
PIE1.5 = 1
;init fram
inx = fram_ptr_v
I2CREAD SDA,SCK,fram__ADDRESS,inx + head,[head_fs]
I2CREAD SDA,SCK,fram__ADDRESS,inx + tail,[tail_fs]
hserout [ 13,10,"init H/T ",dec head_fs,"/",dec tail_fs]
main:
GOSUB GET_NOW
if ((NOW-readTIME)>3000) then '30 sec ie 3000*10Ms
GOSUB GET_tmp
readTIME = now
endif
if ((NOW-dTIME )>36000) then '6 min LOG READING
GOSUB FWR_tmp
dTIME = now
endif
if rxflg then 'SEND C TO CLEAR P TO PRINTOUT WITH A CR [/R] TERMINATION
hserout [13,10, str rxbuff,13,10 ]
IF rxbuff[0]== "C" THEN
head_fs=tail_fs
I2cwrite SDA,SCK,fram__ADDRESS,inx + head,[head_fs]
ELSEIF rxbuff[0]== "P" THEN
GOSUB fram_read_t
endif
rxflg=0
rxinx=0
endif
goto main
GET_NOW: ;millies x 10
pie1.0 = 0
NOW = MILLIES ;millies x 10mS
pie1.0 = 1
RETURN
GET_tmp: ;READ AND PRINT TEMPERATURE H/T
REG = 0
I2CREAD SDA,SCK,as6221_ADDRESS,REG,[temp.highbyte,temp.lowbyte];
dc = temp*100
dc = div32 128
hserout [ 13,10,"temp c#",9,dec dc/100,".",dec2 dc//100,9,dec head_fs,9,dec tail_fs ]
return
FWR_tmp: ;WRITE "temp" TO BUFFER @HEAD
I2cwrite SDA,SCK, fram__ADDRESS,fram_ptr_t + head_fs*2 ,[dc]
head_fs = head_fs+1
inx = fram_ptr_v
I2cwrite SDA,SCK,fram__ADDRESS,inx + head,[head_fs]
if head_fs=tail_fs then
tail_fs = tail_fs + 1 ;CIRCLE ovrflw
I2cwrite SDA,SCK,fram__ADDRESS,inx + tail,[tail_fs]
endif
return
fram_read_t: 'PRINTOUT BUFFER
inx = fram_ptr_v
I2CREAD SDA,SCK,fram__ADDRESS,inx + tail,[rd_ptr]
hserout [ 13,10,"DATA :-",13,10]
while (head_fs-rd_ptr)
I2CREAD SDA,SCK, fram__ADDRESS, fram_ptr_t + rd_ptr*2,[dc]
hserout [ 13,10,dec3 rd_ptr," temp",9,dec dc/100,".",dec2 dc//100 ]
rd_ptr = rd_ptr + 1
wend
return
asm
disp
BANKSEL 0
BTFSS PIR1,5 ;RXISR
goto t01 ;NEXT ISR
BTFSC _rxflg ,0 ;BUFF full
GOTO SFT
movlw high(_rxbuff+1)
movwf FSR0H
movlw LOW(_rxbuff)
movwf FSR0L
MOVF _rxinx,W
ADDWF FSR0L ,F
INCF _rxinx,F
movlw 6 ;BUFF SIZE
SUBWF _rxinx,W ;full UP ?
BTFSS STATUS ,Z
GOTO NB
CLRF _rxinx ;ROLL OVER
SF
INCF FSR0L,F
CLRF INDF0 ;NULL TERMINATE
BANKSEL 0
BSF _rxflg,0 ;full UP / SET FLAG
SFT
BANKSEL RCREG
MOVF RCREG,W ;JUST CLR FLG
GOTO t01 ;NEXT ISR TO SERVICE
NB
BANKSEL RCREG
MOVF RCREG,W
MOVWF INDF0 ;SAVE CHR
movlw 13 ;TERMINATE ON '/r'
SUBWF INDF0,W
BTFSC STATUS ,Z
GOTO SF ;SET FLAG
;GOTO disp ;RECHECK FIFO
t01 ;tmr1 isr
BANKSEL 0
BTFSS PIR1 ,0
goto ex
BCF T1CON,0 ;stop timer
MOVLW HIGH (_timer1_reload)
ADDWF TMR1H,F
MOVLW LOW (_timer1_reload) ;Add TimerReload to the_
ADDWF TMR1L,F ; value in Timer1
BTFSC STATUS,C
INCF TMR1H,F
BSF T1CON,0 ;START timer
BCF PIR1 ,0
MOVLW 1
ADDWF _millies,F
BTFSC STATUS,C
INCF _millies+1,F
ex
RETFIE
endasm
printout
READY
init H/T 156/132
temp c# 22.63 156 132
temp c# 22.60 156 132
P
DATA :-
132 temp 22.91
133 temp 22.91
134 temp 22.90
135 temp 22.96
136 temp 22.98
137 temp 23.10
138 temp 23.05
139 temp 22.67
140 temp 22.54
141 temp 22.46
142 temp 22.38
143 temp 22.26
144 temp 22.26
145 temp 22.73
146 temp 22.77
147 temp 22.83
148 temp 22.73
149 temp 22.71
150 temp 22.81
151 temp 22.76
152 temp 22.74
153 temp 22.57
154 temp 22.66
155 temp 22.67