PDA

View Full Version : Fram temperature logger



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

Ioannis
- 28th September 2022, 11:05
Nice chip this AS6221. But how on earth can one solder this tiny little chip?

I think this line:



hserout [ 13,10,"temp c#",9,dec dc/100,".",dec2 dc//100,9,dec head_fs,9,dec tail_fs ]


can be


hserout [ 13,10,"temp c#",9,dec dc/100,".",dec2 dc,9,dec head_fs,9,dec tail_fs ]


The dc variable holds the temp in x1000, right? So printing the last 2 digit with DEC2 does not need //100.

Ioannis

richard
- 28th September 2022, 12:20
Nice chip this AS6221. But how on earth can one solder this tiny little chip?

i can't i can barely see it. used a dev board , their not cheap either.
when i first saw the board i thought they had sent me a blank board the smd resistors and caps are grains of sand
or dust specs


The dc variable holds the temp in x1000, right? So printing the last 2 digit with DEC2 does not need //100.

no its temp x100 and the second term is the remainder {modulus) I'm not confidant that a simple division would ever be correct

Ioannis
- 28th September 2022, 13:12
no its temp x100 and the second term is the remainder {modulus) I'm not confidant that a simple division would ever be correct

I am not sure I follow.

dc var as I understand, holds the value say, 2236. This represents the value 22.36 degrees celcious.

To display it as integer, dc/100 is used and for the floating part, DEC2 dc will display the least significant digits, that is 36. So the use of //100 I think, only increases the code size.

Ioannis

richard
- 28th September 2022, 13:34
DEC2 dc will display the least significant digits

and it does , that's another one of those things i have micro managed forever for no good reason
duly noted thanks