我即将结束一段漫长的旅程.
如果你有兴趣的话,这是一个很长的故事。https://github.com/hardbyte/python-can/issues/1336
很抱歉,代码片段太长了,但是我不知道我哪里出错了,所以我认为更多就是更多了。
代码如下所示,request_inst()使用来自单片机的dict request_info请求仪表数据,单片机响应,这是由listener获取的。obtain_message()创建了一个存储all_data的未来,这是从listener和msg = await reader.get_message()中产生的。我试图用lock构建这个过程。store_data()是我存储来自单片机的响应数据的地方,这是一个名为all_data的dict。all_data在listener外部打印时显示为零值,如下所示。代码的目的是使all_data在事件循环之外可用,但目前即使有了这个实现,我也无法让all_data在dict中没有零值的情况下出现。
import asyncio
import can
from can.notifier import MessageRecipient
from typing import List
freq = 0.0003
# this is the respond ids and the and the parameter ids of the data
# stored data is suppose to fill up the None with a value
all_data = {268439810: {16512: [None], 16513: [None], 16514: [None], 16515: [None]},
268444162: {16512: [None], 16513: [None], 16514: [None], 16515: [None]}}
request_info = {286326784: {16512, 16513, 16514, 16515},
287440896: {16512, 16513, 16514, 16515}}
# all the request ids in that have been configured
cm4_read_ids = [286326784, 287440896]
# all the response ids in that have been configured
mcu_respond_ids = [268439810, 268444162]
# finds arb id and pid and logs the data from the message
# async def store_data(arb_id, msg_data, msg_dlc):
async def store_data(msg: can.Message, lock):
pid = int.from_bytes(msg.data[0:2], 'little')
arb_id = msg.arbitration_id
if arb_id in mcu_respond_ids:
async with lock:
if msg.dlc == 5:
all_data[arb_id][pid][0] = int.from_bytes(msg.data[2:4], 'little', signed=False)
elif msg.dlc == 7:
all_data[arb_id][pid][0] = int.from_bytes(msg.data[2:6], 'little', signed=False)
return all_data
async def request_inst(bus: can.Bus):
print('Request inst active')
while True:
for key in request_info:
for val in request_info[key]:
pid = int(val)
pidbytes = pid.to_bytes(2, 'little')
msg = can.Message(arbitration_id=key, data=pidbytes)
bus.send(msg)
await asyncio.sleep(freq)
# await store_data(reader)
async def message_obtain(reader: can.AsyncBufferedReader, lock):
print('Started it the get message process')
while True:
await asyncio.sleep(0.01)
msg = await reader.get_message()
future = await store_data(msg, lock)
async with lock:
print('This is the future')
print(future)
async def main() -> None:
with can.Bus(
interface="socketcan", channel="can0", receive_own_messages=True
) as bus:
# Create Notifier with an explicit loop to use for scheduling of callbacks
loop = asyncio.get_running_loop()
reader = can.AsyncBufferedReader()
lock = asyncio.Lock()
listeners: List[MessageRecipient] = [reader]
notifier = can.Notifier(bus, listeners, loop=loop)
try:
task1 = asyncio.create_task(request_inst(bus))
task2 = asyncio.create_task(message_obtain(reader, lock))
await asyncio.gather(task1, task2)
except KeyboardInterrupt:
notifier.stop()
bus.shutdown()
if __name__ == "__main__":
asyncio.run(main())我所看到的问题是,即使在这一页上,我也看到了我认为是并发性的问题。
正如您所看到的,我已经尝试过锁定,但是我仍然看到这些零值出现在all_data中,参见下面,当MCU返回的消息不是零时,pid 16514的balue变为0。
n.b.下面显示不正确数据的输出是来自print(future)的输出

实际值不应该是0,因为它是一个测量值。
b6 = (1016872961).to_bytes(4, 'little')
struct.unpack('<f', b6)
(0.01907348819077015,)我做了什么蠢事吗?尽管在修改all_data时使用了lock,但感觉好像没有正确地访问侦听器中的数据。
如果我从listeners打印数据,即使all_data返回0值,数据也始终是正确的。
如果有人能帮我的话,我将不胜感激。
发布于 2022-11-11 15:40:39
好吧,好吧,原来我做了一件真的很傻的事。我使用嵌套字典来存储关于不同ids的数据,但是键是相同的。在使用id(id1[some_pid1])和id(id2[some_pid1])进行了一些调查之后,我发现这些密钥具有相同的内存地址。
data_dict = {id1: {some_pid1: value, some_pid2: value},
id2: {some_pid1: value, some_pid2: value}}这似乎是一种竞赛条件,但实际上,我只是写零(结果是被迫从MCU)到错误的id,因为它与另一个id共享一个密钥。
Whoops
发布于 2022-10-19 08:14:26
看来问题与软件无关,零是真实存在的。每一天都是学习的日子!
这是高亮显示的发送和顶部显示的响应的PCAN图像。

编辑:确认的MCU响应问题-看起来像在单片机上的固件。我的Rigol不会触发在ID上,所以我不得不1/8的视频,然后屏幕截图,以捕捉它在行动。您可以看到响应都是7字节的空值。

https://stackoverflow.com/questions/74116542
复制相似问题