How to calculate a 256-modulo checksum on arduino - arduino

I am writing a computer program which utilizes input from some equipment which I seldom have availible in my office. In order to develop and test this program I am trying to use an Arduino board to simulate the communication from the actual equipment. To this effect I create datapackets on the Arduino and send them to my computeer over the serial port. The packets are formated as a header and a hexidecimal integer, representing some sensor data.
The header is supposed to contain a checksum (2's complement 256-modulo). I am however not sure how to calculate it. In the datasheet of the equipment (which communication I try to simulate), it is stated that I should first compute the sum all bytes in the packet, and then take the 256-modulo of the sum and perform a 8-bit two's complement on the result.
However, as I am a newbie to bits, bytes and serial communication, I do not understand the following:
1) Lets say that I want to send the value 5500 as two bytes (high byte and low byte). Then the high-byte is '15' and the low-byte is '7c' in hexidecimal encoding, which corresponds to 21 and 124 in decimal values. Do I then add the contributions 21 and 124 to the checksum before taking the 256-modulo, or do I have to do some bit-magic beforehand?
2) How do I perform a two's compliment?
Here is a code which should illustrate how I think. The idea is to send a packet with a header containing a byte which states the length of the packet, a byte which states the type of the packet, and a byte for the checksum. Then a two-byte integer value representing some sensor value is devided into a high-byte and a low-byte, and transmitted low-byte first.
int intVal;
byte Len = 5;
byte checksum;
byte Type = 2;
byte intValHi;
byte intValLo;
void setup(){
Serial.begin(9600);
}
void loop(){
intVal = 5500; //assume that this is a sensor value
intValHi = highByte(intVal);
intValLo = lowByte(intVal);
//how to calculate the checksum? I unsuccessfully tried the following
checksum = 0;
checksum = (Len+checksum+Type+intValHi+intValLo) % 256;
//send header
Serial.write(Len);
Serial.write(checksum);
Serial.write(Type);
//send sensor data
Serial.write(intValLo);
Serial.write(intValHi)
}
Thanks!

The first thing you should understand is that mod 256 is the same thing as looking at the bottom log(256) => 8 bits.
To understand this you have to first realize what the 'mod' operation does and how digits are represented in hardware.
Mod is the remainder after an old-school division (ie only with whole numbers).
eg 5%2 = 1
Digits in hardware are stored in 'bits' which can be interpreted as base 2 mathematics.
Thus if you want to take the mod operation of a power of 2 you don't actually have to do any math.
This is just like if you want to have the remainder of the power of 10, you just take the lower digits.
ie. 157 % 100 = 57.
This can be sped up by using the fact that bytes should overflow by themselves. This means that all you have to do to take %256 of a bunch of numbers is to add them to a single byte and the arduino will take care of the rest.
For twos compliment see this question:
What is “2's Complement”?

Related

I am trying to program a MLX90288 Hall effect sensor and write parameters into its EEPROM

The datasheet provided shows parameters that have addresses and bit size. I want to understand how I can use these with my arduino to program this sensor. Specifically what does the notation "[4:0]" mean next to a parameter.
All calibration parameters on the MLX90288 are stored in a 32 x 16bit non-volatile EEPROM.
"The EEPROM parameters from the first 29 addresses are stored with triple redundancy, to correct if any EEPROM bit would loose its content, by using majority voting. Consequently, an EEPROM word in this part of EEPROM only holds the information of 5 calibration bits + 1 locking bit at index 15. The EEPROM word stored at address 0 thus looks like this:
{LOCK0,PARAM[4:0],PARAM[4:0],PARAM[4:0]}"
So here it says that the clamp voltages are programmable but i don't have knowledge of what the bits mean in the brackets and how I can convert them to hexadecimal:
e.g. CLPHigh[9:0] means 10 bits (from 0 to 9).
With 10 bits the maximum value = dec 1023 (bin 11 1111 1111).
Vdd = 5 Volts, the range is from 0% to 100% (0V to 5V).
The resolution is 0.098% (100 / 1023 = approx. 0.098)
Say you want to set CLPHigh at 25% : 25/0.098 = 255 (= 0xFF)
The Output DAC Resolution = 0.0244, so 1/4 of outDac = 0.098

Serial point to point protocol but with 8 bytes instead of 16

I was looking at answers in Simple serial point-to-point communication protocol and it doesn't help me enough with my issue. I am also trying to communicate data between a computer and an 8-bit microcontroller at first, then eventually I want to communicate the one microcontroller to about 40 others via wireless radio modules. Basically one is designated as a master and the rest are slaves.
speed is an issue
The issue at hand is speed. because communication of every packet needs to be done at least 4x a second back and forth between the master and each slave.
Let's assume baud rate for data is 9600bps. That's 960 bytes a second.
If I used 16-byte packets then: 40 (slaves) times 16 (bytes) times 2 (ways) = 640. Divide that into 960 and that would mean well more than 1/2 a second. Not good.
If I used 8-byte packets then: 40 (slaves) times 8 (bytes) times 2 (ways) = 320. Divide that into 960 and that would mean 1/3 second. It's so-so.
But the thing is I need to watch my baud because too high of baud might mean missed data at larger distances, but you can see the speed difference between an 8 and 16 byte packet.
packet format idea
In my design, I may have a need to transmit a number in the low millions so that will use 24-bits which fits in my idea. But here's my initial idea:
Byte 1: Recipient address 0-255
Byte 2: Sender address 0-255
Byte 3: Command
Byte 4-6: Data
Byte 7-8: 16-bit fletcher checksum of above data
I don't mind if the above format is adjusted, just as long as I have at least 6 bits to identify the sender and receiver (since I'll only deal with 40 units), and the data with command included should be at least 4 bytes total.
How should I modify my data packet idea so that even the device that just turned on in the middle of reception can be in sync with the next set of data? Is there a way without stripping a bit from each data byte?
Rely on the check sum! My packet would consists of:
Recipient's address (0..40) XORed with 0x55
Sender's address (0..40) XORed with 0xAA
Command Byte
Data Byte 0
Data Byte 1
Data Byte 2
CRC8 sum, as suggested by Vroomfondel
Every receiver should have a sliding window of the last seven received bytes. When a byte was shifted in, that window should checked if it is valid:
Are the two addresses in the valid range?
Is it a valid command?
Is the CRC correct?
Especially the last one should safely reject packets on which the receiver hopped on off-sync.
If you have less than 32 command codes, you may go down to six bytes per packet: 40[Senders] times 40[Receivers] times 32[Commands] evaluates to 51200, which would fit into 16 bits instead of 24.
Don't forget to turn off the parity bit!
Update 2017-12-09: Here a receiving function:
typedef uint8_t U8;
void ByteReceived(U8 Byte)
{
static U8 Buf[7]; //Bytes received so far
static U8 BufBC=0;
Buf[BufBC++] = Byte;
if (BufBC<7) return; //Msg incomplete
/*** Seven Byte Message received ***/
//Check Addresses
U8 Adr;
Adr = Buf[0] ^ 0x55; if (Adr >= 40) goto Fail;
Adr = Buf[1] ^ 0xAA; if (Adr >= 40) goto Fail;
if (Buf[2] > ???) goto Fail; //Check Cmd
if (CalcCRC8(Buf, 6) != Buf[6]) goto Fail;
Evaluate(...);
BufBC=0; //empty Buf[]
return;
Fail:
//Seven Byte Msg invalid -> chop off first byte, could use memmove()
Buf[0] = Buf[1];
Buf[1] = Buf[2];
Buf[2] = Buf[3];
Buf[3] = Buf[4];
Buf[4] = Buf[5];
Buf[5] = Buf[6];
BufBC = 6;
}

Calculating CRC / Checksum of hex stream (sniffed)

I'm trying a few days to get the type of the CRC with the following hex stream (sniffed with wireshark):
The Hex data i sniffed:
0000001ec001075465737431323308557365726e616d650850617373776f7264d224
This should be the DATA in HEX:
0000001ec001075465737431323308557365726e616d650850617373776f7264
So the last 4 digits are the checksum, in this case d224
I used many code snippets (PHP, java), and some online checksum calcuation sites:
e.g.:
http://www.scadacore.com/field-applications/programming-calculators/online-checksum-calculator/
But I don't get the correct CRC value.
Thanks!
Update 1
Here are more hex streams with CRC included (the last 4 digits):
0000001dc001045465737409557365726e616d65310950617373776f726431cc96
0000001dc001045465737409557365726e616d65320950617373776f72643289d9
0000001dc001045465737409557365726e616d65330950617373776f726433b51c
0000001dc001045465737409557365726e616d65340950617373776f7264340347
0000001dc001045465737409557365726e616d65350950617373776f7264353f82
It appears to be the ARC CRC, polynomial 0x8005, reflected, zero initial value and no final xor, if I discard the initial 0000001d on each message, and take the CRC at the end to be put in the stream in little-endian order.

IP Checksum with insufficient number of bits

I have to calculate and verify checksums for IP packets (I am writing a router in C). The struct that represents an IP header has a 16 bit checksum but the total number of bits in the struct is not evenly divisible by 16 -- it is 8 bits short.
My question is this. Do I read the struct 16 bits at a time and pad the last set of bits with zeroes to calculate the checksum?
If you had the wrong number of bits, you would pad zero bits to the end of the data.
However, IP calculates over the header fields and thus always has a multiple of 16 bits on which to calculate the checksum. TCP sometimes needs an extra byte of zero at the end of the data.
http://en.wikipedia.org/wiki/IPv4_header_checksum

Simple SDLC CRC calculation not giving the correct value

I am trying to figure out how the calculate the CRC for very simple SDLC frames.
Using an MLT I am capturing the stream and i see some simple frames being sent out like: 0x3073F9E3 and 0x3011EDE3
From my understanding the F9E3 and EDE3 are the 2 byte checksums of the 3073 and 3011 since that is all that was in that frame.
using numerous CRC calculators and calculations I have been able to get the first byte of the checksum, but not the last byte (the F9 and the ED).
Using this calculator (http://www.zorc.breitbandkatze.de/crc.html):
Select CRC-CCITT
Change Final XOR Value to: FFFF
Check Reverse Data Bytes and reverse CRC result before Final XOR
Then type the input: %30%11
Which will give the output B8ED so the last byte is the ED.
Any ideas?
You are getting the correct crc16's (F9 F8, ED B8). I don't know why your last byte is E3 in both cases. This is perhaps a clue that the packets are not being disassembled correctly.

Resources