Micropython——基于PYB的霍尔编码器电机测速与使用

1.编码器电机简介

霍尔传感器

霍尔传感器是根据据霍尔效应制作的一du种磁场传感器。霍尔效应zhi是磁电效应的一种,这一现dao象是霍尔(A.H.Hall,1855—1938)于1879年在研究金属的导电机构时发现的。后来发现半导体、导电流体等也有这种效应,而半导体的霍尔效应比金属强得多,利用这现象制成的各种霍尔元件,广泛地应用于工业自动化技术、检测技术及信息处理等方面。霍尔效应是研究半导体材料性能的基本方法。通过霍尔效应实验测定的霍尔系数,能够判断半导体材料的导电类型、载流子浓度及载流子迁移率等重要参数。
磁场中有一个霍尔半导体片,恒定电流I从A到B通过该片。在洛仑兹力的作用下,I的电子流在通过霍尔半导体时向一侧偏移,使该片在CD方向上产生电位差,这就是所谓的霍尔电压。
在这里插入图片描述

霍尔电压随磁场强度的变化而变化,磁场越强,电压越高,磁场越弱,电压越低,霍尔电压值很小,通常只有几个毫伏,但经集成电路中的放大器放大,就能使该电压放大到足以输出较强的信号。若使霍尔集成电路起传感作用,需要用机械的方法来改变磁感应强度。下图所示的方法是用一个转动的叶轮作为控制磁通量的开关,当叶轮叶片处于磁铁和霍尔集成电路之间的气隙中时,磁场偏离集成片,霍尔电压消失。这样,霍尔集成电路的输出电压的变化,就能表示出叶轮驱动轴的某一位置,利用这一工作原理,可将霍尔集成电路片用作用点火正时传感器。霍尔效应传感器属于被动型传感器,它要有外加电源才能工作,这一特点使它能检测转速低的运转情况。

编码器电机

使用“智能小车之家”的编码器电机,具体信息参数如下:
在这里插入图片描述

脉冲计数方法

每台编码器的规格指标中,都有标明线数是多少。
单位是:线/圈
假设是1024线/圈,那么就意味着编码器每转一圈,就将送出1024个A相和1024个B相的脉冲。
如果是一倍频(就是完整的接收到一个A相脉冲上升沿和一个B相脉冲上升沿后,计一个脉冲),那么就是接收到1024个脉冲;如果是4倍频(每一个A相和B相脉冲的上升沿和下降沿都计一个脉冲,那么一对AB相脉冲,接收器就计4个),那么就是接收到4096个脉冲。

因为在Micropython的Timer库中有专门的编码器读取模式,该模式是在CH1和CH2改变时改变,所以技术方式为4倍频。

  • Timer.ENC_AB — 配置编码器模式下的定时器。定时器只在CH1和CH2改变时改变。

本电机对应的脉冲计速方法
线数为390,即在一倍频、单相的情况下,每圈会有390个脉冲;在四倍频、AB相的情况下,每圈会有1560个脉冲。

  • 脉冲测速方法:
  • n = 脉冲数/采样时间
  • 角速度:w = 2 π n
  • 线速度:v = w r

2.编码器电机接线

MG540PYB
编码器A相X1(TIM2,CH1)
编码器B相X2(TIM2,CH2)
编码器5VV+(Vin)
编码器GNDGND
电机12V12V电源
电机GND电源GND

3.通过定时器的编码器模式读取编码器数值

使用putty远程连接输入代码,进行测试:

from pyb import Timer, Pin
#定义引脚
p1 = Pin("X1")
p2 = Pin("X2")
tim=pyb.Timer(2)
tim.init(prescaler=0,period=10000)
ch1=tim.channel(1,pyb.Timer.ENC_AB,pin=p1)
ch2=tim.channel(2,pyb.Timer.ENC_AB, pin=p2)

tim.counter()

读取结果

在这里插入图片描述

定时器中断定时读取编码器代码

1.采用计数编码器周期的方式进行测算速度

将以下代码写入main.py中,进行执行即可。

from pyb import Timer, Pin

def cb(t):
    pyb.LED(3).toggle()
    print(tim.counter())

#配置编码器AB相读取模式,利用定时器中断进行读取
p1 = Pin("X1")
p2 = Pin("X2")
tim=pyb.Timer(2)
tim.init(prescaler=0,period=10000, callback=cb)
ch1=tim.channel(1,pyb.Timer.ENC_AB,pin=p1)
ch2=tim.channel(2,pyb.Timer.ENC_AB, pin=p2)
2.采用固定频率计算编码器当前值的方式进行测算速度(推荐)

将以下代码写入main.py中,进行执行即可。

from pyb import Timer, Pin
#配置编码器AB相读取模式,利用定时器中断进行读取
p1 = Pin("X1")
p2 = Pin("X2")
tim=pyb.Timer(2)
tim.init(prescaler=0,period=10000)
ch1=tim.channel(1,pyb.Timer.ENC_AB,pin=p1)
ch2=tim.channel(2,pyb.Timer.ENC_AB, pin=p2)

def cb2(t):
    print(tim.counter())   #读取编码器值
    tim.counter(0)   #将编码器值设未0,清0

tim2=pyb.Timer(10,freq=10,callback=cb2)

实时返回读取结果

以10的频率定时返回编码器的当前值。
即在0.1s内,编码器发出了XXX个脉冲。通过脉冲可以算出当前的速度。

在这里插入图片描述

4.封装编码器读取模块

为了方便使用,在这里我将编码器读取任务封装为一个py模块。

encoder.py

import pyb
from pyb import Timer, Pin
import cmath
"""
入口参数:编码器读取频率

# 编码器电机参数参考
    1.光电编码器电机(MG513P30_12V)的参数:
        减速比:1:30
        分辨率(电机驱动线数):500ppr(编码器精度,转一圈输出的脉冲数)

    2.霍尔编码器电机()的参数:
        减速比:1:30
        分辨率:13ppr

# 底盘机械参数参考
    标准轮式机器人硬件尺寸参数:
        轮子直径:6.5cm
        两轮间距:16cm

    履带式机器人硬件尺寸参数:
        轮子直径:4cm
        两轮间距:23cm
"""

class Encoder:
    '''
    机器人自身及编码器电机配置
    '''
    def __init__(self, encoder_freq):
        '''————————————————————————————可调参数——————————————————————————————————'''
        # -------底盘机械参数--------
        self.wheel_distance = 0.160         # 轮间距,单位:cm
        self.Wheel_diameter = 0.065         # 轮直径:单位:cm
        # -------编码器电机参数--------
        reduction_ratio = 1/30              # 减速比,
        resolution_ratio = 500              # 分辨率,单位:ppr
        
        '''————————————————————————————系统参数——————————————————————————————————'''
        #配置编码器AB相读取模式,利用定时器中断进行读取
        p1_A = Pin("Y1"); p2_A = Pin("Y2");
        tim_A = Timer(8)
        tim_A.init(prescaler=0,period=10000)
        ch1_A = tim_A.channel(1,Timer.ENC_AB,pin=p1_A); ch2_A = tim_A.channel(2,Timer.ENC_AB, pin=p2_A);
        p1_B = Pin("X1"); p2_B = Pin("X2");
        tim_B = Timer(5)
        tim_B.init(prescaler=0,period=10000)
        ch1_B = tim_B.channel(1,Timer.ENC_AB,pin=p1_B); ch2_B = tim_B.channel(2,Timer.ENC_AB, pin=p2_B)
        
        # 初始化系统参数
        freq_multiplier = 4 # 倍频数
        self.pi = cmath.pi # pi的值
        self.encoder_freq = encoder_freq
        self.encoder_precision = freq_multiplier * resolution_ratio / reduction_ratio # 编码器精度 = 倍频数*编码器精度(电机驱动线数)*电机减速比
        self.tim_A = tim_A
        self.tim_B = tim_B
        self.encoder_A = 0
        self.encoder_B = 0
        # 定时器中断:固定时间读取编码器数值
        timer_read = Timer(10,freq=self.encoder_freq,callback=self.encoder_cb)

    def encoder_cb(self, encoder):
        '''
        函数功能:通过定时器中断读取编码器A、B计数值,并重置编码器
        '''    
        if self.tim_B.counter() > 5000:
            self.encoder_B = 10000 - self.tim_B.counter()
        else:
            self.encoder_B = -self.tim_B.counter()
        self.tim_B.counter(0)
        if self.tim_A.counter() > 5000:
            self.encoder_A = -(10000 - self.tim_A.counter()) 
        else:
            self.encoder_A = self.tim_A.counter()
        self.tim_A.counter(0)

    def target_enc_process(self, speed):
        '''
        函数功能:将目标速度值转化为目标编码器值
        入口参数:目标速度值
        返回值  :目标编码器值
        # 目标编码器值=(目标速度*编码器精度)/(轮子周长*控制频率)
        '''
        enc = (speed*self.encoder_precision) / ( (self.pi*self.Wheel_diameter) * self.encoder_freq)
        return enc
    
    def enc_to_speed(self, enc):
        '''
        函数功能:将编码器值转化为速度值
        入口参数:编码器值
        返回值:速度值
        速度值=(采集到的脉冲数/编码器精度)*轮子周长*控制频率
        '''
        speed = (enc / self.encoder_precision) * (self.pi*self.Wheel_diameter) * self.encoder_freq
        return speed
    
    '''
    # 已知量,单位m
        v = 0 # 机器人的线速度
        w = 0 # 机器人的角速度
        v_l = 0 # 左轮速度
        v_r = 0 # 右轮速度
        D = 0.2 # 轮间距
        d = D/2
    # 速度、角速度、左右轮速的关系式
        v_l = v + wd
        v_r = v - wd
        v = (v_l + v_r)/2 
        w = (v_l - v_r)/D
    '''

    def speed_to_anglin(self, speed_A, speed_B):
        '''
        函数功能:将两轮速度值转化为角速度和线速度值
        入口参数:两轮速度值
        返回值:角速度,线速度
        '''
        linear_vel = (speed_A + speed_B)/2
        angular_vel = (speed_B - speed_A)/self.wheel_distance
        return angular_vel, linear_vel

    def anglin_to_speed(self, angular_vel, linear_vel):
        '''
        函数功能:将角速度和线速度值转化为两轮速度值
        入口参数:角速度,线速度
        返回值:两轮速度值
        '''
        speed_A = linear_vel - angular_vel * self.wheel_distance/2
        speed_B = linear_vel + angular_vel * self.wheel_distance/2
        return speed_A, speed_B

调用方法

main.py

import encoder

if __name__ == '__main__':
	# 编码器初始化
    print("编码器初始化----")
    encoder_freq = 100 # 编码器读取频率,一般都为100Hz
    enc = encoder.Encoder(encoder_freq)
    # 获取当前编码器值
    enc_A = enc.encoder_A  
    enc_B = enc.encoder_B 
    speed_A = enc.enc_to_speed(enc_A)
    speed_B = enc.enc_to_speed(enc_B)
    angular_vel, linear_vel = enc.speed_to_anglin(speed_A, speed_B)

5.利用编码器实现电机PID调节

可以直接看我的另一篇基于PYB和编码器的PID调节博客:

Micropython——基于PYB的霍尔编码器电机的PID控制

  • 21
    点赞
  • 158
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值