Exclusive-or (XOR) ^ used as a Serial data checksum

Michael V

Senior Member
I've searched the forum on this, plus the net, and not quite finding the answer i want.

A company i deal with is investing in a data acquisition system that requires data to be sent with a calculated checksum, or the data is ignored. Sounds like a pretty smart way to maintain data integrity. This would be a valuable tool also for Picaxe to Picaxe data communication, whether it be by wire or by the Radio modules ( eg Hope HM- TR or Xbee) that are becoming more and more accessible.

In the short term i'd like to send my own data from Picaxe to this data acquisition system.

I have been very sucessfully using the serout command to export data to computers and basic serial logging software (eg Eltima RS232 Data logger) and hyperterminal via RS232.

This computer company, http://www.trisol.com.au/ are saying that the way to send the data is as follows:

<MID>,<PID>,<Value>,<PID>,<Value>,<PID>,<Value>,<PID>,<Value>,CRC<CR><LF>

Where MID = Message ID, PID = Parameter ID and Value is value, all in ascii characters.

I can handle the message ID, Parameter Identifier and value OK with plain characters, text in invered commas, BintoAscii and then Serout. But now the Checksum CRC.

CRC = ASCII representation of exclusive-or (XOR) sum of all characters from MID(inclusive) to the last value (excluding CRC, <CR> and <LF>).

This Checksum system is apparently also used for data which comes from a Garmin GPS antenna..

The receiving computer also calculates the checksum on the incoming data, and if the checksums match, then it accepts the data. Sounds simple.


Picaxe can do XOR, represented by ^. I understand what it is, but not how the maths works. The only thing i can think of is something like:

b1 = b2^b3^b4^b5^ etc
bintoascii b1,b9,b10,b11
Serout 1, T1200, (b2,b3,b4,b5,......b9,b10,b11,13,10)

This code runs on the simulator OK.
b1 = b2^b3^b4^b5
bintoascii b1,b9,b10,b11
Serout 1, T1200, (b2,b3,b4,b5,b9,b10,b11,13,10)

But, i would be using up a lot of variables and i have no way of knowing if i was generating the right number anyway. There must be a better way.

This idea of generating a checksum and then testing for it seems like such a good idea that you would think that it would have been done in picaxe world before. But I can't find where or how. The guy from Trilogy is off on holidays now, so i can't quiz further, till January, but he can't tell me Picaxe code anyway.

Any ideas on using a XOR sum of all characters as described to generate a checksum?
 

leftyretro

New Member
I've searched the forum on this, plus the net, and not quite finding the answer i want.

A company i deal with is investing in a data acquisition system that requires data to be sent with a calculated checksum, or the data is ignored. Sounds like a pretty smart way to maintain data integrity. This would be a valuable tool also for Picaxe to Picaxe data communication, whether it be by wire or by the Radio modules ( eg Hope HM- TR or Xbee) that are becoming more and more accessible.

In the short term i'd like to send my own data from Picaxe to this data acquisition system.

I have been very sucessfully using the serout command to export data to computers and basic serial logging software (eg Eltima RS232 Data logger) and hyperterminal via RS232.

This computer company, http://www.trisol.com.au/ are saying that the way to send the data is as follows:

<MID>,<PID>,<Value>,<PID>,<Value>,<PID>,<Value>,<PID>,<Value>,CRC<CR><LF>

Where MID = Message ID, PID = Parameter ID and Value is value, all in ascii characters.

I can handle the message ID, Parameter Identifier and value OK with plain characters, text in invered commas, BintoAscii and then Serout. But now the Checksum CRC.

CRC = ASCII representation of exclusive-or (XOR) sum of all characters from MID(inclusive) to the last value (excluding CRC, <CR> and <LF>).

This Checksum system is apparently also used for data which comes from a Garmin GPS antenna..

The receiving computer also calculates the checksum on the incoming data, and if the checksums match, then it accepts the data. Sounds simple.


Picaxe can do XOR, represented by ^. I understand what it is, but not how the maths works. The only thing i can think of is something like:

b1 = b2^b3^b4^b5^ etc
bintoascii b1,b9,b10,b11
Serout 1, T1200, (b2,b3,b4,b5,......b9,b10,b11,13,10)

This code runs on the simulator OK.
b1 = b2^b3^b4^b5
bintoascii b1,b9,b10,b11
Serout 1, T1200, (b2,b3,b4,b5,b9,b10,b11,13,10)

But, i would be using up a lot of variables and i have no way of knowing if i was generating the right number anyway. There must be a better way.

This idea of generating a checksum and then testing for it seems like such a good idea that you would think that it would have been done in picaxe world before. But I can't find where or how. The guy from Trilogy is off on holidays now, so i can't quiz further, till January, but he can't tell me Picaxe code anyway.

Any ideas on using a XOR sum of all characters as described to generate a checksum?
It's been a data integrity method used for a long time. Actually checksum and CRC are two very different methods. CRC does use the exclusive or but uses each data and a polynomial.

Here is a link about CRC generation: http://en.wikipedia.org/wiki/Cyclic_Redundancy_Check

A check-sum is a lot simpler. Here is a link for checksum generation:
http://en.wikipedia.org/wiki/Checksum

You use one byte to hold the intermediate results of each summed byte to be sent in the message. You ignore any overflow and just keep adding the message bytes to the sum like so until all have been sent

B0 = 0
B0 = B0 + B1
B0 = B0 + B2
B0 = B0 + B3
etc
etc

When you have finish sending all the message bytes you send the B0 variable as the last byte transmitted.
If the the receiving end does the same running summation as each byte comes in then it's intermediate running check sum will to equal when it compares the last received checksum byte with the results it has accumulated. For this method to work the receiver has to know either how many bytes there are in message or use the first message byte to convey how long the message is in bytes. The Intel HEX format uses a check-sum method and the Kermit file transfer protocol uses CRC method.

Lefty
 

tarzan

Senior Member
Checksum

This is what I came up with when doing a very similar task. My text string was first placed in the scratchpad ram then the checksum calculated and then send to GPS.
Code:
[FONT=Times New Roman][SIZE=3]'CALCULATE CS SUB [/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]{[/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]calculate_CS:[/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]ptr = 0 [/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]CS = $00 [/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]for temp = 0 to message_length[/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]CS = CS^@ptrinc[/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]next temp [/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]return[/SIZE][/FONT]
[FONT=Times New Roman][SIZE=3]}[/SIZE][/FONT]
 

leftyretro

New Member
PH Anderson's basic code for checksum calculation has been referred to before for picaxe use. It is here: http://www.phanderson.com/bx24/crc.html .

This archive thread discusses CRC: http://www.picaxeforum.co.uk/archive/index.php/t-693.html
The main point I was trying to make is that the CRC is NOT a checksum but rather a more robust algorithm then the more simple checksum method. Both are valid methods for increasing data communications integrity, but again CRC != CHECKSUM.

Lefty
 
Last edited:

Michael V

Senior Member
Cyclic Redundancy Check

Thanks guys - Knew i'd come to the right place.

If i'd known CRC was actually a "cyclic redundancy check" i would have had a better start!

He never actually called it a checksum, that was my mistake.

In following all those great links i can see there are all sorts of CRCs. Some of the code in those links is scaring the pants off me.

The CRC they suggest is is just what i'd placed in bold. It is also meant to be simple to implement. PH Anderson's seems to be specific to the Dallas one wire, and the complexity of the code is frightening. I can see the great minds had put some work into this.

Tarzan's code looks to be along the lines of what i want, but i've never used scratchpad. Is this the best way to do it? I'd hoped to use this on a 08m if i could, and these don't have scratchpad.

I was thinking along the lines of lefty's basic maths, and would somehow do a b0 = b0^b1, as i went along. The Identifiers would always have the same XOR sum and i guess could be pre added? I use bintoascii to generate individual integers so i can serout them as ascii, and thought to XOR them as i went along. The message length would always be the same.

I'll keep working on it, any suggestions welcome, but i'm already in a better place.
 

boriz

Senior Member
Also consider a home-brew scratchpad using poke/peek. All Picaxe types have some extra RAM available that essentially does the same job as the variables. EG:

Code:
*PSEUDOCODE*
Poke 0 into location 80 &#8216;just to make sure the first XOR sum is zero
For b0=1 to packet_length
	Read incoming data byte, POKE into location b0+80 &#8216;note b0 starts at 1
	XOR it with PEEK 80, POKE that back into location 80
Next b0
At this point, your data packet is stored in RAM locations 81 and onwards, and location 80 contains the XOR sum check.

Look up POKE in the manual.
 

Michael V

Senior Member
Stumbling

Thanks for the advice, i've been taking it as best i can, using the peek and poke as suggested.

I don't have any "incoming data" as such, as per boriz's suggestion. The required data string that has a lot of data repeated every time, the Message ID, what type of message, paramater IDs and all the delimiting commas. I input each repeated value in the register in sequence, and left space for the measured values. The idea is that when i measure the values i can "Poke" them into the right place in the register. Then, there are 35 characters in the register, then i use a loop as suggested by Tarzan to read each one, do the XOR calc and serout ascii characters one at a time.

It ended up being too big for a Picaxe 08m, and that is without even capturing data from the sensors and processing. The peek & Poke plus loop seems to work on the simulator, BUTwhen i trt to output the # version of CRC it seems to lose it, giving red characters on the serial simulator.

I don't know if it is doing what it is supposed to or not. The "ASCII representation of exclusive-or (XOR) sum of all characters from MID(inclusive) to the last value (excluding CRC, <CR> and <LF>) does not seem to hard a calculation after all that poking and looping.


I've spent quite some time on this, and i'm not sure if i'm on the right track, whether the preload idea is the right way to do it, (eats memory) and whether the CRC calc is what is required of the database.

Also, in working through this i'm confused as to when you use Hex (eg $32) or BCD eg 50 to represent "2".

Here is the code so far:
Code:
; *******************************
; **  data to infofleet database with XOR CRC  **
; ** CRC = Cyclic Redundancy check, for accuracy of data transmission 
; *******************************

#picaxe28x1

symbol temp_byte1 = b10
symbol temp_byte2 = b11
symbol temp_byte3 = b12


symbol CRC = b13

'Data sent in Ascii to the database is supposed to look like this
'GLS,DATA,S1,165,S2,245,S3,185,ST,0,CRC, 13,10

'Preload repeat data bytes into RAM, decimal values from Decimal to accii tables
poke 80,0	'value zero
poke 81,71	'G
poke 82,76	'L
poke 83,83	'S
poke 84,44	',
poke 85,68	'D
poke 86,65	'A
poke 87,84	'T
poke 88,65	'A
poke 89,44	',
poke 90,83	'S
poke 91,49	'1
poke 92,44	',
		'three digits data
poke 93,32	'(space)
poke 94,32	'(space)
poke 95,32	'(space)
		
poke 96,44	',
poke 97,83	'S
poke 98,50	'2
poke 99,44	',
		'three digits data
poke 100,32	'(space)
poke 101,32	'(space)
poke 102,32	'(space)		
		
		
poke 103,44	',
poke 104,83	'S
poke 105,51	'3
poke 106,44	',
		'three digits data
poke 107,32	'(space)
poke 108,32	'(space)
poke 109,32	'(space)
poke 110,44	',
		
poke 111,83	'S		
poke 112,84	'T
poke 113,44	',
		'one digit data
poke 114,32	'(space)
poke 115,44	',


main:

'Future Code to count the number of seconds into word variable, zero to 999 but temporarily
w1 = 340
w2 = 520
w3 = 180
'Status will be determined by future code, but temporarily, 
let b8 = 1 +48	'Converts byte 1 to Ascii 1
crc = $00	'  Resets to zero

bintoascii w1,temp_byte1,temp_byte2,temp_byte3	' Converts to ascii, splits into three integers


poke 93, temp_byte1		' puts the converted byte in the right spot in register
poke 94, temp_byte2	
poke 95, temp_byte3

bintoascii w2,temp_byte1,temp_byte2,temp_byte3	' Converts to ascii, splits into three integers

poke 100, temp_byte1		' puts the converted byte in the right spot
poke 101, temp_byte2	
poke 102, temp_byte3

bintoascii w3,temp_byte1,temp_byte2,temp_byte3	' Converts to ascii, splits into three integers

poke 107, temp_byte1		' puts the converted byte in the right spot
poke 108, temp_byte2	
poke 109, temp_byte3

poke 114, b8

'the ram is now full of correct data on e byte at a time.

'Now Start a loop to get it all back out in sequence

let b9 = 80		' the first register address (blank) 

do while b9 < 116 
	b9 = b9 +1
	peek b9,temp_byte1	' Puts value at register address into the temp byte variable
	CRC = CRC^temp_byte1	' Increments the CRC XOR calc one byte at a time
	serout 0, T1200, (temp_byte1)	' Outputs the data in register one byte at a time.
	
loop	
	
serout 0, T1200, (#crc,13,10)	 '#  Outputs Ascii representation of CRC,  

pause 125
goto main
Any comments or suggestions welcome. Thanks again for your assistance.
 

Jeremy Leach

Senior Member
Have you got any example messages from their kit with a CRC? At least this way you can see if your code generates the same result.
 

Michael V

Senior Member
Another go.

OK, more info on this seemingly esoteric topic.

The guy is back from holidays now. He has given me an example (thanks for the suggestion Jeremy) and some code that i think must be designed for the standard microchip product. I don't know that language. I only know (some) picaxe code, so it doesn't make much sense to me.

Here is what he has given me:

CRC Example:

PASHR,RIO,f1,f2,f3,f4,f5 gives a CRC = cc (hexadecimal but send as the string “cc”)


And here is what he is telling me is the subroutine that checks it:
Code:
The below is a routine that checks if the received checksum is OK. In this example the CRC is marked with a leading * but we will simply look for the two bytes after the last comma.
As you can see the actual checksum (2 bytes) is calculated by XOR (exclusive OR function)-ing every byte in the message.
This does not including the CRC and CR LF (and for this example * is also disregarded), which in this example has already been stripped in the RX_Data but does include the commas and everything else.

private length
global SumInt
private Result

try
length = Find(Rx_Data,"*",0) //get position of CRC-bytes in the message
if (length > 0)
   SumInt = Asc(Mid(Rx_Data,0,1))

   for(private charcount = 1, charcount < length, charcount++)
      SumInt = (SumInt # Asc(Mid(Rx_Data,charcount,1)))
   endfor
   If (SumInt == StrToDouble("0x" + Mid(Rx_Data,(length+1),2))) //String 0x identifies to convert from hexadecimal-string to double
      Result = 1
   else
      Result = 0
   endif
else
   Result = 0
endif
Using this example i wrote the following based on and what i had done before based on all your suggestions. On the simulator it produces all the characters as it is supposed to, but what is meant to be the hex CRC code comes out as [00]91[0D][0a] .If i uncheck the "display non-printing characters as hex" box i get 91. this is nothing like the "cc" i am supposed to get.
Code:
; *******************************
; **  data to infofleet database with XOR CRC  **
; ** CRC = Cyclic Redundancy check, for accuracy of data transmission 
; *******************************
;    Filename: 		
;    Date: 			
;    File Version: 	
;    Written by: 		MV
;    Function:		
;    Last Revision:
;    Target PICAXE:	
; ******************************* 


#picaxe28x1

symbol temp_byte1 = b10
symbol temp_byte2 = b11
symbol temp_byte3 = b12


symbol CRC = b13

'Example Data sent in Ascii to the database is supposed to look like this

'PASHR,RIO,f1,f2,f3,f4,f5  gives  CRC = cc (hexadecimal but send as the string "cc")

'Preload repeat data bytes into RAM, decimal values from Decimal to accii tables
poke 80,0	'value zero
poke 81,80	'P
poke 82,65	'A
poke 83,83	'S
poke 84,72	'H
poke 85,82	'R
poke 86,44	',
poke 87,82	'R
poke 88,73	'I
poke 89,79	'O
poke 90,44	',
poke 91,102	'f
poke 92,49	'1
poke 93,44	',
poke 94,102	'f
poke 95,50	'2
poke 96,44	',
poke 97,102	'f
poke 98,51	'3
poke 99,44	',
poke 100,102'f
poke 101,52	'4
poke 102,44	',		
poke 103,102'f	
poke 104,53	'5



main:


crc = $00	'  Resets to zero


'the ram is now full of correct data on e byte at a time.

'Now Start a loop to get it all back out in sequence

let b9 = 80		' the first register address (blank) 

do while b9 < 105 
	b9 = b9 +1
	peek b9,temp_byte1	' Puts value at register address into the temp byte variable
	CRC = CRC^temp_byte1	' Increments the CRC XOR calc one byte at a time
	serout 0, T1200, (temp_byte1)	' Outputs the data in register one byte at a time.
	
loop	
	
serout 0, T1200, (#crc,13,10)	 '#  Outputs Ascii representation of CRC,  

pause 125
goto main
I must be missing something fundamental, it is supposed to be simple to implement. I think i'm lost in understanding how hex works in all this, and the foreign code is not helping me at all.
I'm trying, but out of options.

Any help or suggestions appreciated. Objective - picaxe code to generate correct CRC to add to the sent data.

Michael
 

Michael V

Senior Member
Assembler?

A bit more info.
The database guy is assuming i know "assembler" language. All i know about "assembler" is from this forum and the manual1 p 90, and that is that picaxe is a lot easier than assembler. He's talking about an accumulator, i thought i was doing that by listing all the bytes in poke registers, taking them out one at a time and and XOR adding the two together. (code in previous post) Then Using # on the final variable should output the proper code, but it gives me 91 and not "cc|"

{quote}
What language is it? I assume Assembler or similar. You might have to load Byte one into accumulator 1 and Byte 2 into accumulator 2 then XOR them. I assume the result would sit in accumulator 1. So then you load byte 3 into accumulator 2 and XOR; Load Byte 3 into accumulator 2 and XOR; … ; until all bytes are completed. The result would be in accumulator 1 &#61672; this is the CRC. Convert it to ASCII and add it to the message.

If you struggle to determine when the end of the message is: assume the longest possible message and set all bytes to 0x00 then add the message bytes which will leave the not used bytes as 0x00. Then run the above XOR sequence. The 0x00 will affect no changes to the CRC result.
{quote}

I can't see where to next. Any ideas? Could it be something really simple? What he describes sounds easy, i think i'm doing that but i can't get it to work.

Michael
 

BeanieBots

Moderator
To do as he describes, simply replace "accumulator" 1 and 2 with variables b0 and b1 or whatever you are using.
It is reasonable for him to assembler because the XOR on a byte value implies working with accumulators and certainly working in binary.
 

Michael V

Senior Member
Think so..

Thanks for your help bb,
I think that is what i am doing with this code. I've used symbol for CRC and temp_byte1, and preloaded the registers 80-104 with the bytes
Code:
let b9 = 80		' the first register address (blank) 

do while b9 < 105 
	b9 = b9 +1
	peek b9,temp_byte1	' Puts value at register address into the temp byte variable
	CRC = CRC^temp_byte1	' Increments the CRC XOR calc one byte at a time
	serout 0, T1200, (temp_byte1)	' Outputs the data in register one byte at a time.
	
loop	
	
serout 0, T1200, (#crc,13,10)	 '#  Outputs Ascii representation of CRC,
It seems straight forward in picaxe speak, but gives me 91 instead of cc. I don't think cc is hex for 91, i couldn't even find cc in the hex table.

Seems there is nowhere else to go. I'm thinking i'll program a Picaxe o8m with this code, send him a box and see what he gets.
 

Jeremy Leach

Senior Member
I haven't had much time to study this, but have tried to work through what his code does (which seems to be in C++ which I'm not familiar with, but got help at http://www.cplusplus.com/) . It seems he is scanning the data, WITHOUT commas. He starts by assigning the variable SumInt to the ASCII value of the first byte. Then the For loop interations get the next byte ASCII value and XOR with SumInt, and does this up to but not including the CRC.

He says the CRC is two bytes. Why it's two and not one I'm not sure, because if you XOR byte values you get byte values not Word values.

Then it seems he adds "0X" and the (non-ASCII?) two byte received CRC value to give a 4 byte string. Then uses a StrToDouble function to convert this string to a double value. Then compares this value to the calculated SumInt. Hmmm, not sure what's going on with this 0x bit !

The devil's in the detail here I expect !
 

Michael V

Senior Member
Another approach

Thanks Jeremy and BB,
Sorry for the delay, i've been on holidays. Been very hot here.

I too got lost in the one byte vs two byte thing, and it didn't make any sense. The picaxe code i have written (earlier posts) does (i think) XOR adds up each successive byte pre loaded into peek and poke, but then by definition ends up with only 1 byte. Why should there be two?

My next approach is just to program a picaxe +rs232 to generate the data string, XOR each sucessive byte, generate the CRC as i have done, add it to the string, and send him the box, and see if his receiving code receives OK.

If it doesn't i will try to negotiate to not use the CRC, and accept the occasional dodgy data.

Thanks again for the assistance, i'll let you know if there is an epiphany.

Michael
 

Michael V

Senior Member
Start from Hex

The "Basic commands" manual p 19 does not list a ++ as an operator.

I've just spoken with the Database guy again. I told him what I (we) had done so far and the confusion about 1 byte vs 2 on the XOR.

It seems the clue is that "you have to start from HEX", (eg 255 = HEX FF) and this is why you end up with two bytes. 1 byte = 2 HEX, apparently, was not clear in earlier info. Somehow you are supposed to "shift left" when you add stuff up. My code ( post 10) is not using HEX, so i guess i need a ascii and/or conversion combination. The numbers can go into peek and poke as hex i guess, just as easy., and when they come out they will be XOR added as hex.

Is this making any more sense? i'm so out of my depth.
 

hippy

Technical Support
Staff member
Back in post 10 ...

Here is what he has given me:

CRC Example:

PASHR,RIO,f1,f2,f3,f4,f5 gives a CRC = cc (hexadecimal but send as the string &#8220;cc&#8221;)


I make that checksum as 91 / $5B so I don't know how he managed to arrive at $CC, even with the code he provided.

Added : It cannot be $CC - Printable ASCII characters never have the msb set so an XOR'd checksum can never set the msb.

You're going to have to point to an actual definition where this checksum calculation is defined.
 
Last edited:

Michael V

Senior Member
Thanks Hippy,
Just been checking that addresses were ok, and they were. Even changed decimal values to Hex and it made no difference. The simulator produces the correct string, and also produced 91 (decimal), as you had also calculated, and which i can now see from the conversion table as hex $5b, or 0x5b.

I'll confidently run this past him with your comment that "it can not be $cc" - but he's gone for the afternoon. I'll let you know what i get.


Thank once again.
 

hippy

Technical Support
Staff member
If the checksum is an XOR and also compatible with Garmin / NMEA ( which it would be, and his example code matches ), then the example checksum he gave is wrong, you've been on a wild goose chase trying to achieve an impossible checksum :)

This checksums an NMEA string correctly ( as per his code ported to PICAXE ) ...

Code:
Symbol adr = b0
Symbol chk = b1
Symbol chr = b2
Symbol msd = b3
Symbol lsd = b4

Data ("$GPGLL,5300.97914,N,00259.98174,E,125926,A*28")

adr = 0     
chk = 0
Read adr,chr
Do While chr <> "*"
  chk = chk ^ chr
  If chr = "$" Then : chk = 0 : End If
  adr = adr + 1    
  Read adr,chr
Loop 

msd = chk / 16 + "0" : If msd > "9" Then : msd = msd+7 : End If
lsd = chk & $F + "0" : If lsd > "9" Then : lsd = lsd+7 : End If

SerTxd( "Checksum=$",msd,lsd,CR,LF)
 

Michael V

Senior Member
GPS

Thanks Hippy,
He did say it was the same as is generated by a GPS, they were using that as a standard, very insightful of you.

I've run the code on the simulator, and it works of course. I can see what the loop does, at $ it resets to zero, XORs successive characters, and keeps going till it hits the * flag. msd is created by dividing by 16, equivalent of the "shift left" he was trying to explainto me. I could never have come up with that. I feel i'm getting much closer now.

I thought The line commencing with "Data" would throw it out, since that command is not in my manual under basic commands. But it didn't. This will save me a lot of converting of individual characters, as i had done before, plus space if i want to use a 08m. Is there a reason "Data" is not in the manual?

I'll keep at this.
 

Michael V

Senior Member
Refinement of Code

Data = Eeprom - how could i have missed that, it was only a few pages on and even says data on the index. What a dork i am. Did i mention i'm a beginner?

Hippy, I've spent some time trying to combine characters and variables into the DATA command, and could not get it to go, it did not pass the compiler check.

My fall back was the earlier suggestion of preloading the RAM (peek and poke). with characters and variables, then using a loop to get them back out, use serout (or sertxd) calculating XOR on each increment as i go. The additional lines from Hippys code ( 3 posts earlier) creates the two discrete Hex characters output as ascii. Very clever guys, i can see you have done this sort of thing before.

The database guy has mentioned the starting character and prefix to the crc (*) from the GPS, but is not using them in this case. When i meet him i'll discuss this, now i've seen hippy's picaxe code i can see it can be done.

Buoyed with the assertion that I have been on a wild goose chase, I have now made up some new code, which has a good chance of working.

I have a picaxe 08M already connected to a DS18B20 temperature sensor and RS232 chip. I'm going to try this code, which works fine in the simulator. It outputs to Picaxe pin 0, which is connected to the RS232 chip:

Code:
#picaxe08m

symbol lsd = b7
symbol msd = b8
symbol temp_byte1 = b10
symbol temp_byte2 = b11
symbol temp_byte3 = b12

symbol CRC = b13
Pause 500	'wait for power up.

main:
'Preload repeat data bytes into RAM, decimal values from Decimal to accii tables
poke 80,0	'value zero
poke 81,84	'T
poke 82,50	'2
poke 83,83	'S
poke 84,44	',
poke 85,68	'D
poke 86,65	'A
poke 87,84	'T
poke 88,65	'A
poke 89,44	',
poke 90,116	't
poke 91,49	'1
poke 92,44	',
poke 93,32	'(sp)
poke 94,32	'(sp)
poke 95,46	'.
poke 96,32	'(sp)
poke 97,44	',


'read the temp, convert it to ascii and load into the RAM
readtemp12 1,w0
w0 = w0*20/32	'convert to temp x 10
bintoascii w0,temp_byte1,temp_byte2,temp_byte3
poke 93,temp_byte1
poke 94,temp_byte2
poke 96,temp_byte3

crc = $00	'  Resets to zero

let b9 = 80		' the first register address (blank) 

' now run a loop to get it all out of the ram.
do while b9 < 97 
	b9 = b9 +1
	peek b9,temp_byte1	' Puts value at register address into the temp byte variable
	CRC = CRC^temp_byte1	' Increments the CRC XOR calc one byte at a time
	serout 0, T1200, (temp_byte1)	' Outputs the data in register one byte at a time.
loop	

msd = crc / 16 + "0" : If msd > "9" Then : msd = msd+7 : End If
lsd = crc & $F + "0" : If lsd > "9" Then : lsd = lsd+7 : End If	

serout 0, T1200, (msd,lsd,13,10)	 '#  Outputs Ascii representation of CRC,  

pause 125
goto main
It outputs T2S,DATA,t1,0.00,7E about once a second.

where 0.00 is the temperature in degrees C and 7E is the CRC shown as Ascii, just as he asked.

When the Temp varies so does the CRC.

I can put the $ at the front and the * before the CRC easily enough, but i can fool around with all that later on.

Syntax check says 167 bytes, so still room on the picaxe 08m for some more tricks.

Any additional comments or advice welcome!

Nothing will happen till at least next week when i see the guy, thanks once again for your assitance, i'll let you know how i get on in the "real world".

Michael
 

hippy

Technical Support
Staff member
@ Micahel : That code looks good and I would say it should work.

Sorry about the "Data" confusion. I usually use "Eeprom" so a normally unused neuron must have fired off while I was typing to confuse things.

One thing you could perhaps do to save some code space and a lot of Poke typing is put the message in Eeprom, copy it from there to SFR using Read/Poke and fill in the missing temperature data, then checksum and send. That might be useful if you have more than one message to transmit.
 

Michael V

Senior Member
Well Done

Well Hippy, you are the man....

:Quote:
It comes to show that you cannot even trust printed books.
Your CRC routine is working fine and matches mine. On the example I had send the CRC is indeed 91Dec that should be send as 5B in hexadecimal = 2 byte as text-ASCII.
I am also getting the same result of 7E for your example.

:Unquote:

So the code in the penultimate post (24) works just fine!

He has suggested to put in the * prior to the CRC because is easier to decode for strings of unknown length. Easily done of course.

I still can't see the eeprom thing, combining text and variables. Youve thrown another TLA (three letter acronym) in there, SFR. I certainly am interested on saving code space because i can use the super versatile 08m, which also saves physical space and looks innocuous. My coding for a raange of outputs has gone over because of using several blocks of text in serout commands, and i'm working on doing that more efficiently. Never had that problem on the 28x1!

Thanks again, I'll let you know how the field testing in the real (computer) world goes.

Michael
 
Last edited:

Michael V

Senior Member
Success and learning points

Well Just to let you know.

Hippys code worked just fine in the real world. The code in the DAQ system software tested it OK.


A few learning points for newbies on combining data and text:

1) If you open the "Calculator" that comes with windows, then "View"Scientific" then you can see how people do XOR sums. You old hands probably knewthat, but it was the first time i had seen this or how to do it. You select Hex or Decimal and then just XOR them up. In the case of this example you then convert to HEX. I had actually written code that would add the letters up with the ^ and ran it on simulator to get the result.

2) it doesn'tactually matter what sequence the letters and numbers are in. This means that you can pre-add the non changing parts of your output string andjust addthe onesthat change.

3) If your output is not a range of numbers, (eg temperature) but a series of states (input high low, finite number of conditiins) It is easy to just precalculate for each state, and add the precalculated CRC code to the end of the output data string,no loops required.

4) using the * prior to the CRC - as per the GPS example- is a good idea, helps you separate the data fromthe CRC.


Thanks once again for the great assistance, i would not survive without the Forum.

Michael
 

hippy

Technical Support
Staff member
Glad you got there Michael and it's all working okay, thanks for the tips, and thanks for letting us know it does work.
 
Top