amobbs.com 阿莫电子技术论坛

标题: 求:单片机采集20路编码器的思路 [打印本页]

作者: lb0857    时间: 2021-9-27 18:05
标题: 求:单片机采集20路编码器的思路
测量20路电机转速  ,  利用机器现有的编码器进行
编码器输出脉冲频率  最大  400hz     最低60hz   

一共是20路     需要实时采集频率送给上位机进行处理   
中断  /STM32单片机也就16路     是一个问题

坛友 有没有其他好的思路  望赐教   好的建议  lz请吃汤圆
作者: 令狐冲    时间: 2021-9-27 18:07
用两片单片机
作者: BOERLBH    时间: 2021-9-27 18:27
是总共20路编码器的AB信号还是 20个编码器? 第一种情况 简单,相当于只用采集10路信号就行,方向信号用硬件+普通IO口判断。 第二中情况。能不能这样做。 比如 1-16 路接在PA0-PA15上,17-20 接在PB12-PB15上。然后在中断里面判断具体引脚。 这个我没试验过,也不知道。
作者: wycox    时间: 2021-9-27 18:40
采用外部计数器芯片吧
作者: lb0857    时间: 2021-9-27 20:41
CD4051单端8通道多路开关,
C、B、A 用来选择通道号  输出到单片机中断io口
分时进行中断采集
如: 50ms给每一路采集时间   
多次采集进行滤波处理之后 即可
这是其他项目采用方案  用起来效果还可以  不占用太多中断资源   普通STC单片机也可以胜任
作者: dukelec    时间: 2021-9-27 20:42
編碼器端加小板子把數據轉 485 再傳送到 MCU
作者: BOERLBH    时间: 2021-9-27 20:48
你这个频率比较低,STM32 所有有IO都能当外部中断输入。用一个定时器做一个 比如10uS的时基。然后再定义20个变量。两次外部中断上升沿(或者下降沿)之间 让对应的变量计数。根据计数值就能算出频率。时基越小精度越高。20路 400Hz 我估计没问题。以前 我用这种方式 在C8051上 做过PWM输出(相当于IO口模拟PWM)。2路频率2K都没问题。
作者: wye11083    时间: 2021-9-27 21:00
BOERLBH 发表于 2021-9-27 20:48
你这个频率比较低,STM32 所有有IO都能当外部中断输入。用一个定时器做一个 比如10uS的时基。然后再定义20 ...

你这太费劲了。最简单最便宜的,stc8调到4khz中断,然后去读io,之后用软件去解码。仅仅是计算个频率而已,最大400hz,中断读数据,正常状态处理数据,轻轻松松而已。
作者: lb0857    时间: 2021-9-27 21:33
谢谢各位参与  汤圆请笑纳
作者: modbus    时间: 2021-9-27 21:39
0.5ms的定时中断扫描IO足矣
作者: lb0857    时间: 2021-9-27 23:01

如果用CD4051单端8通道多路开关,50ms转换一次端口  20个刚好是1s
然后,根据一个io口-----50ms采集到的脉冲数量*50   就是时间1s单路的脉冲总数  
分时复用   
这样方案  大家看看如何
作者: bad_fpga    时间: 2023-9-15 22:36
lb0857 发表于 2021-9-27 23:01
如果用CD4051单端8通道多路开关,50ms转换一次端口  20个刚好是1s
然后,根据一个io口-----50ms采集到的脉 ...
(引用自11楼)

最后采用什么方案了?
作者: tomzbj    时间: 2023-9-15 23:33
参考之前看到的一个旋转编码器的驱动, 挺有意思
用两个普通GPIO, 每次读2bit, 把上次的2bit左移两位, 拼成4bit
那么如果转了, 只能是0001, 0111, 1110, 1000, 或者是0010, 1011, 1101, 0100这8种情况.
如果是0000, 0101, 1010, 1111, 说明没转, 如果是0011, 1100, 0110, 1001, 说明读取间隔太慢, 漏读了一次.

然后把读编码器的函数做成回调, 下面的g.read_f, 这样用哪些GPIO读取可以任意搭配, 方便连线.
判断正转或反转的操作也做成回调, 下面的g.action_f.
old_state数组是各个编码器的旧状态.

只要读得过来, 想读几个都行.

  1.     for(int i = 0; i < ZRE_NUM; i++) {
  2.         unsigned char state = ((g.old_state[i] << 2) | g.read_f(i)) & 0xf;            // 只需要4bit
  3.         switch(state) {
  4.             case 0x1:
  5.             case 0x7:
  6.             case 0xe:
  7.             case 0x8:
  8.                 g.action_f(i, ZRE_CW);             // 顺时针
  9.                 break;
  10.             case 0x2:
  11.             case 0xb:
  12.             case 0xd:
  13.             case 0x4:
  14.                 g.action_f(i, ZRE_CCW);           // 逆时针
  15.                 break;
  16.         }
  17.         g.old_state[i] = state;               // 保存状态供下次使用
  18.     }
复制代码

作者: 老徐    时间: 2023-9-16 00:39
如果真的不认同分时复用的方案,可以将一半通道采用频压转换,一半10个采用AD引脚采集,一半10个接10个定时器




欢迎光临 amobbs.com 阿莫电子技术论坛 (https://www.amobbs.com/) Powered by Discuz! X3.4