Picaxe Casio Calculator Data Logger II

Anobium

Senior Member
I have just completed the Picaxe Casio Calculator Data Logger II. This was inspired by a piece of work completed by Mike Fenton. See here - the major differences 1) handles all the data processing, 2) bi-directional communications for setup and config and 3) up to 1530 samples.

I have built upon this good work with the M series Picaxe chips and I have a completed data logger based on the Casio Graphic Calculator.

Essentially, the Picaxe is the sensor. The Picaxe handles the communication and timing between to and from the Casio Graphic Calculator. The Casio Graphic Calculator sends commands, in terms of setup data and requests for information, and the Casio Graphic Calculator handles the data and the graphics.

The data logger can store 255*6 pages of data. This information is overwritten when the pages are full. Samples can be taken between 2 seconds and 6 minutes. The Casio Graphic Calculator shows the results dynamically on the graphics screen.

You can use Casio Graphic Calculator to analyse the data or you can transfer to your PC. You can also regraph any page of data and you can reset a data log from where you left off.

I have posted a video on YouTube of the Casio Graphic Calculator Data Logger II. See the YouTube video here.

High level details of the code
The Casio Graphic Calculator communicates with the Picaxe via TTL. This requires only a very simple circuit.
The Casio Graphic Calculator to PC link is a little trickier but not hard. These circuits are available on the web.
The Casio Graphic Calculator can send up to 28 variables (real numbers) to the Picaxe (not sure what you will be doing with real numbers.... integers sort of work with the Picaxe...)
The Picaxe can response with variable up to 65535 (or you could implement two complement and handle this in the Casio Graphic Calculator for negative numbers).
The Picaxe has a simple timer looop, this can overridden by an external switch event.
To send data from the Casio Graphic Calculator is
Send (variable)

To receive data into the Casio Graphic Calculator is
Receive (variable)

The code in the Casio Graphic Calculator revolves around the getting data and handling display. Luckily, I had this calculator for my work many years ago and the programming language came back with some ease.


If anyone is interested in the Casio I will share. Send me a message, I could not post as CODE in this posting.

I am using the data logger to capture the temperature every time my Gas meter uses one unit of gas but this solution could be used for many different types of data logging. These calculators are very common schools and this would be a great learning aid.

Anyway, another project done. I needed a data logger - now I have one.

Anobium
 
Last edited:

Anobium

Senior Member
Graph of data transferred to Excel

This is a graph of data that has been transferred to Excel.



01072012.jpg
 
Last edited:

westaust55

Moderator
If anyone is interested in the Casio I will share. Send me a message, I could not post as CODE in this posting.

Anobium
You are limited to approx 10,000 characters within a post and attachment sizes can be limited but:
1. Have you tried to attached as a .bas file?

2. broken the code into say 2 parts for attachment is size is still a problem. (You can have up to 2 attachments on one post).


To attach a file:
1. click on the paper clip icon in the toolbars at the top of the post window. (If you cannot see it, then click on the Go Advanced" button at the bottom right of post/edit window)
2. In the Attachment Management window:
(a) click on add file at top right
(b) click on Select File
(c) browse to and select your .bas (or other) file
(d) click on the Upload File button
(e) once the file has uploaded and you see an icon on the bottom left of the Attachment Management window click the Done button at the bottom right.

3. Submit your post as usual.
 

Anobium

Senior Member
Picaxe Casio Calculator Data Logger II - Code 'Casio 16 v.05'

Code:
#rem


This model supports DS18B20.  The CASIO displays integer temp values.

The 'Timer override switch' will cease the timed delay and output the current temp immediately to the Casio.



                                    ÚÄÄÄÄÄÄÄÄ¿
                                5v  ³1     18³ 0v
                   (Program Port) > ³2     17³ c.0 > LED out (& Program Port)
                    Sensor In c.4 > ³3     16³ c.1 < TTL Serial from Casio
        Timer Override Switch c.3 > ³4     15³ c.2 > TTL Serial out to Casio
                                    ÀÄÄÄÄÄÄÄÄÙ

 v.05                                    
 corrected error in calc of fractional values 
 added support for Negative values

Regarding Timer Override Switch c.3.
   For the application I am using I have this connected to 5 minute timer.  This event ensures I get events event 5 mins.  I have the timing Casio variables I & J set to 255 and 255 to ensure the external Timer Override Switch c.3 is being used as the timer. 

#endrem

#no_data


' Support for DS18B20
Symbol TReading = W0
Symbol Whole = B3
Symbol Fract = B4
Symbol SignBit = B5
Symbol Digg = B6
Symbol TempC_100 = W4

symbol temp = b0
symbol indata1 = b1
symbol indata2 = b2
symbol indata3 = b3

symbol valueout = w6

symbol ignoredelays = b17
symbol vname = b18
symbol checksum = b19

	' 65 53 5
symbol byteval2 = b20
symbol byteval1 = b21
symbol hnunitsval = b22

symbol innerloop = b27
symbol outerloop = b26

symbol units = b27
symbol tens= b26
symbol hundreds = b25
symbol thousands = b24
symbol tenthousands = b23

symbol ledport = c.0
symbol casioInport = c.1
symbol casioOutport = c.2
symbol overrideswitch = pin3
symbol adcport = c.4
setfreq m16

' Flash the LED just to show the Picaxe has rebooted
for temp = 1 to 3
	high ledport
	pause 200
	low ledport
	pause 100
next

valueout = time
ignoredelays = 0

main:

	indata1 = $FF ; set up a non-valid value
	serin casioInport, T9600_16, indata1 ; receive 1 byte
	
	
	
	if indata1 =$15 then ; if a byte was received 
	{	high ledport
	
		' Send inital response, Picaxe is here!
		serout casiooutport, T9600_16, ( $13 )
		
		'Await for the Request Packet and obtain Variable name
		' bytes 1-5
		serin casioInport, T9600_16, (":"), indata1, indata2, indata2, indata2
		' sertxd ("Casio : ", indata1 ,13,10)
		' bytes 6-11
		serin casioInport, T9600_16, indata2, indata2, indata2, indata2, indata2, indata2
		
		' the 12th byte has the variable name		
		serin [4000, fin1],casioInport, T9600_16, vname
		' sertxd ("Casio Variable: ", #vname ,13,10)
		
		' pause to consume the bytes sent by Casio
		pause 250
		
		' Handle Request for Data
		' indata1 contain R[EQ]
		' or indata1 contain V[AL]
		
		if indata1 = "R" then	
			
			' Send Picaxe response to Request Packet
			serout  casiooutport, T9600_16, ( $06 )
			
			' if the CASIO sends 'r' then this is the time override command
			if vname = 205 then
				' set to 2. Means this Request and the next Request for info will ignore any delays
				ignoredelays = 3
				' sertxd ("Casio Variable: ", vname ,13,10)
			end if
			
			
			' Casio responds with $06 - consume byte, but do nothing
			serin casioInport, T9600_16, indata1
		
			if indata1 <> $06 then 
					sertxd ("Casio Error #1 code: ", #indata1,13,10)
			end if
		
		
			' Change the checksum from baseline of variable of A.  Easier than recalculating checksum
			'	checksum = $D0 equate to variable A
			
			checksum = $d0 - vname + 65
			' Send Variable description packet
			serout  casiooutport, T9600_16, ( $3a, $56, $41, $4c, $00, $56, $4d, $00, $01, $00, $01, vname, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $56, $61, $72, $69, $61, $62, $6c, $65, $52, $0a, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, checksum )
			
			
			' Casio responds with $06 - consume byte, but do nothing
			serin casioInport, T9600_16, indata1
			
			if indata1 <> $06 then 
					sertxd ("Casio Error #2 code: ", #indata1,13,10)
			end if
			
			
			' read a value
			readtemp12 4,TReading: gosub CalcT
			gosub calcchecksum
			' send Variable Packet
			' Bytes 6~13 contain the digits. Each byte contains 2 digits, packed in BCD format (13h represents digit 1 and 3; 56h : 5 and 6 ; ...), except for byte 6, which only contains 1 digit. 
			' Byte 14 is 51h for negative values, 0h for zero and 1h for positive values. 

			serout  casiooutport, T9600_16, ( $3A,$00,$01,$00,$01,$00,$00, $00, byteval2, byteval1, hnunitsval, $00, $00, SignBit, $09, checksum)
			
			' Casio responds with $06 - consume byte, but do nothing
			serin casioInport, T9600_16, indata1
			if indata1 <> $06 then 
					sertxd ("Casio Error #3 code: ", #indata1,13,10)
			end if
			
	
			' pause for delay
			' You must have the delay/timing code here or the Casio will time out!
			' We are running at 16mhz so ignore the first loop to calculate delay
			
			peek 80, outerloop
			peek 81, innerloop
						
			for b0 = 1 to 4 &#8216; 4 loops
				' delay 15 minutes (ish, does not include program time)
				for b1 = 1 to outerloop
					for b2 = 1 to innerloop
						pause 250
						if overrideswitch is on then sendendpacket
						' If the command was issued then ignoredelays will cause the loop to be exited.
						' why?  cus we are sending Integers and then Decimal value we want the Integer to be returned quickly then use the timing loop only on the decimal part.
						' this, may not be needed for other uses.
						if ignoredelays > 0 then 
							dec ignoredelays
							goto sendendpacket
						end if
					next
					toggle ledport
				next
			next
			
			
			sendendpacket:
			' Send end packet
				serout  casiooutport, T9600_16, ( $3A, $45, $4E, $44)
				for b0 = 5 to 49
						serout  casiooutport, T9600_16, ( $FF)
				next
				serout  casiooutport, T9600_16, ( $56)
	
		end if
	
		' Handling Incoming Data = Set a Picaxe memory slot/variable
		' currently handles I and J others are handled correctly but ignored!
		' You can adapt to handle more commands!!
		
		if indata1 = "V" then
			' Send Picaxe response to Request Packet
			serout  casiooutport, T9600_16, ( $06 )
			
			
			' read packet
			serin casioInport, T9600_16, ($3A,$00,$01),b0,b0,b11,b12,b0,b0,b0,b0,b0,b0,b0,b13
			
			
			' Code from Mike Fenton
			
			'Read in single floating point unit data digit into b11 0 to 9
			'Read 2 Hex floating point decimal data dgits into b12
			'Read floating point exponent data dgits into b13 
			pause 12
			'Wait while ignoring remainder of Data Header bytes Min 12
			
			w2 = 1000
			for b0 = 0 to b13
			w2 = w2 / 10 
			next
			'Generate the exponent 10 to the power of b13 
			w1 = b11*100
			w1 = b12/16*10 + w1
			w1 = b12//16*1 + w1
			'Genrate floating point number
			w1 = w1 / w2
	
			' Send Picaxe response to Request Packet
			serout  casiooutport, T9600_16, ( $06 )
	
			' Use low byte of W1 to update timing variables
			' Sets the outerloop timing variable
			if vname = "I" then
				poke 80, b2
			end if
			' Sets the innerloop timing variable
			if vname = "J" then
				poke 81, b2
			end if
			
		end if
	
		goto fin2
		fin1:
			' Remove comment to output to terminal
			' sertxd ("Error",13,10) ; echo it back out
		fin2:
		low ledport
	}
	end if
	
	' flash LED
	low ledport
	



goto main



calcchecksum:
	#rem
		 Calculate checksum.  
		 Add all bytes of the header (including the checksum), you divided that sum by 256, the remainder (or modulus) must be 3Ah. 
		 
		 
	#endrem
	
	setfreq m32
	bintoascii valueout, tenthousands, thousands, hundreds, tens, units
	
	
		byteval2 = tenthousands - $30
		byteval2 = byteval2 * 16	
	'

		' use hnunitsval as temp variable
		hnunitsval = thousands - $30
		byteval2 = byteval2 + hnunitsval
		
		
		byteval1 = hundreds - $30
		byteval1 = byteval1 * 16
 

		hnunitsval = tens - $30
		byteval1 = byteval1 + hnunitsval
				
	'least sig byte
		hnunitsval = units - $30
		hnunitsval = hnunitsval * 16
		
	checksum =  byteval2 + byteval1 + hnunitsval  + 11 + SignBit	
	
	checksum = NOT checksum
	
	checksum = checksum + 1
	setfreq m16
return


CalcT:
	 ' Calculate Temp - uses TReading / W1 therefore we can examine the BITS
		
       SignBit = Bit15
       If SignBit = 0 Then 
       	SignBit = $1
       	goto Positive
       End if
       
       if TReading = 0 then
       	SignBit = $00
       else
	       ' its negative
      	 SignBit = $51
	end if
	TReading = TReading ^ $ffff + 1 ' take twos comp
	
Positive:

      TempC_100 =  TReading * 6		' TC = value * 0.0625
      TReading = TReading * 25 / 100
      TempC_100 = TempC_100 + TReading

	' Support M (or the funny little r /Radial) and S requests from Casio

	' Integer value request from Casio
	if vname = "M" or vname = 205 then
		valueout = TempC_100 / 100 
	end if
	
	' Decimal value request from  Casio
	if vname = "S" then
		Fract = TempC_100 % 100
		valueout = Fract / 10
		valueout = valueout * 10
		valueout = valueout + Fract % 100
	end if
	
	


Return
 
Last edited:

Anobium

Senior Member
Revised code [corrects handling of decimal parts of data]

Code:
#rem


This model supports DS18B20.  The CASIO displays integer temp values.

The 'Timer override switch' will cease the timed delay and output the current temp immediately to the Casio.



                                    ÚÄÄÄÄÄÄÄÄ¿
                                5v  ³1     18³ 0v
                   (Program Port) > ³2     17³ c.0 > LED out (& Program Port)
                    Sensor In c.4 > ³3     16³ c.1 < TTL Serial from Casio
        Timer Override Switch c.3 > ³4     15³ c.2 > TTL Serial out to Casio
                                    ÀÄÄÄÄÄÄÄÄÙ
                                    
' corrected error in calc of fractional values
' added support for Negative values
' correct handling of decimal numbers

#endrem

#no_data


' Support for DS18B20
Symbol TReading = W0
Symbol Whole = B3
Symbol Fract = B4
Symbol SignBit = B5
Symbol Digg = B6
Symbol TempC_100 = W4

symbol temp = b0
symbol indata1 = b1
symbol indata2 = b2
symbol indata3 = b3

symbol valueout = w7

symbol ignoredelays = b17
symbol vname = b18
symbol checksum = b19

	' 65 53 5
symbol byteval2 = b20
symbol byteval1 = b21
symbol hnunitsval = b22

symbol innerloop = b27
symbol outerloop = b26

symbol units = b27
symbol tens= b26
symbol hundreds = b25
symbol thousands = b24
symbol tenthousands = b23

symbol ledport = c.0
symbol casioInport = c.1
symbol casioOutport = c.2
symbol overrideswitch = pin3
symbol adcport = c.4
setfreq m16

' Flash the LED just to show the Picaxe has rebooted
for temp = 1 to 3
	high ledport
	pause 200
	low ledport
	pause 100
next

valueout = time
ignoredelays = 0


main:

	indata1 = $FF ; set up a non-valid value
	serin casioInport, T9600_16, indata1 ; receive 1 byte
	
	
	
	if indata1 =$15 then ; if a byte was received 
	{	high ledport
	
		' Send inital response, Picaxe is here!
		serout casiooutport, T9600_16, ( $13 )
		
		'Await for the Request Packet and obtain Variable name
		' bytes 1-5
		serin casioInport, T9600_16, (":"), indata1, indata2, indata2, indata2
		' sertxd ("Casio : ", indata1 ,13,10)
		' bytes 6-11
		serin casioInport, T9600_16, indata2, indata2, indata2, indata2, indata2, indata2
		
		' the 12th byte has the variable name		
		serin [4000, fin1],casioInport, T9600_16, vname
		' sertxd ("Casio Variable: ", #vname ,13,10)
		
		' pause to consume the bytes sent by Casio
		pause 250
		
		' Handle Request for Data
		' indata1 contain R[EQ]
		' or indata1 contain V[AL]
		
		if indata1 = "R" then	
			
			' Send Picaxe response to Request Packet
			serout  casiooutport, T9600_16, ( $06 )
			
			' if the CASIO sends 'r' then this is the time override command
			if vname = 205 then
				' set to 2. Means this Request and the next Request for info will ignore any delays
				ignoredelays = 3
				' sertxd ("Casio Variable: ", vname ,13,10)
			end if
			
			
			' Casio responds with $06 - consume byte, but do nothing
			serin casioInport, T9600_16, indata1
		
			if indata1 <> $06 then 
					sertxd ("Casio Error #1 code: ", #indata1,13,10)
			end if
		
		
			' Change the checksum from baseline of variable of A.  Easier than recalculating checksum
			'	checksum = $D0 equate to variable A
			
			checksum = $d0 - vname + 65
			' Send Variable description packet
			serout  casiooutport, T9600_16, ( $3a, $56, $41, $4c, $00, $56, $4d, $00, $01, $00, $01, vname, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $56, $61, $72, $69, $61, $62, $6c, $65, $52, $0a, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, checksum )
			
			
			' Casio responds with $06 - consume byte, but do nothing
			serin casioInport, T9600_16, indata1
			
			if indata1 <> $06 then 
					sertxd ("Casio Error #2 code: ", #indata1,13,10)
			end if
			
			
			' read a value
			readtemp12 4,TReading
			gosub CalcT
			gosub calcchecksum
			' send Variable Packet
			' Bytes 6~13 contain the digits. Each byte contains 2 digits, packed in BCD format (13h represents digit 1 and 3; 56h : 5 and 6 ; ...), except for byte 6, which only contains 1 digit. 
			' Byte 14 is 51h for negative values, 0h for zero and 1h for positive values. 

			serout  casiooutport, T9600_16, ( $3A,$00,$01,$00,$01,$00,$00, $00, byteval2, byteval1, hnunitsval, $00, $00, SignBit, $09, checksum)
			
			' Casio responds with $06 - consume byte, but do nothing
			serin casioInport, T9600_16, indata1
			if indata1 <> $06 then 
					sertxd ("Casio Error #3 code: ", #indata1,13,10)
			end if
			
	
			' pause for delay
			' You must have the delay/timing code here or the Casio will time out!
			' We are running at 16mhz so ignore the first loop to calculate delay
			
			peek 80, outerloop
			peek 81, innerloop
						
			for b0 = 1 to 4 ‘ 4 loops
				' delay 15 minutes (ish, does not include program time)
				for b1 = 1 to outerloop
					for b2 = 1 to innerloop
						pause 250
						if overrideswitch is on then sendendpacket
						' If the command was issued then ignoredelays will cause the loop to be exited.
						' why?  cus we are sending Integers and then Decimal value we want the Integer to be returned quickly then use the timing loop only on the decimal part.
						' this, may not be needed for other uses.
						if ignoredelays > 0 then 
							dec ignoredelays
							goto sendendpacket
						end if
					next
					toggle ledport
				next
			next
			
			
			sendendpacket:
			' Send end packet
				serout  casiooutport, T9600_16, ( $3A, $45, $4E, $44)
				for b0 = 5 to 49
						serout  casiooutport, T9600_16, ( $FF)
				next
				serout  casiooutport, T9600_16, ( $56)
	
		end if
	
		' Handling Incoming Data = Set a Picaxe memory slot/variable
		' currently handles I and J others are handled correctly but ignored!
		' You can adapt to handle more commands!!
		
		if indata1 = "V" then
			' Send Picaxe response to Request Packet
			serout  casiooutport, T9600_16, ( $06 )
			
			
			' read packet
			serin casioInport, T9600_16, ($3A,$00,$01),b0,b0,b11,b12,b0,b0,b0,b0,b0,b0,b0,b13
			
			
			' Code from Mike Fenton
			
			'Read in single floating point unit data digit into b11 0 to 9
			'Read 2 Hex floating point decimal data dgits into b12
			'Read floating point exponent data dgits into b13 
			pause 12
			'Wait while ignoring remainder of Data Header bytes Min 12
			
			w2 = 1000
			for b0 = 0 to b13
			w2 = w2 / 10 
			next
			'Generate the exponent 10 to the power of b13 
			w1 = b11*100
			w1 = b12/16*10 + w1
			w1 = b12//16*1 + w1
			'Genrate floating point number
			w1 = w1 / w2
	
			' Send Picaxe response to Request Packet
			serout  casiooutport, T9600_16, ( $06 )
	
			' Use low byte of W1 to update timing variables
			' Sets the outerloop timing variable
			if vname = "I" then
				poke 80, b2
			end if
			' Sets the innerloop timing variable
			if vname = "J" then
				poke 81, b2
			end if
			
		end if
	
		goto fin2
		fin1:
			' Remove comment to output to terminal
			' sertxd ("Error",13,10) ; echo it back out
		fin2:
		low ledport
	}
	end if
	
	' flash LED
	low ledport
	



goto main



calcchecksum:
	#rem
		 Calculate checksum.  
		 Add all bytes of the header (including the checksum), you divided that sum by 256, the remainder (or modulus) must be 3Ah. 
		 
		 
	#endrem
	
	setfreq m32
	bintoascii valueout, tenthousands, thousands, hundreds, tens, units
	
	
		byteval2 = tenthousands - $30
		byteval2 = byteval2 * 16	
	'

		' use hnunitsval as temp variable
		hnunitsval = thousands - $30
		byteval2 = byteval2 + hnunitsval
		
		
		byteval1 = hundreds - $30
		byteval1 = byteval1 * 16
 

		hnunitsval = tens - $30
		byteval1 = byteval1 + hnunitsval
				
	'least sig byte
		hnunitsval = units - $30
		hnunitsval = hnunitsval * 16
		
	checksum =  byteval2 + byteval1 + hnunitsval  + 11 + SignBit	
	
	checksum = NOT checksum
	
	checksum = checksum + 1
	setfreq m16
return


CalcT:
	 ' Calculate Temp - uses TReading / W1 therefore we can examine the BITS
		
       SignBit = Bit15
       If SignBit = 0 Then 
       	SignBit = $1
       	goto Positive
       End if
       
       if TReading = 0 then
       	SignBit = $00
       else
	       ' its negative
      	 SignBit = $51
	end if
	TReading = TReading ^ $ffff + 1 ' take twos comp
	
Positive:

      TempC_100 =  TReading * 6		' TC = value * 0.0625
      TReading = TReading * 25 / 100
      TempC_100 = TempC_100 + TReading

	' Support M (or the funny little r /Radial) and S requests from Casio

	' Integer value request from Casio
	if vname = "M" or vname = 205 then
		valueout = TempC_100 / 100 
	end if
	
	' Decimal value request from  Casio
	if vname = "S" then
		Fract = TempC_100 % 100
		valueout = Fract * 10
		' Divide result transfered to CASIO by 1000 to get result fraction

	end if
	
	


Return
 
Top