Python 我可以发送一个2字节大小的变量作为1字节大小的变量吗?

Python 我可以发送一个2字节大小的变量作为1字节大小的变量吗?,python,c,byte,Python,C,Byte,我正在进行一些ADC(模拟到数字)值转换,需要通过UART发送这些值,但由于速度和其他大小限制,我希望将它们转换为一个字节大小 ADC为12位,范围为0.0至5.0 目前,我正在将2字节变量拆分为两个单独的字节,并将它们重新连接到receiver部分 发送(C) 接收(Python) adc1=数据[3] adc1=adc1如果有什么神奇的方法把两个字节的值塞进一个字节的值,我们会把所有的值都塞进一个字节,然后我们会再做一次,我们会继续这样做,把所有的值都减半,直到我们把世界上所有的信息塞进一个

我正在进行一些ADC(模拟到数字)值转换,需要通过UART发送这些值,但由于速度和其他大小限制,我希望将它们转换为一个字节大小

ADC为12位,范围为0.0至5.0

目前,我正在将2字节变量拆分为两个单独的字节,并将它们重新连接到receiver部分

发送(C)

接收(Python)

adc1=数据[3]

adc1=adc1如果有什么神奇的方法把两个字节的值塞进一个字节的值,我们会把所有的值都塞进一个字节,然后我们会再做一次,我们会继续这样做,把所有的值都减半,直到我们把世界上所有的信息塞进一个字节。这样的魔法是不可能的

如果你扔掉一半的数据,你可以减少数据的大小,但是你说你希望小数点后至少有两位数。一个字节只能对256个不同的值进行编码,而对0.00到9.99之间的所有值进行编码需要1000个不同的值,所以您仍然无法做到这一点


更新:有了附加信息,即这些值只有12位,而不是16位,最大值为5.0,我们可以做得更好,尽管8位中仍然没有3位有效数字

首先,我们可以将2个值打包成3个字节,而不是每个值浪费4位。那看起来像

def pack(val1, val2):
    byte1 = val1 >> 4
    byte2 = ((val1 & 0xf) << 4) | (val2 >> 8)
    byte3 = val2 & 0xff
    return byte1, byte2, byte3
并适当解码:

decoded = encoded * 5.0 / 256

这将保持精度为5/256,或约为0.02。其他编码的性能可能更好,这取决于您对信号的期望。例如,只要值变化不太快,就可以准确地对值进行编码,但当值变化很快时,其精度仅为0.04左右。

您可以在发送端转换这些值,然后与2相乘,并在第二个位置加入“.”。。此方法有效(但不太准确)

使用前3位数字并删除小数点

499 
将该值除以2,以便使用一个有符号字节(0-255)发送

使用常规数据传输方法发送值

send[0] = 249 
在接收段,将值乘以2,再加上一个小数点

adc1 = 249*2
newvalue= adc1[:1]+'.'+adc1[1:]
# you get newvalue = 4.98 ( But you loose the accuracy of the converted adc values )

如果我正确地解释了你的问题,似乎:

  • 值的范围为
    0x000
    -
    0xfff
  • 您将使用这些值(
    (val*5)/4096
    )进行一些数学运算,而不关心结果数字逗号后的前两位小数后面是什么
如果这是您的问题,您可以首先验证如果您在计算后从值中丢弃最低有效十六进制数字,您会丢失多少信息:

>>> (0x010 * 5) / 4096
0.01953125
这意味着,如果您将其闲置,则会出现~0.02的错误

如果您对此没有意见,那么您可以将您的值编码为一个字节。 您只需将值右移4,然后再发送:

 0    f    f    8      >> 4 =   [  0    0  ] f    f
0000 1111 1111 1000             [ 0000 0000]1111 1111
这是可能的,因为您已经有一个空的前导半字节,并且 现在,他们在最后释放了另一半

在接收端,您将再次左移,然后进行计算:

>>> b = 0xff << 4
>>> (b * 5) / 4096
4.98046875
>>b=0xff>>(b*5)/4096
4.98046875

如果不丢失位和精度,则无法执行此操作。基本上,您需要将ADC视为8位。这可能不像听起来那么糟糕,例如,如果您的ADC是12位(您的问题中不清楚),那么您只丢失了4位

uint8_t send = (adc_high_byte << 6) | (adc_low_byte >> 2) ;
在您的示例中,4088以4088/16=255的形式发送,并在接收器处进行转换:

(255 * 5.0) / 256 = 4.98
但请注意

(254 * 5.0) / 256= 4.96, 
因此,最终的精度约为0.02(确切地说,如果255表示的最大值为5.0,则精度为5.0/256=0.01953125)。这与原始精度5/4096=0.00122相比

可以使用以下方法进一步细化。在某些应用程序中,例如音频,保留小信号电平比保留高信号电平更重要,因此可以使用非线性编码将12位数据转换为8位,从而使0和1之间的差异比254和255之间的差异小得多。这项技术的适用性和成功与否取决于应用程序——它对音频效果很好。在其他应用中,不同的非线性编码可能是合适的,例如,对于电池监测,您可能在放电曲线的拐点处使用高分辨率,其中电压降速率快速增加(在某些电池化学中)


最后,正如@chux所建议的,您可以用更少的位传输增量(电平变化),并保留完整的分辨率(在一定程度上损失绝对精度),但这是他的建议,所以我不会详细说明,除了说该技术可以用于压扩。

使用时间压缩

以时间换取准确性。当ADC变化快时,发送7位近似值。当变化缓慢时,发送增量

下面是一个粗略的实现思想

假设2字节ADC值在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);
   }
sample=ADC();
编码_值=样本>>7;
发送(编码_值);
diff=sample-(encode_值=-64&&diff>7;
发送(编码_值);

差异=样本-(encode_值我不知道如何在一个字节中编码。-0-5需要3位,0-99需要5位以上。高阶字节中有多少位是有效的?即,这实际上是一个16位ADC还是更小的。提供范围和所需的分辨率。@SaiGanesh:那么我回答中的假设是正确的。你可以保留精度为0.02,适用于8位0到5的范围。您应该在问题中添加有关ADC和真实单位范围的信息,而不是在注释中。这对问题和有用的答案很重要。哈哈哈哈哈哈!+1。我希望我能+更多。我只是想表示(或假表示)将两个字节的值转换为一个字节,我不是说将两个字节填充到一个字节中,只是搜索一个possibility@SaiGane
>>> b = 0xff << 4
>>> (b * 5) / 4096
4.98046875
uint8_t send = (adc_high_byte << 6) | (adc_low_byte >> 2) ;
adc1 = (data * 5.0) / 256 ;
(255 * 5.0) / 256 = 4.98
(254 * 5.0) / 256= 4.96, 
 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);
   }
valid = 0;
loop:
  sample = receive()
  if (sample & 0x80) {
    delta = sample & 0x7F
    if (delta & 0x40) delta -= 128;
    ADC += delta;
  } else {
    ADC = sample << 9;
    valid = 1;
  }