如何通过串行连接有效地使用设备?

发布于 2024-08-13 17:35:42 字数 758 浏览 4 评论 0原文

我已经为此奋斗了很长一段时间,最终我确实得到了一个可行的解决方案,但它并不漂亮,我希望从 stackoverflow 社区获得一些关于如何完成此操作的智慧。

基本上,我正在使用使用菊花链 USB 连接连接到计算机的电机,并且我必须使用 .Net 中的 SerialPort 类与它们进行通信,并且它通过计算机上安装的一些驱动程序通过 USB 与电机进行通信。

问题在于,电机是菊花链式连接的,当我

向其中一个电机询问信息或告诉它做某事时,我必须等待结果返回,然后才能对该电机或任何其他电机执行其他操作。

我刚刚经历了一段艰难的时期,我确信有更好的方法来处理我从未接触过的串行通信。对于此类事情有什么好的指导方针或最佳实践吗?这是一个相当标准的事情吗(串行通信 -> USB 通过计算机上安装的驱动程序)

我正在使用六个 MDrive23Plus 运动控制 来自 IMS 的电机。

我可以提供更多细节,但我不太确定这会导致什么结果。我希望这对 StackOverflow 来说足够具体,尽管我知道它有点模糊。我只是真的不知道如何更好地问它。

实际上,归根结底是如何有效地同步通信,以及如何有效地等待和读取返回的数据?我知道这对某些人来说可能很简单,但对我来说效果不佳。

I have struggled with this for a long time, and I did get a solution working eventually but it wasn't pretty, and I am hoping to gain a little wisdom from the stackoverflow community about how this should be done.

Basically I am working with motors that connect to the computer using a daisychained USB connection and I have to communicate with them using the SerialPort class in .Net and it goes through some driver installed on the computer to talk with the motors over USB.

The problem is that the motors are daisy chained, and when I ask

for information from one, or tell it to do something, i have to wait on the result to come back before doing something else with that motor or with any of the others.

I've just had a generally hard time with it, and I'm sure there are better ways of working with serial communication that I've just never been exposed to. Are there any good guidelines or best practices for this kind of thing? Is this a fairly standard thing to do be doing (serial communication -> usb via a driver installed on computer)

I'm working with six of the MDrive23Plus Motion Control motors from IMS.

I can provide plenty more details, but I'm not really sure where this will lead. I hope this is specific enough for StackOverflow, though I know it is sort of vague. I just don't really know how to ask it any better.

Really what it comes down to is how do I synchronize communication effectively, and how do I wait and read the data coming back effectively? I know this is probably very simple to some people, but it just hasn't been working well for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

优雅的叶子 2024-08-20 17:35:42

这是多点串行网络工作的限制......它没有什么魔力,你可以减轻一些痛苦

通常最好的方法是放入一个抽象层,其中你有一个你想要的东西的消息队列发送,并且每个都有一个回调,当收到响应时会调用该回调。

this is the limit of working multi drop serial networks.....there is no magic to it, you can ease some of the pain

Generally the best approach is to put in an abstraction layer where you have a message queue of things you want to send, and each of those have a callback that gets called when it gets a response.

千笙结 2024-08-20 17:35:42

您可能需要多个线程和/或异步操作。过去,在进行串行通信(不是在 .NET 中)时,我们会对端口上的读取进行排队。当读取完成时,回调函数(委托)将触发,将执行读取处理,可能会更改控制状态 - 我们的典型示例是条形码读取,同时具有键盘读取和计时器。其中一个事件将完成,这将导致一项操作(可能将其他排队的读取留在原地或取消它们,具体取决于状态要移动到的位置。)

您可能需要考虑使用状态机。在这种情况下,状态机知道正在进行什么操作、允许哪些转换、如何在它们之间进行转换以及转换会导致什么操作。

You might need multiple threads and/or asynchronous operations. In the past, when doing serial comms (not in .NET), we would queue up reads on the port(s). When a read would complete, the callback function (delegate) would fire, the processing of the read would be carried out, potentially changing the control state - our typical example was a barcode read, while simultaneously having a keyboard read and a timer. One of the events would complete, which would cause an action (potentially leaving the other queued reads in place or cancelling them, depending on what the state was moving to.)

You might want to look into using state machine(s). In this case, the state machine knows what operations are going on, which transitions are allowed and how to get between them and what actions the transitions cause.

我是有多爱你 2024-08-20 17:35:42

许多设备的串行通信都变化无常。有些设备的通信无法正常运行,无法以指定的波特率读取线路。

我发现我必须表征设备的通信。有些供应商的同一型号的两个设备的通信特性不同。人物塑造是一件相当乏味的事情。表征涉及发现各种情况的组合,然后思考可能性。

  1. 插入延迟之前连续读取/写入的最低阈值字节数。可能性是一次一个字符。
  2. 恢复读/写之前最安全的最短延迟。
  3. 从初始化通信到稳定状态通信所需的最小延迟的变化。
  4. 插入延迟之前以指定波特率可写的阈值字节数的变化。

最坏的情况是影响读/写操作清洁度的状态/可能性组合的激增,并且您可以通过妥协使用读/写操作组中最慢的公分母来减少状态数量。这一切背后一定有科学依据,但我只是用暴力测试尽了最大的努力。

当然,这会导致有一个读/写层将需要通信的例程与直接与端口通信分开。

或者,我们都知道快速、懒惰但效率低下的方法是在每个字节后插入 10 毫秒的等待。

Many devices are fickle on their serial comms. There are devices whose comms cannot behave properly with a line read at the baud rate they specified.

I find that I have to characterize the comms of a device. There are vendors where the comms characteristics of two devices of the same model are different. Characterization is a rather tedious affair. Characterization involves discovering various combination of situations and then think of the possibilities.

  1. the lowest threshold number of bytes read/written continuously before inserting a delay. The possibility is one character at a time.
  2. the safest least delay before resuming a read/write.
  3. the variation of minimum delay required from initialising comms till steady state comms.
  4. the variation of threshold number of bytes writable at specified baud before inserting a delay.

The worst case scenario is a proliferation of states/combinations of possibilities influencing the cleanliness of the read/write operations and you reduce the number of states by compromising to use the slowest common denominator among groups of read/write operations. There must be a science behind all this but I just try my voodooistic best using brute force testing.

Which, of course, would lead to having a read/write layer separating the routines needing communication from directly communicating with the port.

Alternatively, we all know the quick and lazy but inefficient way is inserting a 10 ms wait after every byte.

够钟 2024-08-20 17:35:42

自 2004 年以来,我也一直在使用 .net 串行端口类,我同意状态机可能是这里的方法,除了发送命令,然后等待握手中的相关响应(设备准备就绪时将响应)来回应)。

将您的 serialPort.DataReceived() 事件处理程序视为您的前端。
然后让 DataReceived 执行 BeginInvoke(),而不是 Invoke(),因为串行端口是方法的异步接口,AddReceive()
接下来,在 AddReceive() 中计算它看到的字节数
如果大于 0,则将数据附加到 stringbuilder 容器,例如 sbReceived
最后触发一个计时器处理程序来拾取流中的任何“剩余”数据,其中它还在方法 ReadData() 上执行“beginInvoke”
现在我们准备解析数据并传递到终端显示(这里最好使用富文本框),用颜色编码各种提示来指示>>输出数据,<<在数据、配置、错误、状态中
由于您有多个端口需要监控以及每个端口上的 I/O 状态,因此您可以在一个终端显示器内执行此操作。

我同意状态机在这里是个好主意,无论如何,进程都是有状态的;在其他端口上发送串行端口命令之前,您正在等待串行 1 解析输出的输出来匹配您需要的内容。这样做可以使事情井井有条,并且不同的串行端口活动可以很好地划分出来。在另一种情况下,您可能会发生多个后续命令/查询输出和设备响应周期,最好在两者之间执行 while(serial1.ByteCount==0){}; 以便让设备控制握手中响应的时间。连接调试数字 I/O 设备也很有帮助,这样您就可以切换线路来监控延迟时间并在 DSO 上观察以验证是否满足时序要求。

最后,一定要在每个写入/读取周期清除端口,这样就不会遇到溢出问题,以及数据缓冲区、字符串生成器容器等的重新初始化。

祝你有美好的一天

I have also been using the .net serial port class since 2004, i agree state machines are probably the way to go here, that along with sending out command, then wait for the associated response in the handshake(device will respond when it is ready to respond).

Consider your serialPort.DataReceived() event handler as your front end.
then have DataReceived do a BeginInvoke(), not an Invoke() as serial port is asynchronous interface to a method, AddReceive()
next, in AddReceive() count the number of bytes that it sees
if more than 0, then append data to stringbuilder container, say sbReceived
finally fire a timer handler to pickup any 'left over' data in the stream where it also does a 'beginInvoke' on method, ReadData()
now we are ready to parse data out and pass to terminal display(best to use richtext box here), color code various prompts to indicate >> out data, << in data, configuration, error, status
since you have various ports to monitor and i/o status on each one, you could do so inside of one terminal display.

I agree state machine is good idea here, process is very stateful anyways; you are waiting for output of serial1 parsed output to match what you need, before sending serial port commands on other ports. doing it this way would keep things organized and different serial port activities are nicely partitioned out. in the other case where you might have several subsequent command/query out and device response cycles happening, it might be better to do while(serial1.ByteCount==0){}; in between to just let the device control the timing of the response in the handshake. it can also be helpful to have a debug digital i/o device hooked up so you can toggle line to monitor latency times and watch on DSO to verify timing requirement is being met.

finally, be certain to purge your port on each write/read cycle so you don't experience overflow issues, along with re-initialization of data buffers, stringbuilder containers and the like.

have a good day

绮筵 2024-08-20 17:35:42

我在 Zaber Technologies 工作,我为通过菊花通信的精密步进电机控制器构建了一个控制库-链式串行连接。我使用了三层:

  1. 端口 - 该层只涉及通信协议。它公开了发送消息的方法,并将消息参数转换为字节流。它还侦听传入线路,将字节流转换为消息结构,并在收到完整消息时引发事件。
  2. 设备 - 该层知道如何向菊花链中的特定设备发送消息以及如何过滤来自菊花链中其他设备的响应。
  3. 对话 - 该层协调请求和响应,并让调用代码发出一个请求,该请求将阻塞线程,直到响应返回。

然后,调用代码可以选择是对会话层使用同步请求,还是对设备层使用异步请求。

如果您对更多详细信息感兴趣,可以下载源代码 或者查看用户文档,其中讨论了针对库编写脚本的内容。

I work for Zaber Technologies, and I built a control library for our precision stepper motor controllers that communicate over a daisy-chained serial connection. I used three layers:

  1. The port - this layer is just concerned with the communication protocol. It exposes methods for sending a message, and it converts the message parameters into a byte stream. It also listens on the incoming line, converts the byte stream into a message structure, and raises an event when the complete message has been received.
  2. The device - this layer knows how to send messages to a specific device in the daisy chain and how to filter out responses from other devices in the daisy chain.
  3. The conversation - this layer coordinates requests and responses and lets calling code make a request that will block the thread until a response comes back.

Calling code then has the choice of whether to use synchronous requests with the conversation layer, or use asynchronous requests with the device layer.

If you're interested in more details, you can download the source code or look at the user documentation that talks about writing scripts against the library.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文