树莓派PCA9685的舵机MG996R二度自由云台操控代码,搭配mqtt进行远程操控

# -*- coding:utf-8 -*-
import time
#引入pca9685的原始代码
import machine
#这里加入了灯光展示
from light import Light
#引入mqtt的paho
import paho.mqtt.client as mqtt

#本地ip
MQTTHOST = "127.0.0.1"
#mqtt的端口号
MQTTPORT = 1883
#初始化mqttClient
mqttClient = mqtt.Client()

#初始化pwm
pwm = machine.PCA9685(0x40, debug=False)
#设置pwm的频率
pwm.setPWMFreq(50)

#设置初始上下位置为中间,(500+2500)/2 = 1500
up = 1500
#设置初始左右位置为中间
dw = 1500
#设置灯的接口位置
led = Light(17)

# 消息处理函数
def on_message_come(client, userdata, msg):
    topicmsg = str(msg.payload.decode("utf-8"))
    msgList = topicmsg.split(',', 1)
    #evalFunc的作用是将接受的命令字符串变成对应的方法进行执行
    evalFunc(msgList[0], msgList[1])

# 连接MQTT服务器
def on_mqtt_connect():
    mqttClient.connect(MQTTHOST, MQTTPORT, 60)    

# subscribe 消息订阅
def on_subscribe(top):
    mqttClient.subscribe(top, 1)  # 主题为"mqtt"
    mqttClient.on_message = on_message_come  # 消息到来处理函数
    mqttClient.loop_forever()

def evalFunc(func, n):
    #例如获取到了mqtt消息,right,1 ,这个表示执行向右1个单位,一共10个单位 
    print(str(func) + '(' + str(n) + ')')
    #eval可以调用方法进行执行
    eval(str(func) + '(' + str(n) + ')')

#这个是恢复到初始位置
def reset(n):
    led.blink()
    global up
    global dw
    for i in range(1400,1500,1):
        pwm.setServoPulse(0,i)
        time.sleep(0.00025)
    for i in range(1400,1500,1):
        pwm.setServoPulse(1,i)
        time.sleep(0.00025)
    up = 1500
    dw = 1500

#这个是向前进的代码
def front(n):
    n = int(n)
    #这里我自定义n乘以5,是因为我之前每次执行一个单位,我想一次性执行5个单位的向下
    n = n * 5
    #灯光闪烁
    led.blink()
    global up
    #这里会判断是否已经到了阈值范围,如果到了则不执行下一步
    if up != 2500:
        #开启循环进行,从up到up+100*n,每次走100 * n个距离,当然这里你可以10 * n,这样舵机移动的角度非常小非常小
        #我这里500~2500一共是2000个,分20下100 * n,当n为1时,则移动20下从最前边到最后边,角度大概是从0度到180度这样,具体度数描述不太准确,请见谅
        #现在n = n * 5,意味着我只需要4下就从最前边到最后面,具体根据你的度数范围来,还有根据你移动的角度大小来决定舵机的速度
        for i in range(up,up+100*n,1*n):
            pwm.setServoPulse(0,i)
            time.sleep(0.00025)
        #每次执行完毕后,up都会变化
        up += 100*n
        #这里防止up变大超过2500,则变为2500
        if up > 2500:
            up = 2500

def back(n):
    n = int(n)
    n = n * 5
    led.blink()
    global up
    if up != 500:
        for i in range(up,up-100*n,-1*n):
            pwm.setServoPulse(0,i)
            time.sleep(0.00025)
        up -= 100*n
        if up < 500:
            up = 500

def left(n):
    n = int(n)
    n = n * 2
    led.blink()
    global dw
    if dw != 2500:
        for i in range(dw,dw+100*n,1*n):
            pwm.setServoPulse(1,i)
            time.sleep(0.00025)
        dw += 100*n
        if dw > 2500:
            dw = 2500

def right(n):
    n = int(n)
    n = n * 2
    led.blink()
    global dw
    if dw != 500:
        for i in range(dw,dw-100*n,-1*n):
            pwm.setServoPulse(1,i)
            time.sleep(0.00025)
        dw -= 100*n
        if dw < 500:
            dw = 500

if __name__ == '__main__':
    topic='mqtt'
    on_mqtt_connect()
    on_subscribe(topic)

下面是machine的代码,也就是PCA9685的python3测试代码

#!/usr/bin/python

import time
import math
import smbus

# ============================================================================
# Raspi PCA9685 16-Channel PWM Servo Driver
# ============================================================================

class PCA9685:

  # Registers/etc.
  __SUBADR1            = 0x02
  __SUBADR2            = 0x03
  __SUBADR3            = 0x04
  __MODE1              = 0x00
  __PRESCALE           = 0xFE
  __LED0_ON_L          = 0x06
  __LED0_ON_H          = 0x07
  __LED0_OFF_L         = 0x08
  __LED0_OFF_H         = 0x09
  __ALLLED_ON_L        = 0xFA
  __ALLLED_ON_H        = 0xFB
  __ALLLED_OFF_L       = 0xFC
  __ALLLED_OFF_H       = 0xFD

  def __init__(self, address=0x40, debug=False):
    self.bus = smbus.SMBus(1)
    self.address = address
    self.debug = debug
    if (self.debug):
      print("Reseting PCA9685")
    self.write(self.__MODE1, 0x00)
	
  def write(self, reg, value):
    "Writes an 8-bit value to the specified register/address"
    self.bus.write_byte_data(self.address, reg, value)
    if (self.debug):
      print("I2C: Write 0x%02X to register 0x%02X" % (value, reg))
	  
  def read(self, reg):
    "Read an unsigned byte from the I2C device"
    result = self.bus.read_byte_data(self.address, reg)
    if (self.debug):
      print("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" % (self.address, result & 0xFF, reg))
    return result
	
  def setPWMFreq(self, freq):
    "Sets the PWM frequency"
    prescaleval = 25000000.0    # 25MHz
    prescaleval /= 4096.0       # 12-bit
    prescaleval /= float(freq)
    prescaleval -= 1.0
    if (self.debug):
      print("Setting PWM frequency to %d Hz" % freq)
      print("Estimated pre-scale: %d" % prescaleval)
    prescale = math.floor(prescaleval + 0.5)
    if (self.debug):
      print("Final pre-scale: %d" % prescale)

    oldmode = self.read(self.__MODE1);
    newmode = (oldmode & 0x7F) | 0x10        # sleep
    self.write(self.__MODE1, newmode)        # go to sleep
    self.write(self.__PRESCALE, int(math.floor(prescale)))
    self.write(self.__MODE1, oldmode)
    time.sleep(0.005)
    self.write(self.__MODE1, oldmode | 0x80)

  def setPWM(self, channel, on, off):
    "Sets a single PWM channel"
    self.write(self.__LED0_ON_L+4*channel, on & 0xFF)
    self.write(self.__LED0_ON_H+4*channel, on >> 8)
    self.write(self.__LED0_OFF_L+4*channel, off & 0xFF)
    self.write(self.__LED0_OFF_H+4*channel, off >> 8)
    if (self.debug):
      print("channel: %d  LED_ON: %d LED_OFF: %d" % (channel,on,off))
	  
  def setServoPulse(self, channel, pulse):
    "Sets the Servo Pulse,The PWM frequency must be 50HZ"
    pulse = pulse*4096/20000        #PWM frequency is 50HZ,the period is 20000us
    self.setPWM(channel, 0, int(pulse))

if __name__=='__main__':
 
  pwm = PCA9685(0x40, debug=False)
  pwm.setPWMFreq(50)
  while True:
   # setServoPulse(2,2500)
    for i in range(500,2500,10):  
      pwm.setServoPulse(0,i)   
      time.sleep(0.02)     
    
    for i in range(2500,500,-10):
      pwm.setServoPulse(0,i) 
      time.sleep(0.02)  

Python2的代码在此

#!/usr/bin/python

import time
import math
import smbus

# ============================================================================
# Raspi PCA9685 16-Channel PWM Servo Driver
# ============================================================================

class PCA9685:

  # Registers/etc.
  __SUBADR1            = 0x02
  __SUBADR2            = 0x03
  __SUBADR3            = 0x04
  __MODE1              = 0x00
  __PRESCALE           = 0xFE
  __LED0_ON_L          = 0x06
  __LED0_ON_H          = 0x07
  __LED0_OFF_L         = 0x08
  __LED0_OFF_H         = 0x09
  __ALLLED_ON_L        = 0xFA
  __ALLLED_ON_H        = 0xFB
  __ALLLED_OFF_L       = 0xFC
  __ALLLED_OFF_H       = 0xFD

  def __init__(self, address=0x40, debug=False):
    self.bus = smbus.SMBus(1)
    self.address = address
    self.debug = debug
    if (self.debug):
      print("Reseting PCA9685")
    self.write(self.__MODE1, 0x00)
	
  def write(self, reg, value):
    "Writes an 8-bit value to the specified register/address"
    self.bus.write_byte_data(self.address, reg, value)
    if (self.debug):
      print("I2C: Write 0x%02X to register 0x%02X" % (value, reg))
	  
  def read(self, reg):
    "Read an unsigned byte from the I2C device"
    result = self.bus.read_byte_data(self.address, reg)
    if (self.debug):
      print("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" % (self.address, result & 0xFF, reg))
    return result
	
  def setPWMFreq(self, freq):
    "Sets the PWM frequency"
    prescaleval = 25000000.0    # 25MHz
    prescaleval /= 4096.0       # 12-bit
    prescaleval /= float(freq)
    prescaleval -= 1.0
    if (self.debug):
      print("Setting PWM frequency to %d Hz" % freq)
      print("Estimated pre-scale: %d" % prescaleval)
    prescale = math.floor(prescaleval + 0.5)
    if (self.debug):
      print("Final pre-scale: %d" % prescale)

    oldmode = self.read(self.__MODE1);
    newmode = (oldmode & 0x7F) | 0x10        # sleep
    self.write(self.__MODE1, newmode)        # go to sleep
    self.write(self.__PRESCALE, int(math.floor(prescale)))
    self.write(self.__MODE1, oldmode)
    time.sleep(0.005)
    self.write(self.__MODE1, oldmode | 0x80)

  def setPWM(self, channel, on, off):
    "Sets a single PWM channel"
    self.write(self.__LED0_ON_L+4*channel, on & 0xFF)
    self.write(self.__LED0_ON_H+4*channel, on >> 8)
    self.write(self.__LED0_OFF_L+4*channel, off & 0xFF)
    self.write(self.__LED0_OFF_H+4*channel, off >> 8)
    if (self.debug):
      print("channel: %d  LED_ON: %d LED_OFF: %d" % (channel,on,off))
	  
  def setServoPulse(self, channel, pulse):
    "Sets the Servo Pulse,The PWM frequency must be 50HZ"
    pulse = pulse*4096/20000        #PWM frequency is 50HZ,the period is 20000us
    self.setPWM(channel, 0, int(pulse))

if __name__=='__main__':
 
  pwm = PCA9685(0x40, debug=False)
  pwm.setPWMFreq(50)
  while True:
   # setServoPulse(2,2500)
    for i in range(500,2500,10):  
      pwm.setServoPulse(0,i)   
      time.sleep(0.02)     
    
    for i in range(2500,500,-10):
      pwm.setServoPulse(0,i) 
      time.sleep(0.02)

具体的代码在此,包括python2和python3还有C的代码都在此,想多了解的可以下载一下,也可以不下载,代码也贴出来了,点击下载

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章