树莓派3B及传感器测试实验

树莓派3B介绍

树莓派3B和树莓派4B参数比较

型号

Raspberry Pi 4B

Raspberry Pi 3B

CPU

1.5GHz,Quad-Core Broadcom

BCM2711(Cortex A-72)

1.2GHz,Quad-Core Broadcom

BCM2837 (Cortex A-53)

RAM

1GB/2GB/4GB LPDDR4(取决于型号)

1G LPDDR2

GPU

500 MHZ Broadcom VideoCore VI

250MHZ Broadcom VideoCrore IV

无线

802.11.b/g/n/ac(2.4/5GHz) 1.2Gbps

Bluetooth 5.0

802.11.b/g/n(2.4/5GHz) 150Mbps

Bluetooth 4.1

以太网

Gigabit Ethernet

10/100 Ethernet

USB

2个 USB 2.0 / 2个 USB 3.0

USB Type-c

4 个 USB 2.0

Micro USB

GPIO

40个GPIO引脚

40个GPIO引脚

最大分辨率

2 x micro-HDMI ports, up to 4Kp60 supported

1920x1080

电源

5V,3A DC

5V,2.5A DC

树莓派引脚对照表

TdoList:上图是树莓派2B的引脚图,目前看画的最好,找到个人官网,但发现已经关闭。后续看能不能找到树莓派3B和4B的引脚图。更详细引脚说明参考​​Raspberry Pi GPIO Pinout​​。仅有GPIO.1(物理引脚12)支持 PWM_OUTPUT 模式,仅有GPIO.7(物理引脚 7)支持 CLOCK 输出模式。

特性

I2C

UART

SPI

数据线数目

两根线:SDA(串行数据)和SCL(串行时钟)

两根线:TXD(发送)和RXD(接收)

四根线:MOSI(主机输出从机输入)、MISO(主机输入从机输出)、SCLK(时钟)、SS(片选)

传输速率

最高可达3.4 Mbps

通常情况下速率较低

速率高,可达数十Mbps

通信方式

同步通信

异步通信

同步通信

设备地址

7位或10位设备地址

不需要地址

不需要地址

线长限制

通常不超过1米

通常不超过15米

通常不超过3米

多主机支持

支持多主机

不支持多主机

支持多主机

硬件成本

硬件成本低,只需要两个IO口

硬件成本低,只需要两个IO口

硬件成本较高,需要4个或更多IO口

适用场景

短距离通信

适用于点对点通信和低速数据传输

高速数据传输

常见应用

I/O扩展器、EEPROM、温度传感器等

终端设备、调试设备等

存储器、显示屏、WiFi模块等

树莓派固定IP配置

sudo nano /etc/dhcpcd.conf

因此要改静态IP就要更改/etc/dhcpcd.conf文件。

在此文件后面添加

设置有线配置可以改成eth0(网卡用ifconfig来查询)

最后在shell中输入命令

sudo reboot now

修改软件更新源

sudo nano /etc/apt/sources.list

清华大学软件源stretch版本:

deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ bullseye main non-free contrib rpi
deb-src http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ bullseye main non-free contrib rpi

树莓派实验前期准备

接线准备

面包板

T型扩展板

彩虹排线(一般情况,彩虹线红色为电源线,黑色为地线。)

三者接线图如下(理论上T型板电源引脚与开发板电源对应。本次购买T型板,标红凸起朝向开发板,不要反接)

网络准备

把树莓派接入公司网络,物理网口连接。配置一个无人使用的静态IP。

打开浏览器,输入公司网页登录IP;打开浏览器开发者模式,选择网络-》保留日志

找到login.php,复制-》复制为cURL(bash);

找到有自己用户名的登陆脚本,例如查找"xuwt",找到类似这段的登陆脚本:

curl 'http://10.0.6.106/ac_portal/login.php' \
  -H 'Accept: */*' \
  -H 'Accept-Language: zh' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
  -H 'Cookie: Sessionid=731386501-1' \
  -H 'Origin: http://10.0.6.106' \
  -H 'Referer: http://10.0.6.106/ac_portal/20200703125620/pc.html?template=20200703125620&tabs=pwd&vlanid=0&_ID_=0&switch_url=&url=http://10.0.6.106/homepage/index.html&controller_type=&mac=08-c0-21-04-9a-cb' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67' \
  -H 'X-Requested-With: XMLHttpRequest' \
  --data-raw 'opr=pwdLogin&userName=xuwt&pwd=dea07317bd6e11b9e0&auth_tag=1689129415144&rememberPwd=1' \
  --compressed \
  --insecure
  
  curl 'http://10.0.6.106/ac_portal/login.php' \
  -H 'Accept: */*' \
  -H 'Accept-Language: zh-CN,zh;q=0.9' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
  -H 'Origin: http://10.0.6.106' \
  -H 'Referer: http://10.0.6.106/ac_portal/20200703125620/pc.html?template=20200703125620&tabs=pwd&vlanid=0&_ID_=0&switch_url=&url=http://10.0.6.106/homepage/index.html&controller_type=&mac=08-c0-21-04-9a-cb' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36' \
  -H 'X-Requested-With: XMLHttpRequest' \
  --data-raw 'opr=pwdLogin&userName=xuwt&pwd=510dbf5267f2d5bcafa047&auth_tag=1691130767238&rememberPwd=0' \
  --compressed \
  --insecure

编写一个启动脚本,需要联网时启动。或者把脚本路径写入到rc.local文件,实现树莓派启动后接入网络。有时可能联网失败,手动执行下脚本即可。

交叉编译准备:

参考​​【NFV落地】入网测试Kube5gNfvo总结​​

传感器实验测试

在树莓派基础实验中,主要利用的是​​wiringPi​​​库或者​​bcm2835​​库。

wiringPi库:

​​Raspberry Pi | Wiring | Download & Install | Wiring Pi​​

​​WiringPi / WiringPi 镜像库​​ 32位库

https://github.com/guation/WiringPi-arm64 64位库

目前网站已经不更新,但是参考文档较多。

WiringPi includes a software-driven PWM handler capable of outputting a PWM signal on any of the Raspberry Pi’s GPIO pins.(WiringPi包括一个软件驱动的PWM处理器,能够在Raspberry Pi的任何GPIO引脚上输出PWM信号。)

而wiringPi一般用于C++等平台

#include "wiringPi.h"
wiringPiSetup();

安装完wiringPi库后,输入​​gpio readall​​可以查看树莓派详细引脚信息。

相关库函数:

硬件初始化函数原型

函数返回值

函数说明

int wiringPiSetup (void)

返回:执行状态,-1表示失败

当使用这个函数初始化树莓派引脚时,程序使用的是wiringPi 引脚编号表。引脚的编号为 0~16需要root权限

int wiringPiSetupGpio (void)

返回:执行状态,-1表示失败

当使用这个函数初始化树莓派引脚时,程序中使用的是BCM GPIO 引脚编号表。需要root权限

wiringPiSetupPhys(void)

不常用,不做介绍

/

wiringPiSetupSys (void) ;

不常用,不做介绍

/

通用GPIO控制函数原型

函数参数

函数说明

void pinMode (int pin, int mode)

pin:配置的引脚mode:指定引脚的IO模式可取的值:INPUT、OUTPUT、PWM_OUTPUT,GPIO_CLOCK

作用:配置引脚的IO模式注:只有wiringPi 引脚编号下的1脚(BCM下的18脚) 支持PWM输出;只有wiringPi编号下的7(BCM下的4号)支持GPIO_CLOCK输出

void digitalWrite (int pin, int value)

pin:控制的引脚value:引脚输出的电平值。可取的值:HIGH,LOW分别代表高低电平

让对一个已经配置为输出模式的引脚,输出指定的电平信号

int digitalRead (int pin)

pin:读取的引脚返回:引脚上的电平,可以是LOW HIGH 之一

读取一个引脚的电平值 LOW HIGH ,返回

void analogWrite(int pin, int value)

pin:引脚

value:输出的模拟量

value - 占空比:0(始终断)到255(始终导通)之间。

模拟量输出。树莓派的引脚本身是不支持AD转换的,也就是不能使用模拟量的API,需要增加另外的模块

int analogRead (int pin)

pin:引脚返回:引脚上读取的模拟量

模拟量输入树莓派的引脚本身是不支持AD转换的,也就是不能使用模拟量的API,需要增加另外的模块

void pwmWrite (int pin, int value)

pin:引脚value:写入到PWM寄存器的值,范围在0~1024之间

输出一个值到PWM寄存器,控制PWM输出。pin只能是wiringPi 引脚编号下的1脚(BCM下的18脚)

void pullUpDnControl (int pin, int pud)

pin:引脚pud:拉电阻模式可取的值:PUD_OFF 不启用任何拉电阻。关闭拉电阻PUD_DOWN 启用下拉电阻,引脚电平拉到GNDPUD_UP 启用上拉电阻,引脚电平拉到3.3v

对一个设置IO模式为 INPUT 的输入引脚设置拉电阻模式。与Arduino不同的是,树莓派支持的拉电阻模式更丰富。树莓派内部的拉电阻达50K欧姆

软件模拟PWM函数原型

函数参数

函数说明

int softPwmCreate (int pin, int initialValue, int pwmRange)

pin:用来作为软件PWM输出的引脚initalValue:引脚输出的初始值pwmRange:PWM值的范围上限1-100建议100。返回值:0表示成功。

使用一个指定的pin引脚创建一个模拟的PWM输出引脚

其他IO口

void softPwmWrite (int pin, int value)

pin:通过softPwmCreate创建的引脚value:PWM引脚输出的值

更新引脚输出的PWM值

bcm2835库:

​​bcm2835: C library for Broadcom BCM 2835 as used in Raspberry Pi​​

bcm2835库更加简洁,它只有两个源文件bcm2835.c和bcm2835.h。在使用过程中我们可以选择将其安装到树莓派中来使用,也可以选择直接将两个文件包含到我们的应用代码中。

BCM编码一般都在python库中使用:

import RPi.GPIO as GPIO  //引入RPi.GPIO库
GPIO.setmode(GPIO.BCM) //设置引脚编号为BCM编码方式;

实验分类:

  • 高低电平:双色LED灯、有源蜂鸣器、开关电源
  • PWM:LED(RGB 255,255,255)灯、电机控制、无源蜂鸣器
  • 触发事件(数字):按键开关、继电器、光遮断模块、金属触摸
  • 触发事件(模拟):声音检测模块、麦克风声音模块、光敏电阻
  • 摄像头 :摄像、人脸识别(视频)、远程登陆查看摄像头

实验1:3mm红绿双色LED模块

树莓派

双色LED

GPIO 1

R(中间)

GND

GND

GPIO 2

G(S)

模块上面标-号的接地,中间的接物理引脚12(wiringPi编码1),第三个接物理引脚13(wiringPi编码2)。

使用WiringPi库代码示例:

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define Led_PinRed    1 // 红色LED 管脚
#define Led_PinGreen  2 // 绿色LED 管脚

// LED 初始化
void raspberry_led_Init(void)
{
    pinMode(Led_PinRed, OUTPUT);
    pinMode(Led_PinGreen, OUTPUT);
}

int main(void)
{
    //初始化连接失败时,将消息打印到屏幕
    if(wiringPiSetup() == -1){ 
        printf("setup wiringPi failed !");
         return -1; 
    }
    raspberry_led_Init(); // LED 初始化

    for(int i=0;i<5;i++)
    {
        printf("gpio out: %d\n", i);
        digitalWrite(Led_PinRed, HIGH);   //digital是数字,analog是模拟;
        delay(1000);
        digitalWrite(Led_PinRed, LOW);    
        delay(1000);
        digitalWrite(Led_PinGreen, HIGH);
        delay(1000);
        digitalWrite(Led_PinGreen, LOW);
   }
   return 0;
}
#include <wiringPi.h>
#include <softPwm.h>
#include <stdio.h>

#define uchar unsigned char

#define Led_PinRed    1 // 红色LED 管脚
#define Led_PinGreen  2 // 绿色LED 管脚

// LED 初始化
void makerobo_led_Init(void)
{
    softPwmCreate(Led_PinRed,  0, 100);
    softPwmCreate(Led_PinGreen, 0, 100);
}

int main()
{
    //初始化连接失败时,将消息打印到屏幕
    if(wiringPiSetup() == -1){ 
        printf("setup wiringPi failed !");
        return 1; 
    }
    makerobo_led_Init(); // LED 初始化

    for(int i=0;i<5;i++)
    {
        printf("gpio out: %d\n", i);
        softPwmWrite(Led_PinRed, 100);    
        delay(1000);
        softPwmWrite(Led_PinRed, 0);    
        delay(1000);
        softPwmWrite(Led_PinGreen, 100);
        delay(1000);
        softPwmWrite(Led_PinGreen, 0);
    }
    return 0;
}

编译参数:

gcc -Wall -o 1_mm_led 1_mm_led.c -lwiringPi  //-Wall 是为了使能所有警告,以便发现程序中的问题

或者使用树莓派本地工具Geany打开后,选择"Build"->"Set Build Commands",编译和生成添加"-lwiringPi":

之后就可以选择图像界面进行编译和执行:

python代码接线方式:

树莓派

双色LED

GPIO 18

R

GND

GND

GPIO 27

B

使用bcm2835库测试示例:

import RPi.GPIO as GPIO
import time

# 设置GPIO模式为BCM
GPIO.setmode(GPIO.BCM)

# 定义LED所连接的GPIO引脚号
led_pinRed = 18
led_pinBlue = 27

# 设置GPIO引脚为输出模式
GPIO.setup(led_pinRed, GPIO.OUT)
GPIO.setup(led_pinBlue, GPIO.OUT)

# 控制LED灯的开关状态
def toggle_led(state):
    GPIO.output(led_pinRed, state)

def toggle_ledblue(state):
    GPIO.output(led_pinBlue, state)

# 测试LED灯
try:
    while True:
        toggle_led(GPIO.HIGH)  #
        toggle_ledblue(GPIO.LOW)
        time.sleep(1)  # 延时1秒

        toggle_led(GPIO.LOW)  # 关闭LED灯
        toggle_ledblue(GPIO.HIGH)
        time.sleep(1)  # 延时1秒

except KeyboardInterrupt:
    pass


GPIO.cleanup()

红绿灯切换示意图:

实验2:5mm红绿双色LED模块

代码同上实验1,测试图如下:

实验3:3色LED模块(RGB)模块

模块上面标-号的接地,R接物理引脚11(wiringPi编码0),G接接物理引脚12(wiringPi编码1),B接接物理引脚13(wiringPi编码2)。

树莓派

双色LED

GPIO 17

R

GND

GND

GPIO 18

G

GPIO 27

B

#!/usr/bin/env python   #告诉Linux本文件是一个Python程序
import RPi.GPIO as GPIO  # 导入控制GPIO的模块,RPi.GPIO
import time  # 导入时间模块,提供延时、时钟和其它时间函数

colors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF]  # 颜色列表
R = 17  # 定义物理针脚号
G = 18
B = 27


def setup(Rpin, Gpin, Bpin):
    global pins  # 在函数内部声明被其修饰的变量是全局变量
    global p_R, p_G, p_B
    pins = {'pin_R': Rpin, 'pin_G': Gpin, 'pin_B': Bpin}
    GPIO.setmode(GPIO.BCM)  # 设置引脚编号模式为板载模式,即树莓派上的物理位置编号
    for i in pins:
        GPIO.setup(pins[i], GPIO.OUT)  # 设置针脚模式为输出(或者输入GPIO.IN)
        GPIO.output(pins[i], GPIO.LOW)  # Set pins to low(0 V) to off led
    p_R = GPIO.PWM(pins['pin_R'], 2000)  # set Frequece to 2KHz
    p_G = GPIO.PWM(pins['pin_G'], 1999)
    p_B = GPIO.PWM(pins['pin_B'], 5000)
    p_R.start(0)
    p_G.start(0)
    p_B.start(0)


def ledmap(x, in_min, in_max, out_min, out_max):  # 将颜色的刺激量转换为占空比对应的值。
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min


def off():
    for i in pins:
        GPIO.output(pins[i], GPIO.LOW)  # Turn off all leds


def setColor(col):  # For example : col = 0x112233
    R_val = (col & 0xff0000) >> 16  # 先“与”运算只保留自己颜色所在位的值有效
    G_val = (col & 0x00ff00) >> 8  # 再“右移”运算将自己颜色所在位的值提取出来
    B_val = (col & 0x0000ff) >> 0

    R_val = ledmap(R_val, 0, 255, 0, 100)  # 将颜色的刺激量转换为占空比对应的值
    G_val = ledmap(G_val, 0, 255, 0, 100)
    B_val = ledmap(B_val, 0, 255, 0, 100)

    p_R.ChangeDutyCycle(R_val)  # 更改占空比,调整该颜色的亮度
    p_G.ChangeDutyCycle(G_val)
    p_B.ChangeDutyCycle(B_val)

def loop():
    while True:
        for col in colors:
            setColor(col)
            time.sleep(1)

def destroy():
    p_R.stop()  # Turn off PWM
    p_G.stop()
    p_B.stop()
    off()  # Turn off all leds
    GPIO.cleanup()  # 重置GPIO状态

if __name__ == "__main__":
    try:
        setup(R, G, B)  # 调用初始化设置LED灯的函数
        loop()  # 调用循环函数
    except KeyboardInterrupt:  # 如果遇用户中断(control+C),则执行destroy()函数
        destroy()  # 调用清除LED状态的函数

实验4:摄像头模块

  1. 安装OpenCV库

首先需要安装OpenCV库。您可以使用pip3命令在终端中安装OpenCV库:

pip3 install opencv-python
  1. 测试摄像头打开实验:
import cv2

cap=cv2.VideoCapture(0)
i=0
while(1):
    ret ,frame = cap.read()
    k=cv2.waitKey(1)
    if k==27:           #按下ESC退出窗口
        break
    elif k==ord('s'):   #按下s保存图片
        cv2.imwrite('./'+str(i)+'.jpg',frame)
        i+=1
    cv2.imshow("capture", frame)
cap.release()

  1. 基于OpenCV的摄像头人脸识别实验,下载Haar Cascade分类器

Haar Cascade分类器是OpenCV中用于检测人脸的预训练模型。可以从OpenCV官方GitHub存储库中下载分类器文件。在终端中,输入以下命令下载分类器:

wget https://github.com/opencv/opencv/raw/master/data/haarcascades/haarcascade_frontalface_default.xml

​​haarcascade_frontalface_default.xml​​

  1. 编写Python脚本来打开摄像头并进行人脸检测。以下是一个示例脚本:
import cv2

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)

    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)

    cv2.imshow('frame', frame)

    if cv2.waitKey(1) == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

实验5:模拟温度模块

import RPi.GPIO as GPIO
import time

lm35_pin = 18

GPIO.setmode(GPIO.BCM)  # 以BCM编码格式
GPIO.setup(lm35_pin, GPIO.IN)


def read_temperature():
    # 读取模拟输入引脚的电压值
    voltage = GPIO.input(lm35_pin)

    # 转换为摄氏温度值
    temperature = (voltage * 3.3) / 1024 * 100

    return temperature


def main():
    print("Raspberry Pi Temperature test program\n")
    time.sleep(1)  # 通电后前一秒状态不稳定,时延一秒
    while True:
        temperature = read_temperature()
        print('Temperature: {0:.2f}°C'.format(temperature))
        time.sleep(1)


def destroy():
    GPIO.cleanup()


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()

不确定是否硬件问题,输出温度一直为0(后期有万用表再进行测试)。

实验6:DS18B20温度传感器

   温度传感器DS18B20是一款常用的数字温度传感器,具有体积小,硬件成本低,抗干扰能力强,精度高的特点。数字温度传感器易于连接,采用1线总线,可直接输出温度数据

树莓派

T型转接板

温度传感器模块

GPIO4

GPIO4

OUT

5V

5V

VCC

GND

GND

GND

1、编辑/boot/config.text文件。在文件底部添加一行:dtoverlay=w1-gpio。

/boot/config.text文件

2、重启树莓派系统。

sudo reboot

3、安装设备驱动程序并确认设备是否有效。

sudo modprobe w1-gpio
sudo modprobe w1-therm
cd /sys/bus/w1/devices/
ls

4、查看设备数据,检查当前温度。

pi@raspberrypi:/sys/bus/w1/devices $ cd cd 28-20320c34abca
pi@raspberrypi:/sys/bus/w1/devices/cd 28-20320c34abca $ ls
driver  hwmon  id  name  power  subsystem  uevent  w1_slave
pi@raspberrypi:/sys/bus/w1/devices/cd 28-20320c34abca $ cat w1_slave 
a7 01 55 aa 7f ff 09 10 53 : crc=53 YES
a7 01 55 aa 7f ff 09 10 53 t=26437

  字符段“t=26437”中的数字就是当前温度值。如果要将其转换为摄氏度,也可以除以1000,即当前温度为26437÷1000=26.437°C。

#include <OneWire.h>
 
 
OneWire  ds(10);  // 连接arduino10引脚
 
void setup(void) {
  Serial.begin(9600);
}
 
void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
   
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
   
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }
 
  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
  
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 
 
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end
   
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
   
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
 
  Serial.print("  Data = ");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();
 
  // convert the data to actual temperature
 
  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");   
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
}

实验7:温湿度传感器模块

DHT11用的是单总线协议,一次传送40位的数据。 注意了,看到这一句话,也就是说我们每次读取DHT11的数据时,都要一次性读取40次,也就是读取40位。并且数据前16位是与湿度相关的,中间16位是与温度相关的,最后八位是用来校验的,当我们校验成功后,证明这一次的温湿度结果正确的,树莓派就可以使用这个温湿度值;如果校验不通过,那么就代表我们这次读取出来的温湿度值,是错误的(也许是我们的时序错误了,也许是传感器的问题),我们不进行采样。

DHT11的总体通信流程: 第一步:主机(树莓派)先发送开始信号,从机(DHT11)会返回一个相应信号进行应答。 第二步:主机信号线拉高准备接收数据。 第三步:开始接收数据(一次接收40位)。

接线方式如下:

DHT Pin

Signal

Pi Pin

1

3.3V

1

2

Data/Out

GPIO17

3

Ground

GND

import RPi.GPIO as GPIO
import numpy as np
import time

dhtpin = 17

GPIO.setmode(GPIO.BCM)  # 以BCM编码格式


def read_dht11_dat():
    GPIO.setup(dhtpin, GPIO.OUT)
    GPIO.output(dhtpin, GPIO.LOW)
    # 给信号提示传感器开始工作,并保持低电平18ms以上
    time.sleep(0.02)  # 这里保持20ms
    GPIO.output(dhtpin, GPIO.HIGH)  # 然后输出高电平

    GPIO.setup(dhtpin, GPIO.IN)
    # 发送完开始信号后得把输出模式换成输入模式,不然信号线上电平始终被拉高

    while GPIO.input(dhtpin) == GPIO.LOW:
        continue
    # DHT11发出应答信号,输出 80 微秒的低电平

    while GPIO.input(dhtpin) == GPIO.HIGH:
        continue
    # 紧接着输出 80 微秒的高电平通知外设准备接收数据

    # 开始接收数据
    j = 0  # 计数器
    data = []  # 收到的二进制数据
    kk = []  # 存放每次高电平结束后的k值的列表
    while j < 40:
        k = 0
        while GPIO.input(dhtpin) == GPIO.LOW:  # 先是 50 微秒的低电平
            continue

        while GPIO.input(dhtpin) == GPIO.HIGH:  # 接着是26-28微秒的高电平,或者 70 微秒的高电平
            k += 1
            if k > 100:
                break
        kk.append(k)
        if k < 8:  # 26-28 微秒时高电平时通常k等于5或6
            data.append(0)  # 在数据列表后面添加一位新的二进制数据“0”
        else:  # 70 微秒时高电平时通常k等于17或18
            data.append(1)  # 在数据列表后面添加一位新的二进制数据“1”

        j += 1

    print("sensor is working.")
    print("初始数据高低电平:%s,参数k的列表内容:%s\n" % (data, kk))

    m = np.logspace(7, 0, 8, base=2, dtype=int)  # logspace()函数用于创建一个于等比数列的数组
    # 即[128 64 32 16 8 4 2 1],8位二进制数各位的权值
    data_array = np.array(data)  # 将data列表转换为数组

    # dot()函数对于两个一维的数组,计算的是这两个数组对应下标元素的乘积和(数学上称之为内积)
    humidity = m.dot(data_array[0:8])  # 用前8位二进制数据计算湿度的十进制值
    humidity_point = m.dot(data_array[8:16])
    temperature = m.dot(data_array[16:24])
    temperature_point = m.dot(data_array[24:32])
    check = m.dot(data_array[32:40])

    print(humidity, humidity_point, temperature, temperature_point, check)

    tmp = humidity + humidity_point + temperature + temperature_point
    # 十进制的数据相加

    if check == tmp:  # 数据校验,相等则输出
        return humidity, temperature
    else:  # 错误输出错误信息
        return False


def main():
    print("Raspberry Pi DHT11 Temperature test program\n")
    time.sleep(1)  # 通电后前一秒状态不稳定,时延一秒
    while True:
        result = read_dht11_dat()
        if result:
            humidity, temperature = result
            print("humidity: %s %%,  Temperature: %s  ℃\n" % (humidity, temperature))
            time.sleep(1)

        if result == False:
            print("Data are wrong,skip\n")
            time.sleep(1)


def destroy():
    GPIO.cleanup()


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()

实验8:麦克风声音模块

树莓派

T型转接板

PCF8591模块

*

*

AO

GND

GND

G

5V

5V

+

GPIO4

GPIO4

DO

import RPi.GPIO as GPIO
import time

microphone_pin = 4

GPIO.setmode(GPIO.BCM)  # 以BCM编码格式
GPIO.setup(microphone_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)


def read_voice():
    # 读取模拟输入引脚的电压值
    voltage = GPIO.input(microphone_pin)
    return voltage


def main():
    print("Raspberry Pi microphone test program\n")
    time.sleep(1)  # 通电后前一秒状态不稳定,时延一秒
    while True:
        voice = read_voice()
        print('microphone voice: {0:.2f}'.format(voice))
        time.sleep(1)


def destroy():
    GPIO.cleanup()


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()

麦克风左侧灯常亮,传感器可能异常,可变电阻器被击穿,调节无效。

实验9:激光传感器

树莓派

激光传感器模块

GIPO17

SIG(S)

*

*

GND

GND

#!/usr/bin/env python
#   DO NOT WATCH THE LASER DIRECTLY IN THE EYE!

import RPi.GPIO as GPIO
import time
LedPin = 17

def setup():
    GPIO.setmode(GPIO.BCM)       # Numbers GPIOs by physical location
    GPIO.setup(LedPin, GPIO.OUT)   # Set LedPin's mode is output
    GPIO.output(LedPin, GPIO.LOW) # Set LedPin LOW(0V) to off led

def loop():
    while True:
        print('...Laser off')
        GPIO.output(LedPin, GPIO.LOW)  # led off
        time.sleep(0.5)
        print('Laser on...')
        GPIO.output(LedPin, GPIO.HIGH) # led on
        time.sleep(0.5)

def destroy():
    GPIO.output(LedPin, GPIO.LOW)    # led off
    GPIO.cleanup()                     # Release resource

if __name__ == '__main__':     # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验10:按键开关模块

Python代码说明:

树莓派

T型转接板

轻触开关

GPIO 17

GPIO 17

S

3.3V

3.3V

VCC(中间触点)

GND

GND

GND

树莓派

T型转接板

双色LED

GPIO 12

GPIO 12

R(红色端口)

GND

GND

GND

GPIO 13

GPIO 13

G(绿色端口)

若按键没有按下则信号是高电平,GPIO.input(BtnPin)的值为1,即LED(x)中的x==1,红灯亮,打印显示“Button is up !”;   按下键后信号是低电平,GPIO.input(BtnPin)的值为0,即LED(x)中的x==0,绿灯亮,打印显示“Button is down !”。

#!/usr/bin/env python
import RPi.GPIO as GPIO

BtnPin = 17
Rpin = 12
Gpin = 13


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(Gpin, GPIO.OUT)  # Set Green Led Pin mode to output
    GPIO.setup(Rpin, GPIO.OUT)  # Set Red Led Pin mode to output
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)


def Led(x):  # 控制双色LED灯闪烁的函数
    if x == 0:
        GPIO.output(Rpin, 1)  # 红灯亮
        GPIO.output(Gpin, 0)  # 绿灯灭
    if x == 1:
        GPIO.output(Rpin, 0)  # 红灯灭
        GPIO.output(Gpin, 1)  # 绿灯亮


def Print(x):  # 打印按键是否按下的提示消息
    if x == 0:
        print('    *   Button is down!   *')
    elif x == 1:
        print('    *   Button is up !   *')


def detect(chn):
    Led(GPIO.input(BtnPin))  # 控制双色LED灯闪烁
    Print(GPIO.input(BtnPin))  # 打印按键是否按下的提示消息


def loop():
    while True:
        pass  # pass 不做任何事情,一般用做占位语句。


def destroy():
    GPIO.output(Gpin, GPIO.LOW)  # Green led off
    GPIO.output(Rpin, GPIO.LOW)  # Red led off
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验11:Arduino 继电器

树莓派

T型转接板

继电器模块

GPIO 4

GPIO 4

SIG(IN)

5V

5V

VCC(DC+)

GND

GND

GND(DC-)

5V

5V

COM

双色LED模块

T型转接板

继电器模块

R

*

常开(NO)

GND

GND

*

G

*

常闭(NC)

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

RelayPin = 4


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(RelayPin, GPIO.OUT)
    GPIO.output(RelayPin, GPIO.LOW)


def loop():
    while True:
        print('...relay on')
        GPIO.output(RelayPin, GPIO.LOW)  # 低电平时,继电器为初始状态
        time.sleep(1)  # 常闭触点通电,绿灯亮
        print('relay off...')
        GPIO.output(RelayPin, GPIO.HIGH)  # 高电平时,继电器为激活状态
        time.sleep(1)  # 常开触点通电,红灯亮


def destroy():
    GPIO.output(RelayPin, GPIO.LOW)
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

测试灯将在红绿之间切换:

实验12:水银开关

树莓派

T型转接板

磁簧开关

GPIO 17

GPIO 17

SIG

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
BtnPin = 17


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)


def Print(x):  # 打印是否有打开开关
    if x == 0:
        print('    *  Light!  *')
    elif x == 1:
        print('    *  No light! *')


def detect(chn):
    Print(GPIO.input(BtnPin))  # 验证GPIO.input(ReedPin)的值


def loop():
    while True:
        pass


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验13:磁簧开关模块

磁簧开关(Reed Switch)是一个通过所施加的磁场操作的电开关。基本型式是将两片磁簧片密封在玻璃管内,两片虽重叠,但中间间隔有一小空隙。当外来磁场时将使两片磁簧片接触,进而导通。 一旦磁体被拉到远离开关,磁簧开关将返回到其原来的位置。可以用来计数或限制位置。

树莓派

T型转接板

磁簧开关

GPIO 17

GPIO 17

SIG(DO)

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
BtnPin = 17


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)


def Print(x):  # 打印检测到磁性物质
    if x == 0:
        print('    *  Detected Magnetic Material!  *')
    elif x == 1:
        print('    *  Nothing  happened! *')


def detect(chn):
    Print(GPIO.input(BtnPin))  # 验证GPIO.input(ReedPin)的值


def loop():
    while True:
        pass  # pass 不做任何事情,一般用做占位语句。


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验14:光敏电阻

光敏电阻随着光强的变化而改变其电阻,光敏电阻阻值随光强变化,光线越强,阻值越小。

树莓派

T型转接板

干簧管传感器

GPIO 17

GPIO 17

SIG(DO)

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
BtnPin = 17


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)


def Print(x):  # 打印是否有光照
    if x == 0:
        print('    *  Detected Magnetic Material!  *')
    elif x == 1:
        print('    *  Nothing  happened! *')


def detect(chn):
    Print(GPIO.input(BtnPin))  # 验证GPIO.input(ReedPin)的值


def loop():
    while True:
        pass  


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验15:光遮断模块

接线、代码同14:光敏电阻。遮断操作如下:

实验16:红外避障传感器

树莓派

T型转接板

红外避障传感器

GPIO17

GPIO17

OUT(SIG)

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time
ObstaclePin = 17


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(ObstaclePin, GPIO.IN, pull_up_down=GPIO.PUD_UP)


def loop():
    while True:
        if 0 == GPIO.input(ObstaclePin):  # 当检测到障碍物时,输出低电平信号
            print("Detected Barrier!")
        else:
            print("****Nothing!******")


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验17:红外发射接收模块

一般情况下,发射和接收模块使用2块开发板进行测试,目前使用1块开发板可以验证该功能,后续深入了解可再进行优化。

发射模块:

树莓派

T型转接板

红外发射

GPIO 17

GPIO 17

S

GPIO 18

GPIO 18

中间(未使用)

GND

GND

GND

import RPi.GPIO as GPIO
import time

led_pin = 17

GPIO.setmode(GPIO.BCM)  # 以BCM编码格式
GPIO.setup(led_pin, GPIO.OUT)


# 控制LED灯的开关状态
def toggle_led(state):
    GPIO.output(led_pin, state)


def main():
    print("Raspberry Pi IR LED test program\n")
    time.sleep(1)  # 通电后前一秒状态不稳定,时延一秒
    while True:
        toggle_led(GPIO.HIGH)  #
        print('Set GPIO.HIGH')
        time.sleep(1)  # 延时1秒
        toggle_led(GPIO.LOW)  # 关闭LED灯
        print('Set GPIO.LOW')
        time.sleep(1)  # 延时1秒


def destroy():
    GPIO.cleanup()


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()

接收模块:

树莓派

T型转接板

红外接收

GPIO 12

GPIO 12

S

5V

5V

VCC中间

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
BtnPin = 12


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)


def Print(x):  # 打印是否有光照
    if x == 0:
        print('    *  Receive!  *')
    elif x == 1:
        print('    *  No Receive! *')


def detect(chn):
    Print(GPIO.input(BtnPin))  # 验证GPIO.input(ReedPin)的值


def loop():
    print('    *  Start  IR Receive!  *')
    while True:
        pass


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

当接收到信号时,接收模块会红灯闪烁。

实验18:火焰模块

没有火。接线、代码同13:光敏电阻。

树莓派

T型转接板

火焰模块

GPIO 17

GPIO 17

SIG(DO)

3.3V

3.3V

VCC

GND

GND

GND

实验19:霍尔磁力传感器模块

树莓派

T型转接板

霍尔传感器

GPIO 17

GPIO 17

SIG(DO)

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
BtnPin = 17


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)


def Print(x):  # 打印检测到磁性物质
    if x == 0:
        print('    *  Detected Magnetic Material!  *')
    elif x == 1:
        print('    *  Nothing  happened! *')


def detect(chn):
    Print(GPIO.input(BtnPin))  # 验证GPIO.input(ReedPin)的值


def loop():
    print(' Start Hall Sensor! ')
    while True:
        pass


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验20:金属触摸传感器

树莓派

T型转接板

PCF8591模块

*

*

AO

GND

GND

G

5V

5V

+

GPIO4

GPIO4

DO

代码处理类似声音判断。

import RPi.GPIO as GPIO
import time

microphone_pin = 4

GPIO.setmode(GPIO.BCM)  # 以BCM编码格式
GPIO.setup(microphone_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def read_voice():
    # 读取模拟输入引脚的电压值
    voltage = GPIO.input(microphone_pin)
    return voltage

def main():
    print("Raspberry Pi microphone test program\n")
    time.sleep(1)  # 通电后前一秒状态不稳定,时延一秒
    while True:
        voice = read_voice()
        print('touch test: {0:.2f}'.format(voice))
        time.sleep(1)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()

触摸后左侧灯亮,且收到输入信号。

实验21:魔术光杯模块

树莓派

T型转接板 (BCM)

旋转编码器模块

GPIO17

GPIO17

S

GPIO18

GPIO18

L

3.3V

3.3V

VCC(+)

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
BtnPin = 17
LedPin = 18

def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)
    GPIO.setup(LedPin, GPIO.OUT)  # 设置针脚模式为输出(或者输入GPIO.IN)
    GPIO.output(LedPin, GPIO.LOW)


def Print(x):  # 水银传感器震动后,灯亮
    if x == 0:
        print('    *  Light!  *')
        GPIO.output(LedPin, GPIO.HIGH)
    elif x == 1:
        print('    *  No light! *')
        GPIO.output(LedPin, GPIO.LOW)

def detect(chn):
    Print(GPIO.input(BtnPin))  # 验证GPIO.input(ReedPin)的值


def loop():
    while True:
        pass


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验22:敲击传感器

树莓派

T型转接板

振动开关

GPIO 17

GPIO 17

SIG

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

BtnPin = 17
tmp = 0


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input


def Print(x):  # 打印是否有震动变化,只打印变化情况
    global tmp
    if x != tmp:
        if x == 0:
            print('*  Shake On!  *')
        elif x == 1:
            print('*  Shake Off! *')
        tmp = x


def loop():
    while True:
        state = GPIO.input(BtnPin)
        if state != 1:   # 每当振动产生时
            print("state:%d\n" % state)
            Print(state)
            time.sleep(1)
        else:
            Print(state)

def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    print('*  Shake Code Start!  *')
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验23:倾斜开关

树莓派

T型转接板

振动开关

GPIO 17

GPIO 17

SIG

3.3V

3.3V

VCC

GND

GND

GND

实验代码与敲击传感器相同;

实验24:手指侦测心跳模块

树莓派

T型转接板

振动开关

GPIO 17

GPIO 17

SIG

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

BtnPin = 17
tmp = 0


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input


def Print(x):  # 打印是否有心跳变化,只打印变化情况
    global tmp
    if x != tmp:
        if x == 0:
            print('*  Off!  *')
        elif x == 1:
            print('*  On! *')
        tmp = x


def loop():
    while True:
        state = GPIO.input(BtnPin)
        if state == 1:
            print("state:%d\n" % state)
            Print(state)
            time.sleep(1)
        else:
            Print(state)

def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    print('* Heartbeat check start!  *')
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验25:双轴XY摇杆

树莓派

T型转接板

双轴XY摇杆

GPIO 17

GPIO 17

VRx

GPIO 18

GPIO 18

VRy

GPIO 27

GPIO 27

SW

5V

5V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
BtnPinX = 17
BtnPinY = 18
BtnPinPress = 27


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPinX, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.add_event_detect(BtnPinX, GPIO.BOTH, callback=directionX, bouncetime=200)
    GPIO.setup(BtnPinY, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.add_event_detect(BtnPinY, GPIO.BOTH, callback=directionY, bouncetime=200)
    GPIO.setup(BtnPinPress, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.add_event_detect(BtnPinPress, GPIO.BOTH, callback=directionPress, bouncetime=200)


def directionX(chx):  # 获取X轴操纵杆方向结果
    statex = GPIO.input(BtnPinX)
    print("x state :%d" % statex)

def directionY(chy):  # 获取Y轴操纵杆方向结果
    statey = GPIO.input(BtnPinY)
    print("y state :%d" % statey)

def directionPress(chp):  # 获取操纵杆按下结果
    statepress = GPIO.input(BtnPinPress)
    print("Press state :%d" % statepress)

def loop():
    print('    *  Start Rocker Sensor!  *')
    while True:
        pass


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验26:有源蜂鸣器

  • 有源蜂鸣器常用于发出单一的提示性报警声音,没有频率变化,内置振荡器;

有源蜂鸣器内部有一个简单的振荡电路,能将恒定的直流电转化成一定频率的脉冲信号,程序控制方便但频率固定,单片机一个高低电平就可以让其发出声音。

  • 无源蜂鸣器的驱动方式为频率脉冲驱动,可以发出各种有频率的信号声音;

无源蜂鸣器和电磁扬声器一样没有内部驱动电路,需要接在音频输出电路中才能发声。如果给直流信号是不响的,因为磁路恒定,必须用2K-5K的方波去驱动它。

树莓派

T型转接板

有源蜂鸣器

GPIO 17

GPIO 17

SIG

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

BuzzerPin = 17  # pin11

def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BuzzerPin, GPIO.OUT)
    GPIO.output(BuzzerPin, GPIO.HIGH)

def on():
    GPIO.output(BuzzerPin, GPIO.LOW)
    # 低电平是响

def off():
    GPIO.output(BuzzerPin, GPIO.HIGH)
    # 高电平是停止响

def beep(x):  # 响3秒后停止3秒
    print("buzzer start")
    on()
    time.sleep(x)
    off()
    time.sleep(x)

def loop():
    print("loop start")
    while True:
        beep(3)

def destroy():
    GPIO.output(BuzzerPin, GPIO.HIGH)
    GPIO.cleanup()  # Release resource

if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验27:无源蜂鸣器

树莓派

T型转接板

无源蜂鸣器

GPIO 17

GPIO 17

SIG

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

Buzzer = 17

CL = [0, 131, 147, 165, 175, 196, 211, 248]

CM = [0, 262, 294, 330, 350, 393, 441, 495]

CH = [0, 525, 589, 661, 700, 786, 882, 990]

song_0 = [CL[1], CL[2], CL[3], CL[4], CL[5], CL[6], CL[7],
          CM[1], CM[2], CM[3], CM[4], CM[5], CM[6], CM[7],
          CH[1], CH[2], CH[3], CH[4], CH[5], CH[6], CH[7]]
# song_0表示从低音do依次到高音si的音符列表

beat_0 = [2, 2, 2, 2, 2, 2, 2,
          2, 2, 2, 2, 2, 2, 2,
          2, 2, 2, 2, 2, 2, 2]


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(Buzzer, GPIO.OUT)  # Set pins' mode is output
    global Buzz  # Assign a global variable to replace GPIO.PWM
    Buzz = GPIO.PWM(Buzzer, 440)  # 440 is initial frequency.
    Buzz.start(50)  # Start Buzzer pin with 50% duty ration


def loop():
    while True:
        # --------------------------------------------
        print('\n\n    Playing Low C notes...')
        for i in range(0, 7):  # Play song 0的C调低音音符
            Buzz.ChangeFrequency(song_0[i])
            # 根据歌曲的音符改变频率
            time.sleep(beat_0[i] * 0.5)
            # 根据节拍列表每个音符延迟1秒,2 beats*0.5s=1s

        print('\n\n    Playing Middle C notes...')
        for i in range(7, 14):  # Play song 0
            Buzz.ChangeFrequency(song_0[i])  # Change the frequency along the song note
            time.sleep(beat_0[i] * 0.5)  # delay a note for beat * 0.5s

        print('\n\n    Playing High C notes...')
        for i in range(14, 21):  # Play song 0
            Buzz.ChangeFrequency(song_0[i])  # Change the frequency along the song note
            time.sleep(beat_0[i] * 0.5)  # delay a note for beat * 0.5s
        Buzz.ChangeFrequency(0.5)  # 一首曲子结束,间隔3秒
        time.sleep(3)

def destory():
    Buzz.stop()  # Stop the buzzer
    GPIO.output(Buzzer, 1)  # Set Buzzer pin to High
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destory()

实验28:旋转编码器模块

树莓派

T型转接板 (BCM)

旋转编码器模块

GPIO0

GPIO17

CLK

GPIO1

GPIO18

DT

GPIO2

GPIO27

SW

3V

3V

VCC(+)

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

RoAPin = 17  # CLK Pin
RoBPin = 18  # DT Pin
BtnPin = 27  # Button Pin

globalCounter = 0

flag = 0
Last_RoB_Status = 0
Current_RoB_Status = 0


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(RoAPin, GPIO.IN)  # input mode
    GPIO.setup(RoBPin, GPIO.IN)
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)


def rotarydeal():
    global flag
    global Last_RoB_Status
    global Current_RoB_Status
    global globalCounter
    Last_RoB_Status = GPIO.input(RoBPin)
    while not GPIO.input(RoAPin):  # 未旋转时,GPIO.input(RoAPin)值为1,旋转时会变为0
        Current_RoB_Status = GPIO.input(RoBPin)  # 旋转时的当前值
        flag = 1
    if flag == 1:
        flag = 0
        if (Last_RoB_Status == 1) and (Current_RoB_Status == 0):
            globalCounter = globalCounter + 1  # 顺时针旋转,角位移增大
        if (Last_RoB_Status == 0) and (Current_RoB_Status == 1):
            globalCounter = globalCounter - 1  # 逆时针旋转,数值减小


def btnisr(channel):
    global globalCounter
    globalCounter = 0


def loop():
    global globalCounter
    tmp = 0  # Rotary Temporary

    GPIO.add_event_detect(BtnPin, GPIO.FALLING, callback=btnisr)
    # 当按下按钮时,调用回调函数btnISR
    while True:
        rotarydeal()
        if tmp != globalCounter:
            print("globalCounter = %d\n" % globalCounter)
            tmp = globalCounter


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验29:循迹模块

树莓派

T型转接板

无源蜂鸣器

GPIO 17

GPIO 17

SIG

3.3V

3.3V

VCC

GND

GND

GND

#!/usr/bin/env python
import RPi.GPIO as GPIO
BtnPin = 17


def setup():
    GPIO.setmode(GPIO.BCM)  # Numbers GPIOs by physical location
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(BtnPin, GPIO.BOTH, callback=detect, bouncetime=200)


def Print(x):  # 打印检测黑线或白线
    if x == 0:
        print('    *  black line!  *')
    elif x == 1:
        print('    *  white line! *')


def detect(chn):
    Print(GPIO.input(BtnPin))  # 验证GPIO.input(ReedPin)的值


def loop():
    while True:
        pass


def destroy():
    GPIO.cleanup()  # Release resource


if __name__ == '__main__':  # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

实验30:在 Raspberry Pi 上运行 TensorFlow Lite 对象检测模型

​​- 如何在 Raspberry Pi 上设置和运行 TensorFlow Lite 对象检测模型​​

遗留问题

  1. 32bit和64bit之间如何切换?

【答】OS的不同,重新烧录系统

  1. 树莓派的内存怎么看?

在芯片上可以看,应该是被散热片挡住了。

  1. 树莓派上有ntp吗?

可以搭建ntp服务器。

树莓派服务端:

timedatectl set-timezone Asia/Shanghai
apt-get install ntp
systemctl start  ntp

客户端:

timedatectl set-timezone Asia/Shanghai
apt-get install ntpdate
ntpdate ntp.server.ip      #ntp服务器ip地址

vim /etc/crontab             #设置客户端定时更新
30 10 * * * root /usr/sbin/ntpdate ntp.server.ip   #表示每天10:30自动执行ntpdate指令,与NTP服务器时间同步
crontab -e 立即生效
  1. http网页登陆查看摄像头,出现摄像头打开失败情况。
  2. 疑问:对softPwmWrite函数的参数设置都是大于100的,而且如果想混色,是需要遵循标准RGB表进行设置。如红色设置为(255,0,0),超过100就是没用的?猜测精度是否不够?

参考资料:

​​Raspberry Pi | Wiring | Download & Install | Wiring Pi​​

​​树莓派wiringPi库详解​​

​​Raspberry Pi | Wiring | Download & Install | Wiring Pi​​

​​WiringPi / WiringPi 镜像库​​ 32位库

https://github.com/guation/WiringPi-arm64 64位库

​​bcm2835: C library for Broadcom BCM 2835 as used in Raspberry Pi​​

(Works on all versions up to and including RPI 4. Works with all versions of Debian up to and including Debian Buster 10. bcm2835库更加简洁,它只有两个源文件bcm2835.c和bcm2835.h。在使用过程中我们可以选择将其安装到树莓派中来使用,也可以选择直接将两个文件包含到我们的应用代码中。bcm2835库本身就只有两个源文件,添加到应用层代码很简单而且方便查看源码。wring目前资料较多,与Arduino代码类似。)

​​树莓派使用C/C++基于Bcm2835操作GPIO学习记录_c++ 树莓派 io 口 操作 cannot find -lbcm2835_假的程序猿LC的博客-CSDN博客​​bcm2835源码说明

​​超简单教你在树莓派上安装opencv(二)_树莓派安装opencv_流 浪 猫的博客-CSDN博客​​

暂时找到32位,python3.9.2版本安装流程,测试通过。64位还需要测试(找文档注意系统和python版本);

​​树莓派基础实验_慕雪华年的博客-CSDN博客​​

​​热门内容和标签 | 树莓派实验室​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/500397.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【使用 PyQt6-第01章】 创建基本的应用程序

使用 PyQt6 创建您的第一个应用程序 目录 一、说明二、创建应用程序三、单步执行代码四、什么是事件循环&#xff1f;4.1 Qt 中的事件循环。 五、主窗口 QMainWindow六、调整窗口和小部件的大小 一、说明 本教程也适用于 PySide6 、 PySide2 和 PyQt5 在本教程中&#xff0c;…

钉钉 AI 升级多种功能;智谱AI PC智能助手发布;百度回应与苹果合作

▶ 钉钉 AI 升级上线多种功能 3 月 28 日&#xff0c;钉钉 AI 助理升级。升级后上线了图片理解、文档速读、工作流等产品能力&#xff0c;率先探索多模态、长文本与 RPA 技术在 AI 应用的落地。 基于阿里通义千问大模型&#xff0c;升级后的钉钉 AI 助理可以做到&#xff1a; …

C++ —— C++11新增语法

目录 一&#xff0c;列表初始化 1.1 这是什么&#xff1f; 1.2 initializer_list 1.3 在容器的运用 1.4 STL中的变化 二&#xff0c;右值引用和左值引用 2.1 是什么&#xff1f; 2.2 这两个东西有啥关系&#xff1f; 2.3 有啥用&#xff1f; 三&#xff0c;*移动构…

Jmeter 配置说明之线程组

一、线程组介绍&#xff1a; 线程组元件是任何一个测试计划的开始点。在一个测试计划中的所有元件都必须在某个线程组下。所有的任务都是基于线程组&#xff1a; 通俗理解&#xff1a; 线程组&#xff1a;就是一个线程组&#xff0c;里面有若干个请求&#xff1b; 线程&am…

基于JSPM的美食推荐管理系统

背景 互联网的迅猛扩张彻底转变了全球各类组织的运营模式。自20世纪90年代起&#xff0c;中国各级政府和企事业单位便开始探索运用网络系统来处理管理事务。然而&#xff0c;早期的网络覆盖不广、用户接受度不高、相关网络法规不健全以及技术发展不成熟等因素&#xff0c;都曾…

Kubernetes-running app on kube

Docker 安装Docker 首先&#xff0c;您需要在Linux机器上安装Docker。如果您不使用Linux&#xff0c;则需要启动一个Linux虚拟机(VM)并在该虚拟机中运行Docker。如果你使用的是Mac或Windows系统&#xff0c;并按照指令安装Docker, Docker将为你建立一个虚拟机&#xff0c;并在…

uniapp-打包IOS的APP流程

打包前所需配置 在manifest文件内配置 1. APP图标 2. 启动界面 有三种启动界面配置 第一种是 HBuilderX 官方给的通用启动界面&#xff0c;页面单一&#xff0c;屏幕中间就一个圆框图标 第二种是自定义的启动图&#xff0c;无法通过AppStore的审核 第三种是自定义storyboard启动…

亚信安全联合人保财险推出数字安全保障险方案,双重保障企业数字化转型

数字化发展&#xff0c;新兴技术的应用与落地带来网络攻击的进一步演进升级&#xff0c;同时全球产业链供应链融合协同的不断加深&#xff0c;更让网络威胁的影响范围与危害程度不断加剧。 企业单纯依靠自身安全能力建设&#xff0c;能否跟上网络威胁的进化速度&#xff1f;能否…

Go的数据结构与实现【Queue】

介绍 与栈一样&#xff0c;队列也是最基本的数据结构之一。队列也是值的一种容器&#xff0c;其中值的插入和删除遵循“先进先出”&#xff08;First-In-First-Out, FIFO&#xff09;的原则⎯⎯也就是说&#xff0c;每次删除的只能是最先插入的值。 实现 队列的抽象数据类型…

进程的等待

文章目录 一、进程等待意义二、进程等待方法 一、进程等待意义 当父进程创建子进程之后&#xff0c;当子进程退出时&#xff0c;需要它的父进程回收它的内核数据结构对象(pcb),因为进程退出之后不回收它会造成内存泄漏问题&#xff0c;子进程退出&#xff0c;若是父进程不管&a…

HarmonyOS ArkTS 骨架屏加载显示(二十五)

目录 前言1、骨架屏代码显示2、代码中引用3、效果图展示 前言 所谓骨架屏&#xff0c;就是在页面进行耗时加载时&#xff0c;先展示的等待 UI, 以告知用户程序目前正在运行&#xff0c;稍等即可。 等待的UI大部分是 loading 转圈的弹窗&#xff0c;有的是自己风格的小动画。其实…

010_documentation_in_Matlab中的帮助与文档

Matlab中的帮助与文档 1. 前言 一眨眼已经写了十篇文章。 000在Matlab中使用Python包CoolProp001Matlab运行时间测试与时间复杂度分析002避免使用for循环003Matlab中的向量约定004Matlab中的矩阵约定005Matlab中的数组索引006Matlab中的逻辑数组索引007Matlab学习的启动与加…

Word、Excel、PPT文件转PDF文件(C#)

一、添加依赖 为wpf项目引用Microsoft.Office.Interop.Excel、Microsoft.Office.Interop.PowerPoint、Microsoft.Office.Interop.Word、Office&#xff0c;依赖文件已经打到源代码包里了。 二、先定义一些命名空间 using Word Microsoft.Office.Interop.Word;using Excel M…

C++项目——集群聊天服务器项目(七)Model层设计、注册业务实现

在前几节的研究中&#xff0c;我们已经实现网络层与业务层分离&#xff0c;本节实现数据层与业务层分离&#xff0c;降低各层之间的耦合性&#xff0c;同时实现用户注册业务。 网络层专注于处理网络通信与读写事件 业务层专注于处理读写事件到来时所需求的各项业务 数据层专…

Polar靶场web(三)

期待得到某一件事物的时候&#xff0c;才是最美好的。 签到 发现不能提交&#xff0c;看一下f12 发现提交按钮被禁用了&#xff0c;且最大输入9个字符&#xff0c;我们可以改一下。 现随便提交一个发现要提交ilovejijcxy session文件包含 发现有文件包含&#xff0c;那先包含…

02正式学习第一天

1、windows上加载socket库 链接输入ws2_32.lib 代码code&#xff1a; #ifdef _WIN32 #include<windows.h> #else #include <sys/socket.h> #include<sys/types.h> #include<unistd.h> #include<cstring> #include<arpa/inet.h> #include…

基于Unity+Vue3通信交互的WebGL项目发布实践

基于UnityVue3通信交互的WebGL项目发布实践 实践路线 基于UnityVue3通信交互的WebGL项目发布实践问题背景准备工作解决方案项目实践小目标搭建Unity测试项目 创建Vue3测试项目运行项目验证unity和vue通信功能总结与展望 问题背景 我们最近需要把unity开发的pc项目迁移到web端&…

文心一言 VS 讯飞星火 VS chatgpt (225)-- 算法导论16.3 7题

七、推广赫夫曼算法&#xff0c;使之能生成三进制的码字(即码字由符号0、1、2组成)&#xff0c;并证明你的算法能生成最优三进制码。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 推广赫夫曼算法以生成三进制码字需要对算法进行一定的修改&#xff0c;确保在每…

阿里云国际DDoS高防如何添加网站配置?

将网站域名配置到DDoS高防后&#xff0c;DDoS高防会为网站生成一个CNAME地址&#xff0c;您需要将网站域名的DNS解析指向高防CNAME地址&#xff0c;DDoS高防才能转发业务流量为网站防御DDoS攻击。本文介绍如何添加网站配置。 注意事项 接入DDoS高防&#xff08;中国内地&#…

WPF中获取TreeView以及ListView获取其本身滚动条进行滚动

实现自行调节scoll滚动的位置(可相应获取任何控件中的内部滚动条) TreeView:TreeViewAutomationPeer lvap new TreeViewAutomationPeer(treeView); var svap lvap.GetPattern(PatternInterface.Scroll) as ScrollViewerAutomationPeer; var scroll svap.Owner as ScrollVie…