查看: 326|回复: 6

[已解决] 用 PyQt GUI 界面下的旋钮控制舵机角度

[复制链接]

该用户从未签到

发表于 2020-7-5 04:14 | 显示全部楼层 |阅读模式
本帖最后由 sun0727 于 2020-7-10 04:46 编辑

新人报道,

我想用 PyQt 下的 Dial 旋钮模块来控制舵机的角度。如果一切正常,这个 GUI 的旋钮和舵机应该近似同步旋转。

Xnip2020-07-04_22-04-27.jpg

基本思路我想的很简单,就是将旋钮对应的 Value 通过串口传递给 Arduino


对应相关代码:

Arduino 部分


  1. void loop(){

  2.     // while(!Serial){} //
  3.    if(Serial.available()>0){        
  4.        posOrder = Serial.readString(); // get Angle-Value from Serial
  5.         
  6.        // write to Serial Monitor
  7.         Serial.print("Set Servo Position to: ");   
  8.         Serial.println(posOrder);

  9.         int angle = posOrder.toInt();
  10.         myservo.write(angle);   
  11.         Serial.flush();
  12.      
  13.         delay(30);
  14.     }
  15. }
复制代码

GUI 部分

  1. ## ....some code...

  2.    self.dial.valueChanged.connect(self.writeToSerial)

  3. ## ...

  4. def writeToSerial(self):  
  5.      # create serial connection
  6.      self.ser = serial.Serial(self.portPath, timeout=None, baudrate=self.baudRate)
  7.       
  8.      self.posAngle = self.dial.value()  # get value
  9.      self.ser.write(str(self.posAngle).encode()) # write to Serial
复制代码



原理很简单,就是当旋钮的值变化时,触发 dial.valueChanged.connect(self.writeToSerial),然后 wirteToSerial 函数会被调用,相应的值就会通过串口传给单片机。

问题是,如果仅仅是通过鼠标点击旋钮刻度,那么工作的很正常。每点击一下,就传递一个值过去。Serial Monitor 看起来是这样的

  1. Set Servo Position to: 65
  2. Set Servo Position to: 90
  3. Set Servo Position to: 170
复制代码



但是,如果是用按住鼠标左键拖动旋钮转动的方式,由于旋钮的值此时变化差不多是连续的,dial.valueChanged.connect(self.writeToSerial) 会被频繁调用,相应的写入串口的操作也会频繁进行,速度跟不上后,Serial Monitor 看起来这样

  1. Set Servo Position to: 65666770717273747677
  2. Set Servo Position to: 99100104108109114116119122126128130131133
  3. Set Servo Position to: 1411421431441451461481501521541561
复制代码
可以看出来,是连续几个角度值拼接在一起了。

当然,也可以通过设置,让读取旋钮值的行为发生在旋钮松开后,但是这样的话,两者不同步了。舵机只会在旋钮位置设置好后才旋转,而不是同步旋转。



请问大神们有什么好的解决办法没?先谢过







该用户从未签到

发表于 2020-7-5 18:20 | 显示全部楼层
sun0727 发表于 2020-7-5 17:04
我现在改成换行符分隔了

发送方:ser.write("{}\n".format(self.posAngle).encode())

如果你是用串口发送数据的,那么尽量提高串口的波特率,否则会出现丢帧。

如果波特率已经很高了,还是丢帧的话,那就要加入校验,最简单的就是增加一个校验和字节,接收方如果校验不通过,就直接舍弃。

该用户从未签到

发表于 2020-7-5 10:38 | 显示全部楼层
不管你用什么方式传输数据,都必须事先定义好数据传输的格式,否则接收方就无法准确的解析数据。

比如最简单的,定长格式,3个字节。那么发送方将数据转换成3个字节,比如65转换成065,然后接收方3个字节一收。

也可以用结束码,比如回车。那么65转换成65回车,接收方在收到回车后,才将之前的内容转换成数字。

该用户从未签到

 楼主| 发表于 2020-7-5 17:04 | 显示全部楼层
开在边缘 发表于 2020-7-5 10:38
不管你用什么方式传输数据,都必须事先定义好数据传输的格式,否则接收方就无法准确的解析数据。

比如最简 ...

我现在改成换行符分隔了

发送方:ser.write("{}\n".format(self.posAngle).encode())

接收方:posOrder = Serial.readStringUntil('\n');

虽然比以前改善很多,但是 GUI 上一转得快,依旧有几个连起来的

该用户从未签到

 楼主| 发表于 2020-7-5 19:54 | 显示全部楼层
开在边缘 发表于 2020-7-5 18:20
如果你是用串口发送数据的,那么尽量提高串口的波特率,否则会出现丢帧。

如果波特率已经很高了,还是丢 ...

新人表示我太菜了  Python Serial 地方我设置了一个 奇校验或者偶校验,但是没用。 这个校验位正确如何处理,Arduino 地方如何设置呢

该用户从未签到

发表于 2020-7-5 20:36 | 显示全部楼层
sun0727 发表于 2020-7-5 19:54
新人表示我太菜了  Python Serial 地方我设置了一个 奇校验或者偶校验,但是没用。 这个校验位正确如 ...


我说的校验和,是指软件层面的校验,并不是指串口的奇偶校验。

比如说,你要传输的内容是纯数字456,然后以换行作为分隔符,那么发送方从串口发送出去的内容就是“456\n”。如果传输的时候丢帧了,接收方有可能收到的数据是“46\n”,那么这时候我们就需要增加一个校验和。我们把456相加取和,4+5+6=15,然后取低8位(也就是个位数“5”)做为内容一起发送,那么发送出去的就是“4565\n”。那么当接收方收到数据后,做一个同样方式的校验,就能知道收到的数据是不是完整的。

如果发送的内容不是纯数字,还有英文字母、符号之类的,那就转换成ascii码进行相加取和,然后取低8位就可以了。

该用户从未签到

 楼主| 发表于 2020-7-5 22:35 | 显示全部楼层
开在边缘 发表于 2020-7-5 20:36
我说的校验和,是指软件层面的校验,并不是指串口的奇偶校验。

比如说,你要传输的内容是纯数字456,然 ...

谢谢你

目前我把 发送方改成 发送一个字节,posAngleInByte = self.posAngle.to_bytes(length=1, byteorder='big') 然后 Arduino 单纯用 Serial.read()  貌似解决了问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

热门推荐

5分钟带你快速了解新一代开发板:M5STACK
5分钟带你快速了解新一代
一、什么是M5Stack M5Stack是一种模块化、可堆叠扩展的开发板,每个模块
Arduino UNO中文数据手册
Arduino UNO中文数据手册
2018.9.23重新翻译整理 转载请注明来自Arduino中文社区,并附本帖链接 本帖地址:http
LabVIEW监控温度传感器
LabVIEW监控温度传感器
这里涉及 dht11 数字温度湿度传感器模块、TM1637数码显示模块、LabVIEW。 功能
黑乌鸦的Arduino兵器库-----DS1302时钟模块
黑乌鸦的Arduino兵器库---
嗯 这是一个系列后期会罗列几乎所有的常见基础模块的demo所以 大家的回复将是我最大
中文 字库 的8针 OLED 12864模块 arduino
中文 字库 的8针 OLED 128
屏幕电路SPI连线: 中文字库OLED Arduino UNO GND GND
Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
快速回复 返回顶部 返回列表