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;
}
Related
Trying to understand difference in performance of signal based routing and PDU based routing in AUTOSAR.
As per my understanding,
Signal based routing -> The signal need to be converted to I-PDU and routed
PDU based routing -> The PDU directly routed
What is the difference in performance between these two.Because anyway routing is handled as PDU.
Some note could see that signal based routing having low latency. Why so? Whether signal based routing is overhead or not?
If my understanding is correct, there is a huge difference between PDU-based routing and signal-based routing. The PDU-based should be much faster.
Signal based routing -> The signal need to be converted to I-PDU and routed
PDU based routing -> The PDU directly routed
Seems pretty correct to me, so let's check an example with a CAN FD frame with several PDUs.
Byte 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
PDU [-------PDU_1------] [--PDU_2--]
Signal II II II
Signal_1 Signal_2 Signal_3
4 bits 3 bits 1 bit
If the PDU_1 is routed using PDU-based routing, from the software perspective, it's just a matter of copying the 7 bytes of PDU_1 to another PDU with the same structure. No need to highlight how fast it is to copy a few bytes from a memory location to another memory location. You can find this case when you have a gateway in Automotive translating PDUs from CAN FD to Flexray and back.
If we use signal-based routing, it's another topic, much more complicated if we consider the software implementation. The software will need to extract the value of Signal_1 and Signal_2 from the the byte fields, then use the factor and offset to determine its physical value with floating points numbers and then convert back to the destination signal which might not have the exact same factor or offset. There are much more calculations involved and this has a strong impact on the performances if the number of signal is important. If you need this, you probably want a MCU with a floating point unit.
static uint32_t GW_GetSignal_1 (uint8_t *Data)
{
uint32_t Byte_0 = Data[0];
uint32_t Bytes = (Byte_0 >> 3);
uint32_t SignalValue = (Bytes & 0xF); /* 0000.1111 */
return SignalValue;
}
static uint32_t GW_GetSignal_2 (uint8_t *Data)
{
uint32_t Byte_0 = Data[0];
uint32_t Bytes = (Byte_0 >> 0);
uint32_t SignalValue = (Bytes & 0x7); /* 0000.0111 */
return SignalValue;
}
static float Raw32ToPhysical (uint32_t RawValue, float Factor, float Offset)
{
float PhysicalValue = ((float)RawValue) * Factor + Offset;
return PhysicalValue;
}
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
My hardware currently has four sets of sensors that I treat as four separate serial ports with receive functionality only enabled wired to the lower 4 bits of port 0. I have attempted numerous times to retrieve the correct serial port data (by aiming the lazer direct at the sensor) without success. I then researched that for more reliability, on a standard UART, each bit is sampled at 16x a second (I found this 3/4 down the page on https://www.allaboutcircuits.com/technical-articles/back-to-basics-the-universal-asynchronous-receiver-transmitter-uart/).
So I ended up rolling off my own version of that but due to my timings, my count is more like 32x a second, but that's ok.
I'm going to explain what I did first so everyone understands what is going on.
code explanation
I have four consecutive address locations setup to point to values of counters for each bit. Four bits are read simultaneously from hardware and a counter for that bit goes up or down based on whether that bit is set (light detected on that group of sensors) or clear (light not detected). This loop executes frequently at about a 9600bps speed.
The second loop only executes when a value is needed. This happens once every 16 times that the last loop executes (more like at a 600bps speed). It takes the counter value of each bit as if it was a signed number and uses the MSB value as the final value of that bit. Those MSB values get crammed together to form the official bit read from the sensors.
Is this approach OK to reliably determine whether the bit value is set or cleared?
And could I somehow redo this code so the processes run faster? because each loop consumes a large number of clock cycles (32 to 40) and if I can get it down to maybe 20 clock cycles, I'd be happy.
Also, this code is executed on AT89S52 microcontroller so I'm using its extended memory addresses.
the code
;memory is preinitialized to nulls
LAZMAJ equ 0E0h ;majority counters start address (end address at 0E4h)
MAJT equ 20h ;Majority value at bit address
mov A,P0 ;get bit values from hardware
mov R1,#LAZMAJ ;go to start of pointer
;loop uses 40 clock cycles out of 192 available
countmaj:
rrc A ;get bit
jnc noincmaj
inc #R1 ;bit is set so add 1 to counter for that bit
noincmaj:
jc incmaj
dec #R1 ;bit is clear so subtract 1 from counter for that bit
incmaj:
inc R1 ;move pointer to next bit
cjne R1,#LAZMAJ+4,countmaj ;see if pointer is out of range
;it is so end loop
;loop uses about 32 clock cycles and executes when we want data
mov R1,#LAZMAJ+4 ;go to out of range position
chkmaj:
dec R1 ;decrement pointer first so we are within range
mov MAJT,#R1 ;load value to majority variable. treat it as signed
mov #R1,#0h ;clear value from memory space
mov C,MAJT.7 ;Take sign and use that as carry
rlc A ;and put it into our final variable
cjne R1,#LAZMAJ,chkmaj ;if pointer isn't in first address then keep going
;otherwise exit loop and A=value we want
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”?
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