Can i send a 2 byte size variable as 1 byte size variable?
Can i send a 2 byte size variable as 1 byte size variable?
I am working on some ADC(Analog-to-Digital) value conversions and need to send those values over the UART but due to the speed and other size limitations I want to convert those to one byte size
The ADC is 12 bit for a range 0.0 to 5.0.
Currently I am splitting the 2 byte variable to two separate bytes and joining them back in the receiver section
Sending (C)
// i am trying to send 0xFF8 (4088) which is read from that register send[0] = (VADC_G5RES4.B.RESULT) >> 8 ; send[1] = (VADC_G5RES4.B.RESULT) & 0x0FF; . send[30] = .....
Receiving (Python)
adc1 = data[3] adc1 = adc1 << 8 | data[4] adc1 = (float(adc1 * 5) / 4096) # gives me 4.990234 as the value
Is there any way that i can send the value in just one byte (maybe by performing the calculation on the sending side)
Only 2 digits after the decimal (4.99) would be fine
Answer by user2357112 for Can i send a 2 byte size variable as 1 byte size variable?
If there were some magic way to stuff two-byte values into one-byte values, we would do it to everything, and then we would do it again, and we would keep doing it and keep halving the size of everything until we were shoving all the world's information into a single byte. Such magic is not possible.
If you instead throw away half your data, you can reduce the size of things, but you say you want at least 2 digits after the decimal point. A byte can only encode 256 different values, and encoding everything from 0.00 to 9.99 takes 1000 different values, so you still can't do it.
UPDATE: With the additional information that these are only 12-bit values, rather than 16-bit, and that the maximum value is 5.0, we can do a lot better, though still not quite 3 significant figures in 8 bits.
First, instead of wasting 4 bits per value, we can pack 2 values into 3 bytes. That'd look something like
def pack(val1, val2): byte1 = val1 >> 4 byte2 = ((val1 & 0xf) << 4) | (val2 >> 8) byte3 = val2 & 0xff return byte1, byte2, byte3
You might need to deal with a trailing half-byte.
If 1.5 bytes per value is still too much, there are lossy encoding options. For example, we can just throw away the 4 least-significant bits of every value:
encoded = val >> 4
and decode appropriately:
decoded = encoded * 5.0 / 256
This keeps a precision of 5/256, or about 0.02. Other encodings might perform better, depending on what you expect the signal to look like. For example, chux's solution encodes values exactly as long as the values don't change too fast, but only has a precision of about 0.04 when the values are changing quickly.
Answer by user2345 for Can i send a 2 byte size variable as 1 byte size variable?
You can convert those in the sending side and multiply with 2 and join a '.' at the 2nd position.. This method works( but not very accurate)
(4088*5)/4096 = 4.990234
use the first 3 digits and remove the decimal point
499
divide the value by 2 so that it can be sent using one signed byte (0-255)
499/2 = 249
send the value using your regular data transfer method
send[0] = 249
On receiving section multiply the value with 2 and add a decimal point
adc1 = 249*2 newvalue= adc1[:1]+'.'+adc1[1:] # you get newvalue = 4.98 ( But you loose the accuracy of the converted adc values )
Answer by etuardu for Can i send a 2 byte size variable as 1 byte size variable?
If I correctly deciphered your problem, it seems that:
- you have values in the range
0x000
-0xfff
- you will make some math with those values (
(val * 5) / 4096
) and only care about the first two decimals after the comma of the resulting number
If this is your question, you can first of all verify how much information you loose if you throw away the least significant byte from your values after the math:
>>> (0x010 * 5) / 4096 0.01953125
This means that if you spare the last byte you will have an error of ~0.02.
If you are ok with that, you can then skip it and encode your value in a single byte. You just need to right-shift by 4 your value before sending:
0 f f 8 >> 4 [ 0 0 ] f f 0000 1111 1111 1000 [ 0000 0000]1111 1111
On the receiving side, you will left-shift it again and then process:
>>> b = 0xff << 4 >>> (b * 5) / 4096 4.98046875
Answer by Clifford for Can i send a 2 byte size variable as 1 byte size variable?
It cannot be done without loosing bits and therefore precision. Essentially you would need treat your ADC as if it were 8 bit. That may not be as bad as it sounds, for example, if your ADC is 12 bit (not clear in your question), you loose just 4 bits.
uint8_t send = (adc_high_byte << 6) | (adc_low_byte >> 2) ;
then in the receiver:
adc1 = (float(data * 80)) / 4096 ;
In your example 4088 is sent as 4088/16 = 255 and at th ereceiver its is transfromed:
(float(255*80))/4096 = 4.98
but note that
(float(254*80))/4096 = 4.96,
so you end up with a precision of approximately 0.02 (precisely speaking, if your maximum value represented by 255 is 5.0, then the precision is 5.0/256 = 0.01953125). This compares to the original precision of 5/4096 = 0.00122
A further refinement is possible using companding. In some applications, such as audio, it is more important to retain detail a small signal levels than high, so you can transform the 12 bit data to 8 using a non-linear encoding so that the difference between say 0 and 1 is much smaller than between 254 and 255. The applicability and success of this will be application dependent - it works well for audio. In other applications a different non-linear encoding may be appropriate, for example for battery monitoring you might use high resolution at the knee of the discharge curve, where rate of voltage drop increases rapidly (in some battery chemistries).
Finally as suggested by @chux, you can transmit delta (changes in level) in fewer bits and retain the full resolution (with some loss of absolute accuracy), but that was his suggestion so I won't elaborate, except to say that the technique can be used with commanding.
Answer by chux for Can i send a 2 byte size variable as 1 byte size variable?
Use temporal compression.
Trade time for accuracy. When the ADC is changing fast, sent a 7-bit approximation. When it changes slow, send the delta.
The following is a coarse implementation idea.
Assume 2-byte ADC value in the ranges 0-3FFF.
sample = ADC(); encode_value = sample >> 7; send(encode_value); diff = sample - (encode_value << 7); loop: previous_sample = sample sample = ADC(); diff = previous_sample - sample; if (diff >= -64 && diff <= 63) { send(diff | 0x80); diff = 0; } else { encode_value = sample >> 7; send(encode_value); diff = sample - (encode_value << 7); }
// Receive
valid = 0; loop: sample = receive() if (sample & 0x80) { delta = sample & 0x7F if (delta & 0x40) delta -= 128; ADC += delta; } else { ADC = sample << 9; valid = 1; }
Likely should reserve another bit to detect a missed sequence when sending a delta. Other considerations apply, yet here it is to give the OP another point of view.
Refinements include having the delta
give up 2 bits of mantissa
for a 2-bit exponent.
[Edit]
12 bits of random data do not fit in 8 bits. Some ideas:
Give up precision. Simple divide the 12-bit value by 16, send those 8 bits and multiply by 16 on the receiving end.
Send the first A/D sample in 2 parts by cutting the 12-bit value into 2 6-bits halves. Use the MSB to distinguish if the upper or lower is sent. The receiving end needs 2 samples to put things back together. The 2nd A/D sample on the transmits end is thrown away.
Like #2, but send 2 out of every 3 samples. 24-bits of data in 3 8-bit messages.
As answered in the beginning of this answer. Sometimes sending the course value, other times, the delta.
As commented below @Clifford always send a signed 8-bit delta. Might need a minor adjustment to insure any bias in the receiving sum eventually works its way out.
Take a couple 1000 (million) samples and write it as packed 12-bit data into a file. Zip (compress) the file. What every the ration of compression is found, is an indicator of the best compression scheme we could derive. If it is not at least 33%, then you best to accept that data is too dynamic to be completely transmitted with the requirements given.
Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 71
0 comments:
Post a Comment