Python 物联网入门指南(三)(1)

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

第六章:构建人脸检测器和人脸识别应用程序

本章介绍以下主题:

  • 人脸识别系统简介
  • 构建人脸检测器应用程序
  • 构建人脸识别应用程序
  • 人脸识别系统的应用

介绍

近年来,人脸识别已成为最热门的研究领域之一。人脸识别系统是一种具有检测和识别人脸能力的计算机程序。为了识别一个人,它考虑他们独特的面部特征。最近,它已被应用于多个安全和监控设施,以确保高风险区域、住宅区、私人和公共建筑等的安全。

构建人脸检测器应用程序

在本节中,我们讨论了如何从网络摄像头图像中检测人脸。需要将 USB 网络摄像头连接到树莓派 3 上,以实现实时人脸检测。

如何做…

  1. 导入必要的包:
import cv2 
import numpy as np 
  1. 加载人脸级联文件:
frontalface_cascade= cv2.CascadeClassifier('haarcascade_frontalface_alt.xml') 
  1. 检查人脸级联文件是否已加载:
if frontalface_cascade.empty(): 
  raiseIOError('Unable to load the face cascade classifier xml file') 
  1. 初始化视频捕获对象:
capture = cv2.VideoCapture(0) 
  1. 定义缩放因子:
scale_factor = 0.5 
  1. 直到按下Esc键为止执行操作:
# Loop until you hit the Esc key 
while True: 
  1. 捕获当前帧并调整大小:
ret, frame = capture.read() 
  frame = cv2.resize(frame, None, fx=scale_factor, fy=scale_factor,  
            interpolation=cv2.INTER_AREA) 
  1. 将图像帧转换为灰度:
gray_image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 
  1. 在灰度图像上运行人脸检测器:
face_rectangle = frontalface_cascade.detectMultiScale(gray_image, 1.3, 5)
  1. 绘制矩形框:
for (x,y,w,h) in face_rectangle: 
    cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 3) 
  1. 显示输出图像:
cv2.imshow('Face Detector', frame) 
  1. 检查是否按下了Esc键以终止操作:
a = cv2.waitKey(1) 
  if a == 10: 
    break 
  1. 停止视频捕获并终止操作:
capture.release() 
cv2.destroyAllWindows() 

人脸检测系统中获得的结果如下所示:


构建人脸识别应用程序

人脸识别是在人脸检测之后执行的一种技术。检测到的人脸与数据库中存储的图像进行比较。它从输入图像中提取特征并将其与数据库中存储的人脸特征进行匹配。

如何做…

  1. 导入必要的包:
import cv2 
import numpy as np   
from sklearn import preprocessing 
  1. 加载编码和解码任务运算符:
class LabelEncoding(object): 
  # Method to encode labels from words to numbers 
  def encoding_labels(self, label_wordings): 
    self.le = preprocessing.LabelEncoder() 
    self.le.fit(label_wordings) 
  1. 为输入标签实现从单词到数字的转换:
def word_to_number(self, label_wordings): 
    return int(self.le.transform([label_wordings])[0])
  1. 将输入标签从数字转换为单词:
def number_to_word(self, label_number): 
    return self.le.inverse_transform([label_number])[0] 
  1. 从输入路径提取图像和标签:
def getting_images_and_labels(path_input): 
  label_wordings = [] 
  1. 迭代输入路径的过程并附加文件:
for roots, dirs, files in os.walk(path_input): 
    for fname in (x for x in files if x.endswith('.jpg')): 
      fpath = os.path.join(roots, fname) 
      label_wordings.append(fpath.split('/')[-2])
  1. 初始化变量并解析输入寄存器:
images = [] 
  le = LabelEncoding() 
  le.encoding_labels(label_wordings) 
  labels = [] 
  # Parse the input directory 
  for roots, dirs, files in os.walk(path_input): 
    for fname in (x for x in files if x.endswith('.jpg')): 
      fpath = os.path.join(roots, fname) 
  1. 读取灰度图像:
img = cv2.imread(fpath, 0)  
  1. 提取标签:
names = fpath.split('/')[-2] 
  1. 执行人脸检测:
face = faceCascade.detectMultiScale(img, 1.1, 2, minSize=(100,100)) 
  1. 使用面部矩形迭代该过程:
for (x, y, w, h) in face: 
        images.append(img[y:y+h, x:x+w]) 
        labels.append(le.word_to_number(names)) 
  return images, labels, le 
if __name__=='__main__': 
  path_cascade = "haarcascade_frontalface_alt.xml" 
  train_img_path = 'faces_dataset/train' 
  path_img_test = 'faces_dataset/test' 
  1. 加载人脸级联文件:
faceCascade = cv2.CascadeClassifier(path_cascade) 
  1. 使用局部二值模式初始化人脸检测:
face_recognizer = cv2.createLBPHFaceRecognizer()
  1. 从训练人脸数据集中提取人脸特征:
imgs, labels, le = getting_images_and_labels(train_img_path) 
  1. 训练人脸检测系统:
print "nTraining..." 
  face_recognizer.train(imgs, np.array(labels)) 
  1. 测试人脸检测系统:
print 'nPerforming prediction on test images...' 
  flag_stop = False 
  for roots, dirs, files in os.walk(path_img_test): 
    for fname in (x for x in files if x.endswith('.jpg')): 
      fpath = os.path.join(roots, fname) 
  1. 验证人脸识别系统:
predicting_img = cv2.imread(fpath, 0) 
            # Detect faces 
      face = faceCascade.detectMultiScale(predicting_img, 1.1,  
                    2, minSize=(100,100)) 
            # Iterate through face rectangles 
      for (x, y, w, h) in face: 
        # Predict the output 
        index_predicted, config = face_recognizer.predict( 
predicting_img[y:y+h, x:x+w]) 
        # Convert to word label 
        person_predicted = le.number_to_word(index_predicted) 
        # Overlay text on the output image and display it 
        cv2.putText(predicting_img, 'Prediction: ' +  person_predicted,  
                        (10,60), cv2.FONT_HERSHEY_SIMPLEX, 2, (255,255,255), 6) 
        cv2.imshow("Recognizing face", predicting_img) 
      a = cv2.waitKey(0) 
      if a == 27: 
        flag = True 
        break 
    if flag_stop: 
      break 

这里显示了人脸识别的输出结果:


工作原理…

人脸识别系统广泛用于实现个人安全系统。读者可以参考文章基于 OpenCV 的人脸检测系统,网址为ieeexplore.ieee.org/document/6242980/

另请参阅用于实时人脸检测系统的人脸检测算法研究,网址为ieeexplore.ieee.org/document/5209668

另请参阅

请参考以下文章:

人脸识别系统的应用

人脸识别广泛应用于安全、医疗保健和营销领域。各行业正在利用深度学习开发新型人脸识别系统,用于识别欺诈、区分人脸和照片之间的差异等。在医疗保健领域,人脸识别结合其他计算机视觉算法用于检测面部皮肤疾病。

第七章:使用 Python 驱动硬件

在本章中,我们将涵盖以下主题:

  • 控制 LED
  • 响应按钮
  • 控制关机按钮
  • GPIO 键盘输入
  • 多路复用彩色 LED
  • 使用视觉持久性编写消息

介绍

树莓派计算机的一个关键特性是它能够直接与其他硬件进行接口。树莓派上的通用输入/输出(GPIO)引脚可以控制各种低级电子设备,从发光二极管(LED)到开关、传感器、电机、伺服和额外的显示器。

本章将重点介绍如何连接树莓派与一些简单的电路,并掌握使用 Python 来控制和响应连接的组件。

树莓派硬件接口由板子一侧的 40 个引脚组成。

GPIO 引脚及其布局将根据您拥有的特定型号略有不同。

树莓派 3、树莓派 2 和树莓派 B+都具有相同的 40 针布局。

树莓派 1 代老款(非 plus 型号)有一个 26 针的引脚,与新款模型的 1-26 针相同。

树莓派 2、树莓派 B+和树莓派 Plus GPIO 引脚(引脚功能)

连接器的布局如上图所示;引脚编号从 GPIO 引脚的引脚 1 开始。

引脚 1 位于最靠近 SD 卡的一端,如下图所示:

树莓派 GPIO 引脚位置

在使用 GPIO 引脚时应当小心,因为它还包括电源引脚(3V3 和 5V),以及地线(GND)引脚。所有的 GPIO 引脚都可以用作标准 GPIO,但其中一些还具有特殊功能;这些被标记并用不同颜色突出显示。

工程师通常使用 3V3 标记来指定原理图中的值,以避免使用可能被忽略的小数位(使用 33V 而不是 3.3V 会对电路造成严重损坏)。同样的方法也可以应用于其他组件的值,比如电阻,例如,1.2K 欧姆可以写成 1K2 欧姆。

TX 和 RX 引脚用于串行通信,借助电压级转换器,信息可以通过串行电缆传输到另一台计算机或设备。

我们还有 SDA 和 SCL 引脚,它们能够支持一种名为 I²C 的双线总线通信协议(树莓派 3 和 Plus 板上有两个 I²C 通道:通道 1 ARM,用于通用用途,通道 0 VC,通常用于识别 HAT 模块上连接的硬件)。还有 SPI MOSI、SPI MISO、SPI SCLK、SPI CE0 和 SPI CE1 引脚,支持另一种名为 SPI 的高速数据总线协议。最后,我们有 PWM0/1 引脚,允许生成脉冲宽度调制信号,对于伺服和生成模拟信号非常有用。

然而,在本章中,我们将专注于使用标准的 GPIO 功能。GPIO 引脚布局如下图所示:

树莓派 GPIO 引脚(GPIO.BOARD 和 GPIO.BCM)

树莓派 Rev 2(2014 年 7 月之前)与树莓派 2 GPIO 布局相比有以下不同:

  • 26 个 GPIO 引脚的引脚头(匹配前 26 个引脚)。
  • 引脚头旁边的另一组八个孔(P5)。详细信息如下:

树莓派 Rev 2 P5 GPIO 引脚

  • 原始的树莓派 Rev 1(2012 年 10 月之前)总共只有 26 个 GPIO 引脚(匹配当前树莓派的前 26 个引脚),除了以下细节:

树莓派 Rev 1 GPIO 引脚头的差异

RPi.GPIO库可以使用两种系统之一引用树莓派上的引脚。中间显示的数字是引脚的物理位置,也是在GPIO.BOARD模式下RPi.GPIO库引用的数字。外部的数字(GPIO.BCM)是处理器物理端口的实际引用数字,指示哪些引脚被连接(这就是为什么它们没有特定的顺序)。当模式设置为GPIO.BCM时使用它们,并且它们允许控制 GPIO 引脚以及连接到其他 GPIO 线的任何外围设备。这包括 BCM GPIO 4 上的附加摄像头上的 LED 和板上的状态 LED。但是,这也可能包括用于读/写 SD 卡的 GPIO 线,如果干扰会导致严重错误。

如果您使用其他编程语言访问 GPIO 引脚,编号方案可能会有所不同,因此如果您了解 BCM GPIO 引用,将会很有帮助,它们指的是处理器的物理 GPIO 端口。

请务必查看附录硬件和软件清单,其中列出了本章中使用的所有物品以及您可以从哪里获得它们。

控制 LED

硬件上的hello world等同于 LED 闪烁,这是一个很好的测试,可以确保一切正常工作,并且你已经正确地连接了它。为了让它更有趣,我建议使用红色、蓝色和绿色(RGB)LED,但如果你只有单独的 LED 也可以。

准备工作

你将需要以下设备:

  • 4 x 杜邦母对公补丁线
  • 迷你面包板(170 个连接点)或更大的面包板
  • RGB LED(共阴)/3 个标准 LED(最好是红色、绿色和蓝色)
  • 面包板线(实心线)
  • 3 x 470 欧姆电阻

前面提到的每个组件成本都不会太高,并且可以在其他项目中重复使用。面包板是一个特别有用的物品,可以让你在不需要焊接的情况下尝试自己的电路:

RGB LED、标准 LED 和 RGB 电路的图表

以下图表显示了面包板电路:

连接到 GPIO 引脚的 RGB LED/标准 LED 的接线图有几种不同类型的 RGB LED 可用,因此请检查您组件的数据表以确认引脚顺序和类型。有些是 RGB 的,所以确保你按照相应的方式连接引脚,或者在代码中调整RGB_引脚设置。你也可以获得共阳极变种,这将需要阳极连接到 3V3(GPIO 引脚 1)才能点亮(它们还需要将RGB_ENABLERGB_DISABLE设置为01)。

本书的面包板和组件图是使用一个名为Fritzingwww.fritzing.org)的免费工具创建的;它非常适合规划您自己的树莓派项目。

如何做…

  1. 创建ledtest.py脚本如下:
#!/usr/bin/python3 
#ledtest.py 
import time 
import RPi.GPIO as GPIO 
# RGB LED module 
#HARDWARE SETUP 
# GPIO 
# 2[======XRG=B==]26[=======]40 
# 1[=============]25[=======]39 
# X=GND R=Red G=Green B=Blue  
#Setup Active States 
#Common Cathode RGB-LED (Cathode=Active Low) 
RGB_ENABLE = 1; RGB_DISABLE = 0 
#LED CONFIG - Set GPIO Ports 
RGB_RED = 16; RGB_GREEN = 18; RGB_BLUE = 22 
RGB = [RGB_RED,RGB_GREEN,RGB_BLUE] 
def led_setup(): 
  #Setup the wiring 
  GPIO.setmode(GPIO.BOARD) 
  #Setup Ports 
  for val in RGB: 
    GPIO.setup(val,GPIO.OUT) 
def main(): 
  led_setup() 
  for val in RGB: 
    GPIO.output(val,RGB_ENABLE) 
    print("LED ON") 
    time.sleep(5) 
    GPIO.output(val,RGB_DISABLE) 
    print("LED OFF") 
try: 
  main() 
finally: 
  GPIO.cleanup() 
  print("Closed Everything. END") 
#End
  1. RPi.GPIO库将需要sudo权限来访问 GPIO 引脚硬件,因此您需要使用以下命令运行脚本:
sudo python3 ledtest.py  

运行脚本时,您应该看到 LED 的红色、绿色和蓝色部分(或者如果您使用单独的 LED,则分别点亮)。如果没有,请仔细检查您的接线或确认 LED 是否正常工作,方法是暂时将红色、绿色或蓝色线连接到 3V3 引脚(GPIO 引脚 1)。

大多数与硬件相关的脚本都需要sudo命令,因为用户通常不会直接在这么低的层次上控制硬件。例如,设置或清除作为 SD 卡控制器一部分的控制引脚可能会损坏正在写入的数据。因此,出于安全目的,需要超级用户权限,以防止程序意外(或恶意)使用硬件。

工作原理…

要使用 Python 访问 GPIO 引脚,我们导入RPi.GPIO库,该库允许通过模块函数直接控制引脚。我们还需要time模块来暂停程序一定数量的秒。

然后,我们为 LED 的接线和激活状态定义值(请参阅本食谱的有更多…部分中的控制 GPIO 电流段)。

在程序使用 GPIO 引脚之前,我们需要通过指定编号方法(GPIO.BOARD)和方向(GPIO.OUTGPIO.IN)来设置它们(在这种情况下,我们将所有 RGB 引脚设置为输出)。如果引脚配置为输出,我们将能够设置引脚状态;同样,如果它配置为输入,我们将能够读取引脚状态。

接下来,我们使用GPIO.ouput()来控制引脚,指定 GPIO 引脚的编号和我们希望它处于的状态(1 = 高/开启,0 = 低/关闭)。我们打开每个 LED,等待五秒,然后关闭它。

最后,我们使用GPIO.cleanup()将 GPIO 引脚恢复到它们的原始默认状态,并释放对引脚的控制,以供其他程序使用。

有更多…

在树莓派上使用 GPIO 引脚必须小心,因为这些引脚直接连接到树莓派的主处理器,没有额外的保护。必须小心使用,因为任何错误的接线可能会损坏树莓派处理器,并导致其完全停止工作。

或者,您可以使用许多直接插入 GPIO 引脚排针的模块之一(减少接线错误的机会):

例如,Pi-Stop 是一个简单的预制 LED 板,模拟了一组交通信号灯,旨在成为那些对控制硬件感兴趣但又想避免损坏树莓派的人的一个过渡阶段。掌握了基础知识后,它也是一个出色的指示器,有助于调试。

只需确保您在ledtest.py脚本中更新LED CONFIG引脚引用,以引用您使用的硬件的引脚布局和位置。


请参阅附录中的硬件和软件清单,了解树莓派硬件零售商的清单。

控制 GPIO 电流

每个 GPIO 引脚在烧毁之前只能处理一定电流(单个引脚最大 16mA,总共 30mA),同样,RGB LED 的电流应限制在 100mA 以下。通过在 LED 之前或之后添加电阻,我们将能够限制通过 LED 的电流并控制其亮度(更大的电流将使 LED 更亮)。

由于我们可能希望同时点亮多个 LED,因此我们通常会尽量将电流设置得尽可能低,同时仍然提供足够的功率点亮 LED。

我们可以使用欧姆定律来告诉我们需要多少电阻来提供特定的电流。该定律如下图所示:

欧姆定律:电路中电流、电阻和电压之间的关系

我们将以最小电流(3mA)和最大电流(16mA)为目标,同时仍然从每个 LED 产生相当明亮的光。为了获得 RGB LED 的平衡输出,我测试了不同的电阻,直到它们提供了接近白光(通过卡片查看)。每个 LED 选择了 470 欧姆的电阻(您的 LED 可能略有不同):

需要电阻器来限制通过 LED 的电流

电阻器上的电压等于 GPIO 电压(Vgpio = 3.3V)减去特定 LED 的电压降(Vfwd);然后我们可以使用这个电阻来计算每个 LED 使用的电流,如下面的公式所示:

我们可以计算每个 LED 的电流

响应按钮

许多使用树莓派的应用程序要求在不需要连接键盘和屏幕的情况下激活操作。 GPIO 引脚为树莓派提供了一种优秀的方式,使其可以通过您自己的按钮和开关进行控制,而无需鼠标/键盘和屏幕。

准备工作

您将需要以下设备:

  • 2 x DuPont 母对公跳线
  • 迷你面包板(170 个连接点)或更大的面包板
  • 按钮开关(瞬时闭合)或导线连接以打开/关闭电路
  • 面包板导线(实心线)
  • 1K 欧姆电阻器

开关如下图所示:

按钮开关和其他类型的开关以下示例中使用的开关是单极,单刀SPST),瞬时闭合,按钮开关。单极SP)意味着有一组使连接的触点。在这里使用的按钮开关的情况下,每侧的腿与中间的单极开关连接在一起。双极DP)开关的作用就像单极开关,只是两侧在电上是分开的,允许您同时打开/关闭两个独立的组件。

单刀ST)意味着开关将仅在一个位置进行连接;另一侧将保持开放。双刀DT)意味着开关的两个位置将连接到不同的部分。

瞬时闭合意味着按下按钮时将关闭开关,并在释放时自动打开。锁定按钮开关将保持关闭状态,直到再次按下。

尝试使用树莓派的扬声器或耳机

按钮电路的布局

在此示例中,我们将使用声音,因此您还需要将扬声器或耳机连接到树莓派的音频插孔。

您需要使用以下命令安装名为flite的程序,这将让我们让树莓派说话:

sudo apt-get install flite  

安装后,您可以使用以下命令进行测试:

sudo flite -t "hello I can talk"  

如果太安静(或太吵),您可以使用以下命令调整音量(0-100%):

amixer set PCM 100%  

如何做…

创建btntest.py脚本如下:

#!/usr/bin/python3 
#btntest.py 
import time 
import os 
import RPi.GPIO as GPIO 
#HARDWARE SETUP 
# GPIO 
# 2[==X==1=======]26[=======]40 
# 1[=============]25[=======]39 
#Button Config 
BTN = 12 
def gpio_setup(): 
  #Setup the wiring 
  GPIO.setmode(GPIO.BOARD) 
  #Setup Ports 
  GPIO.setup(BTN,GPIO.IN,pull_up_down=GPIO.PUD_UP) 
def main(): 
  gpio_setup() 
  count=0 
  btn_closed = True 
  while True: 
    btn_val = GPIO.input(BTN) 
    if btn_val and btn_closed: 
       print("OPEN") 
       btn_closed=False 
    elif btn_val==False and btn_closed==False: 
       count+=1 
       print("CLOSE %s" % count) 
       os.system("flite -t '%s'" % count) 
       btn_closed=True 
    time.sleep(0.1) 
try: 
  main() 
finally: 
  GPIO.cleanup() 
  print("Closed Everything. END") 
#End 

它是如何工作的…

与上一个示例一样,我们根据需要设置 GPIO 引脚,但这次是作为输入,并且还启用了内部上拉电阻器(有关更多信息,请参阅本示例的更多内容…部分中的上拉和下拉电阻器电路)使用以下代码:

GPIO.setup(BTN,GPIO.IN,pull_up_down=GPIO.PUD_UP) 

在设置了 GPIO 引脚之后,我们创建一个循环,将不断检查BTN的状态,使用GPIO.input()。如果返回的值为false,则表示通过开关将引脚连接到 0V(地),我们将使用flite每次按下按钮时为我们大声计数。

由于我们在try/finally条件中调用了主函数,即使我们使用Ctrl + Z关闭程序,它仍将调用GPIO.cleanup()

我们在循环中使用短延迟;这可以确保忽略开关上的接触产生的任何噪音。这是因为当我们按下按钮时,按下或释放时并不总是完美接触,如果我们再次按下它,可能会产生多个触发。这被称为软件去抖动;我们在这里忽略了信号中的弹跳。

更多内容…

树莓派 GPIO 引脚必须小心使用;用于输入的电压应该是

在特定范围内,并且从中抽取的任何电流应该最小化使用

保护电阻。

安全电压

我们必须确保只连接在 0(地)和 3V3 之间的输入。一些处理器使用 0V 到 5V 之间的电压,因此需要额外的组件才能安全地与它们接口。除非确定安全,否则永远不要连接使用 5V 的输入或组件,否则会损坏树莓派的 GPIO 端口。

上拉和下拉电阻电路

先前的代码设置了 GPIO 引脚使用内部上拉电阻。如果 GPIO 引脚上没有上拉电阻(或下拉电阻),电压可以在 3V3 和 0V 之间自由浮动,实际逻辑状态保持不确定(有时为 1,有时为 0)。

树莓派的内部上拉电阻为 50K 欧姆至 65K 欧姆,下拉电阻为 50K 欧姆至 65K 欧姆。外部上拉/下拉电阻通常用于 GPIO 电路(如下图所示),通常使用 10K 欧姆或更大的电阻出于类似的原因(当它们不活动时提供非常小的电流吸收)。

上拉电阻允许通过 GPIO 引脚流动少量电流,并且在开关未按下时提供高电压。当按下开关时,小电流被流向 0V 的大电流所取代,因此我们在 GPIO 引脚上得到低电压。开关在按下时为活动低电平和逻辑 0。它的工作原理如下图所示:

上拉电阻电路

下拉电阻的工作方式相同,只是开关为活动高电平(按下时 GPIO 引脚为逻辑 1)。它的工作原理如下图所示:

下拉电阻电路

保护电阻

除了开关外,电路还包括与开关串联的电阻,以保护 GPIO 引脚,如下图所示:

GPIO 保护限流电阻

保护电阻的目的是保护 GPIO 引脚,如果它被意外设置为输出而不是输入。例如,假设我们的开关连接在 GPIO 和地之间。现在 GPIO 引脚被设置为输出并打开(驱动到 3V3),一旦我们按下开关,没有电阻的情况下,GPIO 引脚将直接连接到 0V。 GPIO 仍然会尝试将其驱动到 3V3;这将导致 GPIO 引脚烧毁(因为它将使用太多电流来驱动引脚到高状态)。如果我们在这里使用 1K 欧姆电阻,引脚可以使用可接受的电流驱动高(I = V/R = 3.3/1K = 3.3 毫安)。

受控关机按钮

树莓派应该始终正确关机,以避免 SD 卡损坏(在对卡进行写操作时断电)。如果您没有连接键盘或屏幕(可能正在运行自动化程序或通过网络远程控制),这可能会造成问题,因为您无法输入命令或查看您正在做什么。通过添加我们自己的按钮和 LED 指示灯,我们可以轻松地命令关机和重启,然后再次启动以指示系统处于活动状态。

准备工作

您将需要以下设备:

  • 3 x DuPont 母对公跳线
  • 迷你面包板(170 个连接点)或更大的面包板
  • 按钮开关(瞬时闭合)
  • 通用 LED
  • 2 x 470 欧姆电阻
  • 面包板导线(实心)

关机电路的整个布局将如下图所示:

受控关机电路布局

如何操作…

  1. 创建shtdwn.py脚本如下:
#!/usr/bin/python3 
#shtdwn.py 
import time 
import RPi.GPIO as GPIO 
import os 
# Shutdown Script 
DEBUG=True #Simulate Only 
SNDON=True 
#HARDWARE SETUP 
# GPIO 
# 2[==X==L=======]26[=======]40 
# 1[===1=========]25[=======]39 
#BTN CONFIG - Set GPIO Ports 
GPIO_MODE=GPIO.BOARD 
SHTDWN_BTN = 7 #1 
LED = 12       #L 
def gpio_setup(): 
  #Setup the wiring 
  GPIO.setmode(GPIO_MODE) 
  #Setup Ports 
  GPIO.setup(SHTDWN_BTN,GPIO.IN,pull_up_down=GPIO.PUD_UP) 
  GPIO.setup(LED,GPIO.OUT) 
def doShutdown(): 
  if(DEBUG):print("Press detected") 
  time.sleep(3) 
  if GPIO.input(SHTDWN_BTN): 
    if(DEBUG):print("Ignore the shutdown (<3sec)") 
  else: 
    if(DEBUG):print ("Would shutdown the RPi Now") 
    GPIO.output(LED,0) 
    time.sleep(0.5) 
    GPIO.output(LED,1) 
    if(SNDON):os.system("flite -t 'Warning commencing power down 3 2 1'") 
    if(DEBUG==False):os.system("sudo shutdown -h now") 
    if(DEBUG):GPIO.cleanup() 
    if(DEBUG):exit() 
def main(): 
  gpio_setup() 
  GPIO.output(LED,1) 
  while True: 
    if(DEBUG):print("Waiting for >3sec button press") 
    if GPIO.input(SHTDWN_BTN)==False: 
       doShutdown() 
    time.sleep(1) 
try: 
  main() 
finally: 
  GPIO.cleanup() 
  print("Closed Everything. END") 
#End
  1. 要使这个脚本自动运行(一旦我们测试过它),我们可以将脚本放在~/bin中(如果只想复制它,可以使用cp而不是mv),并使用以下代码将其添加到crontab中:
mkdir ~/bin 
mv shtdwn.py ~/bin/shtdwn.py  
crontab -e 
  1. 在文件末尾,我们添加以下代码:
@reboot sudo python3 ~/bin/shtdwn.py 

Python 物联网入门指南(三)(2)https://developer.aliyun.com/article/1507200

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
6天前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
14天前
|
Python
【python从入门到精通】-- 第五战:函数大总结
【python从入门到精通】-- 第五战:函数大总结
47 0
|
2天前
|
数据采集 机器学习/深度学习 人工智能
Python编程入门:从基础到实战
【10月更文挑战第24天】本文将带你进入Python的世界,从最基础的语法开始,逐步深入到实际的项目应用。我们将一起探索Python的强大功能和灵活性,无论你是编程新手还是有经验的开发者,都能在这篇文章中找到有价值的内容。让我们一起开启Python的奇妙之旅吧!
|
4天前
|
数据采集 存储 数据库
Python中实现简单爬虫的入门指南
【10月更文挑战第22天】本文将带你进入Python爬虫的世界,从基础概念到实战操作,一步步指导你如何使用Python编写一个简单的网络爬虫。我们将不展示代码示例,而是通过详细的步骤描述和逻辑讲解,帮助你理解爬虫的工作原理和开发过程。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你打开一扇通往数据收集新世界的大门。
|
2天前
|
测试技术 开发者 Python
探索Python中的装饰器:从入门到实践
【10月更文挑战第24天】 在Python的世界里,装饰器是一个既神秘又强大的工具。它们就像是程序的“隐形斗篷”,能在不改变原有代码结构的情况下,增加新的功能。本篇文章将带你走进装饰器的世界,从基础概念出发,通过实际例子,逐步深入到装饰器的高级应用,让你的代码更加优雅和高效。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往高效编程的大门。
|
4天前
|
存储 人工智能 数据挖掘
Python编程入门:构建你的第一个程序
【10月更文挑战第22天】编程,这个听起来高深莫测的词汇,实际上就像搭积木一样简单有趣。本文将带你走进Python的世界,用最浅显的语言和实例,让你轻松掌握编写第一个Python程序的方法。无论你是编程新手还是希望了解Python的爱好者,这篇文章都将是你的理想起点。让我们一起开始这段奇妙的编程之旅吧!
12 3
|
3天前
|
机器学习/深度学习 人工智能 算法
机器学习基础:使用Python和Scikit-learn入门
机器学习基础:使用Python和Scikit-learn入门
9 1
|
5天前
|
存储 程序员 开发者
Python编程入门:从零开始掌握基础语法
【10月更文挑战第21天】本文将带你走进Python的世界,通过浅显易懂的语言和实例,让你快速了解并掌握Python的基础语法。无论你是编程新手还是想学习一门新的编程语言,这篇文章都将是你的不二之选。我们将一起探索变量、数据类型、运算符、控制结构、函数等基本概念,并通过实际代码示例加深理解。准备好了吗?让我们开始吧!
|
9天前
|
存储 算法 Python
【10月更文挑战第16天】「Mac上学Python 27」小学奥数篇13 - 动态规划入门
本篇将通过 Python 和 Cangjie 双语介绍动态规划的基本概念,并解决一个经典问题:斐波那契数列。学生将学习如何使用动态规划优化递归计算,并掌握编程中的重要算法思想。
68 3
|
11天前
|
设计模式 开发者 Python
Python编程中的设计模式:从入门到精通####
【10月更文挑战第14天】 本文旨在为Python开发者提供一个关于设计模式的全面指南,通过深入浅出的方式解析常见的设计模式,帮助读者在实际项目中灵活运用这些模式以提升代码质量和可维护性。文章首先概述了设计模式的基本概念和重要性,接着逐一介绍了几种常用的设计模式,并通过具体的Python代码示例展示了它们的实际应用。无论您是Python初学者还是经验丰富的开发者,都能从本文中获得有价值的见解和实用的技巧。 ####