Python 物联网入门指南(八)(2)

简介: Python 物联网入门指南(八)

Python 物联网入门指南(八)(1)https://developer.aliyun.com/article/1507342

寻找极限

机械臂套件在 eBay 或亚马逊上相对容易获得。这并不难组装,需要几个小时来准备。一些机械臂套件可能不会随舵机一起发货,如果是这样,你可能需要单独订购。我建议选择与舵机捆绑在一起的套件,因为如果你选择单独订购舵机,可能会出现兼容性问题。

正如你所知,这些舵机将使用 PWM 工作,控制它们也不难。所以,让我们直接开始并看看我们能做些什么。一旦你组装好了机械臂套件,将舵机的线连接如下:


现在,首先,我们需要知道我们机器人上连接的每个舵机的最大物理极限是什么。有各种各样的技术可以做到这一点。最基本的方法是进行物理测量。这种方法可能很好,但你将无法充分利用舵机电机的全部潜力,因为在测量时会有一定程度的误差。因此,你放入舵机的值将略小于你认为它可以达到的值。第二种方法是手动输入数据并找出确切的角度。所以,让我们继续用第二种方法做事情,并上传以下代码:

import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setup(14,GPIO.OUT) GPIO.setup(16,GPIO.OUT) GPIO.setup(18,GPIO.OUT) GPIO.setup(20,GPIO.OUT) GPIO.setup(21,GPIO.OUT) GPIO.setup(22,GPIO.OUT)
  GPIO.setwarnings(False) pwm1 = GPIO.PWM(14, 50) pwm2 = GPIO.PWM(16, 50) pwm3 = GPIO.PWM(18, 50) pwm4 = GPIO.PWM(20, 50) pwm5 = GPIO.PWM(21, 50) pwm6 = GPIO.PWM(22, 50)
  pwm1.start(0) pwm2.start(0) pwm3.start(0) pwm4.start(0) pwm5.start(0) pwm6.start(0)  def cvt_angle(angle):     dc = float(angle/90) + 0.5
    return dc  while 1:
 j = input('select servo')  if j == 1: i = input('select value to rotate')
  pwm1.ChangeDutyCycle(cvt_angle(i))
 time.sleep(2)
  pwm1.ChangeDutyCycle(cvt_angle(90)) elif j ==2:  i = input('select value to rotate')   pwm2.ChangeDutyCycle(cvt_angle(i))
 time.sleep(2) pwm2.ChangeDutyCycle(cvt_angle(90))   elif j ==3:   i = input('select value to rotate') pwm3.ChangeDutyCycle(cvt_angle(i))
 time.sleep(2) pwm3.ChangeDutyCycle(cvt_angle(90))  elif j ==4:  i = input('select value to rotate')
  pwm4.ChangeDutyCycle(cvt_angle(i))
 time.sleep(2) pwm4.ChangeDutyCycle(cvt_angle(90))  elif j ==5:  i = input('select value to rotate')
  pwm5.ChangeDutyCycle(cvt_angle(i))
 time.sleep(2) pwm5.ChangeDutyCycle(cvt_angle(90))  elif j ==6:  i = input('select value to rotate')   pwm6.ChangeDutyCycle(cvt_angle(i))
 time.sleep(2) pwm6.ChangeDutyCycle(cvt_angle(90)) }

现在,让我们看看这段代码在做什么。这段代码看起来可能相当复杂,但它所做的事情非常简单。

j = input('select servo from 1-6')

使用前面的代码行,我们正在为用户打印从 1-6 选择舵机的语句。当用户输入舵机的值时,这个值被存储在一个名为j的变量中:

if j == 1: i = input('select value to rotate')
  pwm1.ChangeDutyCycle(cvt_angle(i))
 time.sleep(2) pwm1.ChangeDutyCycle(cvt_angle(90))  

这里的if条件检查j的值。如果在这一行中,j=1,那么它将运行与舵机编号1对应的代码。在这段代码中,第一行将打印选择要旋转的值。完成后,程序将等待用户输入。一旦用户输入任何值,它将被存储在一个名为I的变量中。然后,使用cvt_angle(i)函数,用户输入的值将被转换为相应的占空比值。这个占空比值将被获取到pwm1.ChangeDutyCycle()参数中,从而给予机器人你想要的特定关节角度。由于time.sleep(2)函数,舵机将等待到下一行。之后,我们使用pwm1.ChangeDutyCycle(cvt_angle(90))这一行,这将把它带回到 90 度。

你可能会问,为什么我们要这样做?这是一个非常重要的原因。假设您已经给它一个超出其物理极限的命令。如果是这种情况,那么舵机将继续尝试朝那个方向移动,不管发生什么。然而,由于物理限制,它将无法继续前进。一旦发生这种情况,然后在几秒钟内,您将看到蓝烟从舵机中冒出,表明它的损坏。问题在于,制造这种类型的错误非常容易,损失是非常明显的。因此,为了防止这种情况,我们迅速将其带回到中心位置,这样它就不会有任何烧毁的可能性。

现在,根据前面的代码,通过机器人对舵机 1-6 执行相同的操作。现在你知道发生了什么,是时候拿起笔和纸开始给舵机赋予角度值了。请记住,这段代码的最终目标是找出最大限制。因此,让我们从 90 度开始做起。在每一侧给它一个值,直到你能够接受的值。在纸上列出清单,因为我们将需要它用于下一段代码。

使机器人安全

在本章的前一部分中,通过我们的多次尝试,我们已经能够找到每个舵机的最大位置。现在是时候使用这些值了。在本章中,我们将为舵机编程其绝对最大值。在这个程序中,我们将确保舵机永远不需要超出两侧的定义参数。如果用户给出超出它的值,那么它将选择忽略用户输入,而不是造成自身损坏。

那么,让我们看看如何完成它。在程序的某些部分,数字值已经用粗体标出。这些是您需要用本章前面记录的值替换的值。例如,对于舵机 1,记录下的值是23170,作为每一侧的最大值。因此,代码的更改将从if a[0] < 160 and a[0] > 30变为ifa[0] < 170 and a[0] > 23。同样,对于每个舵机,必须遵循相同的程序:

import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setup(14,GPIO.OUT) GPIO.setup(16,GPIO.OUT) GPIO.setup(18,GPIO.OUT) GPIO.setup(20,GPIO.OUT) GPIO.setup(21,GPIO.OUT) GPIO.setup(22,GPIO.OUT)
  GPIO.setwarnings(False) pwm1 = GPIO.PWM(14, 50) pwm2 = GPIO.PWM(16, 50) pwm3 = GPIO.PWM(18, 50) pwm4 = GPIO.PWM(20, 50) pwm5 = GPIO.PWM(21, 50) pwm6 = GPIO.PWM(22, 50)
  pwm1.start(cvt_angle(90)) pwm2.start(cvt_angle(90)) pwm3.start(cvt_angle(90)) pwm4.start(cvt_angle(90)) pwm5.start(cvt_angle(90)) pwm6.start(cvt_angle(90))
def cvt_angle(angle):
    dc = float(angle/90) + 0.5
    return dc
while True:
    a = raw_input("enter a list of 6 values")
    if a[0] < 160 and  a[0] > 30:
        pwm1.ChangeDutyCycle(cvt_angle(a[0]))
    if a[1] < 160 and  a[1] > 30:  pwm2.ChangeDutyCycle(cvt)angle(a[1]))
    if a[0] < 160 and  a[0] > 30: pwm3.ChangeDutyCycle(cvt_angle(a[2]))    if a[0] < 160 and  a[0] > 30: pwm4.ChangeDutyCycle(cvt_angle(a[3]))    if a[0] < 160 and  a[0] > 30: pwm5.ChangeDutyCycle(cvt_angle(a[4]))    if a[0] < 160 and  a[0] > 30: pwm6.ChangeDutyCycle(cvt_angle(a[5]))}

现在,在这段代码中,我们做了一些非常基础的事情。您可以放心地说,我们所做的一切就是将ChangeDutyCycle()函数放在一个if语句中。这个if语句将决定舵机是移动还是保持在原位。对一些人来说,将这个程序放在一个特殊的部分似乎很天真。但是,请相信我,不是这样的。这个语句现在将作为以后每个程序的一部分。为了检查通过这个if语句传递给舵机的最终值,必须检查为舵机移动编写的所有代码;因此,对代码的基本可视化是非常必要的。

现在解释完毕,是时候给出不同的命令并查看它们是否在安全工作限制内工作了。

编写多个帧

在上一章中,我们已经学习了如何确保机器人在安全限制下工作的基础知识。在本章中,我们将看看如何使机器人能够在点击按钮的同时执行不同的活动,而不是逐个输入值。

为了做到这一点,我们需要了解一些高级运动概念。每当您观看任何视频或玩任何视频游戏时,您一定会遇到“每秒帧数”(FPS)这个术语。如果您还没有听说过这个术语,那么让我为您解释一下。现在制作的每个视频实际上都是由静止图像制成的。这些静止图像是由摄像机捕捉的,每秒点击 25-30 次。当这些图像以与它们被捕捉的速率相同的速率在屏幕上播放时,它形成了一个平滑的视频。

同样,在机器人中,我们也有帧的概念。然而,这些帧不是图像,而是机器人必须遵循的多个步骤。在一个简单的机器人程序中,可能只有两个帧,即初始帧和最终帧。这两个帧将对应于初始位置或最终位置。

然而,在现实世界中,这并不总是可能的,因为当机器人直接从初始位置到最终位置时,它会沿着特定的路径运动,并具有特定的曲率。然而,在这条路径上可能会有障碍物,或者这条路径可能不是所需的,因为需要遵循的路径可能是另一条。因此,我们需要帧。这些帧不仅定义了机器人从初始位置到最终位置的运动,而且将这两个位置之间的过渡分解为多个步骤,使机器人遵循所需的路径。

这可以被称为帧编程,在本章中我们将介绍。要记住的一件事是,帧数越多,机器人的运行就越平稳。你还记得我们看到的闭路电视录像吗?我们可以说它不够平滑,而且有很多抖动。这是由于闭路电视摄像头的低帧率造成的。它们不是以 30FPS 工作,而是以 15FPS 工作。这是为了减少视频的存储空间。然而,如果你看到最新的视频,有一些游戏和视频的帧率比正常的要高得多。我们最新的摄像头有 60FPS 的工作,使视频更加平滑和愉快。机器人也是如此。帧数越多,运动就越平滑和可控。但是,请确保不要过度使用。

现在,要从一个位置移动到另一个位置,我们将不得不在一开始就放入每个舵机的角度值。一旦获取,它将自动开始逐个执行这些值。为此,请继续编写以下代码:

import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setup(14,GPIO.OUT) GPIO.setup(16,GPIO.OUT) GPIO.setup(18,GPIO.OUT) GPIO.setup(20,GPIO.OUT) GPIO.setup(21,GPIO.OUT) GPIO.setup(22,GPIO.OUT)
  GPIO.setwarnings(False) pwm1 = GPIO.PWM(14, 50) pwm2 = GPIO.PWM(16, 50) pwm3 = GPIO.PWM(18, 50) pwm4 = GPIO.PWM(20, 50) pwm5 = GPIO.PWM(21, 50) pwm6 = GPIO.PWM(22, 50)
  pwm1.start(0) pwm2.start(0) pwm3.start(0) pwm4.start(0) pwm5.start(0) pwm6.start(0)
def cvt_angle(angle):
    dc = float(angle/90) + 0.5
    return dc
prev0 = 90
prev1 = 90
prev2 = 90
prev3 = 90
prev4 = 90
prev5 = 90 
while True:
    a = raw_input("enter a list of 6 values for motor 1")
    b = raw_input("enter a list of 6 values for motor 2")
    c = raw_input("enter a list of 6 values for motor 3")
    d = raw_input("enter a list of 6 values for motor 4")
    e = raw_input("enter a list of 6 values for motor 5")
    f = raw_input("enter a list of 6 values for motor 6")
    for i in range(6):
        if a[i] > 10 and a[i]< 180 :  
            pwm1.ChangeDutyCycle(cvt_angle(a[i]))
        if b[i] > 10 and b[i] < 180:
  pwm2.ChangeDutyCycle(cvt_angle(b[i]))
        if c[i] > 10 and c[i] < 180:
 pwm3.ChangeDutyCycle(cvt_angle(c[i]))
        if d[i] > 10 and d[i] < 180:
 pwm4.ChangeDutyCycle(cvt_angle(d[i]))
        if e[i] > 10 and e[i] < 180:
 pwm5.ChangeDutyCycle(cvt_angle(e[i]))
        if f[i] > 10 and f[i] < 180:
 pwm6.ChangeDutyCycle(cvt_angle(f[i])) 

在这个程序中,你可以看到我们复制了以前的程序并进行了一些非常小的改动。所以,让我们看看这些改动是什么:

a = raw_input("enter a list of 6 values for motor 1")
    b = raw_input("enter a list of 6 values for motor 2")
    c = raw_input("enter a list of 6 values for motor 3")
    d = raw_input("enter a list of 6 values for motor 4")
    e = raw_input("enter a list of 6 values for motor 5")
    f = raw_input("enter a list of 6 values for motor 6")

在这里,我们正在为每个舵机获取输入值并将其存储在不同的列表中。对于舵机 1,将使用列表a;类似地,对于舵机 2,将使用b,依此类推直到f。在代码的前面几行中,机器人将提示用户填写电机 1的六个帧值。然后,它将要求电机 2的六个值,以此类推直到电机 6

for i in range(6):

给舵机提供 PWM 的整个程序都集中在这个 for 循环中。这个循环将检查i的值并每次递增。i的值将从1开始,循环将运行并递增i的值直到达到6

if a[i] > 10 and a[i]< 180 :  
            pwm1.ChangeDutyCycle(cvt_angle(a[i]))

在程序的这一行中,列表中包含的值是基于1的值进行排序的。因此,第一次它将读取a[1]的值,这将对应于列表a[]的第一个值。这个值应该在安全工作范围内,因此使用if循环。如果在安全工作范围内,那么if条件中的程序将执行,否则不会执行。在if循环内,我们有一个简单的语句:pwm1.ChangeDutyCycle(cvt_angle(a[I]))。这将简单地取a[1]的值并将其转换为相应的 PWM 值,并将其提取到ChangeDutyCycle()函数中,这将改变舵机 1 的 PWM。

对于其余的舵机也制作了类似的程序,从舵机 1 到舵机 6。因此,所有这些都将逐一读取其对应列表中的值,并根据用户编程的方式改变舵机的角度。此外,随着循环的执行,i的值将增加,从而使程序读取列表中提取的不同值。列表中舵机的每个值将对应一个不同的帧,从而使机器人通过它。

所以继续玩一些有趣的东西,让你的机器人做一些很棒的动作。只要小心对待它!

Python 物联网入门指南(八)(3)https://developer.aliyun.com/article/1507344

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
1月前
|
程序员 UED Python
Python入门:3.Python的输入和输出格式化
在 Python 编程中,输入与输出是程序与用户交互的核心部分。而输出格式化更是对程序表达能力的极大增强,可以让结果以清晰、美观且易读的方式呈现给用户。本文将深入探讨 Python 的输入与输出操作,特别是如何使用格式化方法来提升代码质量和可读性。
Python入门:3.Python的输入和输出格式化
|
1月前
|
机器学习/深度学习 人工智能 算法框架/工具
Python入门:1.Python介绍
Python是一种功能强大、易于学习和运行的解释型高级语言。由**Guido van Rossum**于1991年创建,Python以其简洁、易读和十分工程化的设计而带来了庞大的用户群体和丰富的应用场景。这个语言在全球范围内都被认为是**创新和效率的重要工具**。
Python入门:1.Python介绍
|
3月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
3月前
|
机器学习/深度学习 数据可视化 数据挖掘
使用Python进行数据分析的入门指南
本文将引导读者了解如何使用Python进行数据分析,从安装必要的库到执行基础的数据操作和可视化。通过本文的学习,你将能够开始自己的数据分析之旅,并掌握如何利用Python来揭示数据背后的故事。
|
1月前
|
开发者 Python
Python入门:8.Python中的函数
### 引言 在编写程序时,函数是一种强大的工具。它们可以将代码逻辑模块化,减少重复代码的编写,并提高程序的可读性和可维护性。无论是初学者还是资深开发者,深入理解函数的使用和设计都是编写高质量代码的基础。本文将从基础概念开始,逐步讲解 Python 中的函数及其高级特性。
Python入门:8.Python中的函数
|
1月前
|
存储 索引 Python
Python入门:6.深入解析Python中的序列
在 Python 中,**序列**是一种有序的数据结构,广泛应用于数据存储、操作和处理。序列的一个显著特点是支持通过**索引**访问数据。常见的序列类型包括字符串(`str`)、列表(`list`)和元组(`tuple`)。这些序列各有特点,既可以存储简单的字符,也可以存储复杂的对象。 为了帮助初学者掌握 Python 中的序列操作,本文将围绕**字符串**、**列表**和**元组**这三种序列类型,详细介绍其定义、常用方法和具体示例。
Python入门:6.深入解析Python中的序列
|
1月前
|
缓存 算法 数据处理
Python入门:9.递归函数和高阶函数
在 Python 编程中,函数是核心组成部分之一。递归函数和高阶函数是 Python 中两个非常重要的特性。递归函数帮助我们以更直观的方式处理重复性问题,而高阶函数通过函数作为参数或返回值,为代码增添了极大的灵活性和优雅性。无论是实现复杂的算法还是处理数据流,这些工具都在开发者的工具箱中扮演着重要角色。本文将从概念入手,逐步带你掌握递归函数、匿名函数(lambda)以及高阶函数的核心要领和应用技巧。
Python入门:9.递归函数和高阶函数
|
1月前
|
存储 SQL 索引
Python入门:7.Pythond的内置容器
Python 提供了强大的内置容器(container)类型,用于存储和操作数据。容器是 Python 数据结构的核心部分,理解它们对于写出高效、可读的代码至关重要。在这篇博客中,我们将详细介绍 Python 的五种主要内置容器:字符串(str)、列表(list)、元组(tuple)、字典(dict)和集合(set)。
Python入门:7.Pythond的内置容器
|
1月前
|
存储 Linux iOS开发
Python入门:2.注释与变量的全面解析
在学习Python编程的过程中,注释和变量是必须掌握的两个基础概念。注释帮助我们理解代码的意图,而变量则是用于存储和操作数据的核心工具。熟练掌握这两者,不仅能提高代码的可读性和维护性,还能为后续学习复杂编程概念打下坚实的基础。
Python入门:2.注释与变量的全面解析
|
24天前
|
数据采集 人工智能 数据挖掘
Python 编程基础与实战:从入门到精通
本文介绍Python编程语言,涵盖基础语法、进阶特性及实战项目。从变量、数据类型、运算符、控制结构到函数、列表、字典等基础知识,再到列表推导式、生成器、装饰器和面向对象编程等高级特性,逐步深入。同时,通过简单计算器和Web爬虫两个实战项目,帮助读者掌握Python的应用技巧。最后,提供进一步学习资源,助你在Python编程领域不断进步。