本人最近在 nanopc T4 开发板上做了一些小功能(完成导师安排的任务),初步实现了以下几个功能:

    1. 键盘控制 舵机上下左右旋转(两台舵机)
    1. nanopc-T4 开发板实现的人脸检测
    1. 根据人脸的位置控制舵机跟随人脸左右运动(人脸识别+人脸跟踪)
    1. nanopc-T4 开发板实现人脸识别
    1. 远程(http_get)控制舵机上下左右转动
    1. 舵机使用软件 PWM 驱动
    1. 解决舵机软件 PWM 驱动造成的抖动的一种方法


1. 键盘控制 舵机上下左右旋转(两台舵机)

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

void foo(int pinN,int moveAngle);
// 接收一个输入度数
int main(void)
{
    // pinN 为nanopc-T4 开发板上的引脚(以 Wpi脚 计数,通过 gpio readall 命令查看 wpi 引脚标号)
    // 物理引脚为 7、11
    int pinN_1=7;
    int pinN_2=0;
    int num;
    wiringPiSetup() ;
    //设置舵机控制引脚
    pinMode (pinN_1, OUTPUT) ;
    pinMode (pinN_2, OUTPUT) ;
    //设置初始旋转到90度
    // 330-2400 (10~170度)
    int moveAngle_1=1365;
    int moveAngle_2=1365;
    foo(pinN_1,moveAngle_1);
    foo(pinN_2,moveAngle_2);
    for(;;){
        printf("请输入移动方向,0表示左,1表示右,2表示上,3表示下\n");
        scanf("%d",&num);
        if(num==0||num==1){
            if(num==0){
            moveAngle_1=moveAngle_1-100;
            }
            if(num==1){
                moveAngle_1=moveAngle_1+100;
            }
            foo(pinN_1,moveAngle_1);
        }

        if(num==2||num==3){
            if(num==2){
            moveAngle_2=moveAngle_2-100;
            }
            if(num==3){
                moveAngle_2=moveAngle_2+100;
            }
            foo(pinN_2,moveAngle_2);
        }
        
        if(moveAngle_1>2400||moveAngle_1<320||moveAngle_2>2400||moveAngle_2<320){
            printf("已到头!");
            break;
        }
    }
	printf("%d\n", num);
	printf("%d\n", moveAngle_1);
	printf("%d\n", moveAngle_2);
	return 0;
}

void foo(int pinN,int moveAngle){
     // 给舵机一段时间的反应,持续输出控制值
    for (int i = 0; i < 200; i++)
    {
    digitalWrite(pinN,HIGH);
    delayMicroseconds(moveAngle);
    digitalWrite(pinN,LOW);
    delayMicroseconds(2500-moveAngle);
    }
    printf("1");
}

2. nanopc-T4 开发板实现的人脸检测

import numpy as np
import cv2

# 获取opencv自带的用于人脸识别的级联分类器 
faceCascade = cv2.CascadeClassifier('/media/pi/userdata/root/usr/local/share/OpenCV/haarcascades/haarcascade_frontalcatface.xml')
eye_cascade = cv2.CascadeClassifier('/media/pi/userdata/root/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml')

# 打开摄像头,本地自带的摄像头默认为0
cap = cv2.VideoCapture(10)
cap.set(3,640) # set Width
cap.set(4,480) # set Height
i=0
range1=80
range2=60
# 设置舵机旋转90度时对应值
moveAngle_1=1435

while True:
    ret, img = cap.read()
    #  控制图像翻转给,1,左右翻转,-1,上下翻转
    img = cv2.flip(img, 1) 
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(
        gray,     
        # 表示每次图像检测的比例
        scaleFactor=1.1,
        # 表示每一个目标至少要被检测到3次才算是真的目标
        minNeighbors=3,     
        minSize=(20, 20)
    )
    
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
        print("%d,x = %d,x+w = %d,y = %d,y+h = %d" %(i,x,x+w,y,y+h))
        i+=1
        #  框选出人脸区域,在人脸区域而不是全图中进行人眼检测,节省计算资源
        face_area = img[y:y+h, x:x+w]  # 人脸区域
        eyes = eye_cascade.detectMultiScale(face_area,1.1,5)
        for (ex,ey,ew,eh) in eyes:
            #画出人眼框,绿色,画笔宽度为1
            cv2.rectangle(face_area,(ex,ey),(ex+ew,ey+eh),(0,255,0),1)

        roi_gray = gray[y:y+h, x:x+w]
        roi_color = img[y:y+h, x:x+w]  
    
    cv2.namedWindow("enhanced",0);

    cv2.resizeWindow("enhanced", 640, 640);
    cv2.imshow('video',img)
    
    k = cv2.waitKey(30) & 0xff
    if k == 27: # press 'ESC' to quit
        break
 
cap.release()
cv2.destroyAllWindows()

3. 根据人脸的位置控制舵机跟随人脸左右运动(人脸检测+人脸跟踪)

通过 1 与 2 的结合,调整部分程序代码实现。

舵机控制程序 duoji.c

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

// gcc -Wall -o duoji duoji.c -lwiringPi -lwiringPiDev -lpthread -lrt -lm -lcrypt -shared

void foo(int pinN,int moveAngle);

// 接收一个输入度数
int fmain(int num,int moveAngle_1)
{
    // pinN 为nanopc-T4 开发板上的引脚(以 Wpi脚 计数,通过 gpio readall 命令查看 wpi 引脚标号)
    int pinN_1=7;
    int pinN_2=0;

    wiringPiSetup() ;

    // for(;;){
    //     moveAngle_1=1365;
    //     moveAngle_2=1365;
    //     break;
    // }
    //设置舵机控制引脚
    pinMode (pinN_1, OUTPUT) ;
    pinMode (pinN_2, OUTPUT) ;
    //旋转到90度

    // foo(pinN_1,moveAngle_1);
    // foo(pinN_2,moveAngle_2);
    
        // printf("请输入移动方向,0表示左,1表示右,2表示上,3表示下\n");
        // scanf("%d",&num);
        if(num==0||num==1){
            if(num==0){
            moveAngle_1=moveAngle_1-50;
            }
            if(num==1){
                moveAngle_1=moveAngle_1+50;
            }
            foo(pinN_1,moveAngle_1);
        }

        if(moveAngle_1>2400||moveAngle_1<320){
            printf("已到头!");
        }
    
	printf("%d\n", num);
	printf("%d\n", moveAngle_1);

	return moveAngle_1;
}

void foo(int pinN,int moveAngle){
     // 给舵机一段时间的反应,持续输出控制值
    for (int i = 0; i < 200; i++)
    {
    digitalWrite(pinN,HIGH);
    delayMicroseconds(moveAngle);
    digitalWrite(pinN,LOW);
    delayMicroseconds(2500-moveAngle);
    }
    printf("1");
}

通过编译命令将其进行编译
gcc -Wall -o duoji duoji.c -lwiringPi -lwiringPiDev -lpthread -lrt -lm -lcrypt -shared

通过人脸检测程序 face.py 判断人脸的位置,并调用舵机控制程序实现人脸的跟踪

import numpy as np
import cv2
# python 调用 C 所必须的操作
import ctypes  
ll = ctypes.cdll.LoadLibrary   
lib = ll("./duoji/duoji")
 
faceCascade = cv2.CascadeClassifier('/media/pi/userdata/root/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('/media/pi/userdata/root/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml')


cap = cv2.VideoCapture(10)
cap.set(3,640) # set Width
cap.set(4,480) # set Height
i=0
moveAngle_1=1435

while True:
    ret, img = cap.read()
    img = cv2.flip(img, 1) 
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(
        gray,     
        # 表示每次图像尺寸减小的比例
        scaleFactor=1.1,
        # 表示每一个目标至少要被检测到3次才算是真的目标
        minNeighbors=10,     
        minSize=(20, 20)
    )
    
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
        print("%d,x = %d,x+w = %d,y = %d,y+h = %d" %(i,x,x+w,y,y+h))
        i+=1
         # 框选出人脸区域,在人脸区域而不是全图中进行人眼检测,节省计算资源
        face_area = img[y:y+h, x:x+w]  # 人脸区域
        eyes = eye_cascade.detectMultiScale(face_area,1.1,5)
        for (ex,ey,ew,eh) in eyes:
            #画出人眼框,绿色,画笔宽度为1
            cv2.rectangle(face_area,(ex,ey),(ex+ew,ey+eh),(0,255,0),1)

        # x 是人脸识别框中的左上角横坐标,根据 x 坐标在相机中的位置,判断相机(舵机)的移动方向
        if(x < 320-0.7*w):
            print(x)
            # 0 或 1 表示转动方向,moveAngle_1 为转动角度系数,调用 duoji.c 中函数
            moveAngle_1=lib.fmain(0,moveAngle_1)
            # print("lib.fmain(0)="+str(lib.fmain(0)))
        if(x+w > 320+0.7*w):
            moveAngle_1=lib.fmain(1,moveAngle_1)

        roi_gray = gray[y:y+h, x:x+w]
        roi_color = img[y:y+h, x:x+w]  
    
    cv2.namedWindow("enhanced",0);

    cv2.resizeWindow("enhanced", 640, 640);
    cv2.imshow('video',img)
    
    k = cv2.waitKey(30) & 0xff
    if k == 27: # press 'ESC' to quit
        break
 
cap.release()
cv2.destroyAllWindows()

4. nanopc-T4 开发板实现人脸识别

本次使用3个Python程序,分别为人脸数据采集程序,人脸数据训练程序以及人脸数据检测程序来实现此人脸识别程序。本程序经测试在本地电脑中运行结果良好,能正常识别出已训练好的人脸数据,但在 nanopc-T4 开发板中运行结果较不理想,初步判断为 nanopc-T4 开发板性能不足导致,后期仔细分析病假一改善。

在OpenCV中,可以用函数cv2.face.LBPHFaceRecognizer_create()生成LBPH识别器实例模型,然后应用cv2.face_FaceRecognizer.train()函数完成训练,最后用cv2.face_FaceRecognizer.predict()函数完成人脸识别。

  1. 个人人脸图片采集程序,将采集的人脸图片数据存放到 ./userImg 目录下
import cv2
import os

cam = cv2.VideoCapture(0)  # 获取摄像头
cam.set(3, 640) # set video width  # 设置视频的高度和宽度
cam.set(4, 480) # set video height

# 获取本地安装的cv2目录下的级联分类器
face_detector = cv2.CascadeClassifier(r'C:\Users\hotpotman\.conda\envs\face\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')

# 对于每个人,输入一个编号用以区分
face_id = input('\n enter user id end press <return> ==>  ')

#print("\n [INFO] Initializing face capture. Look the camera and wait ...")
# Initialize individual sampling face count
count = 0

while(True):
    ret, img = cam.read() # 从摄像头读取图像
    # 从文件中读取图像
    # img = cv2.imread("/home/pi/Desktop/uerImg/" + str(count) + '.jpg')
    #print("/home/pi/Desktop/兔子牙/" + str(count) + '.jpg')
    # 翻转图像 1  水平翻转  0 垂直翻转   -1 水平垂直翻转
    #img = cv2.flip(img, -1) # flip video image vertically
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转化为灰度图
    # 使用级联分类器进行图片人脸检测
    faces = face_detector.detectMultiScale(gray, 1.2, 5)
    
    count += 1
# 在人脸上画矩形
    for (x,y,w,h) in faces:
        cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)
        

        # 将图片保存到 userImg目录下
        cv2.imwrite("./userImg/" + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])
        cv2.imshow('image', img) # 显示
        
    cv2.imshow('image', img) # 显示
    # 当按下 ESC 或者采集到 10 张图片时 退出
    k = cv2.waitKey(100) & 0xff 
    if k == 27:
        break
    elif count >= 10: 
        break

# 关闭所有窗口,并释放资源
print("\n [INFO] Exiting Program and cleanup stuff")
cam.release()
cv2.destroyAllWindows()
  1. 根据采集到的人脸数据进行训练,提取其特征,并将训练好的数据存放到 ./trainer/trainer.yml 文件中
import numpy as np
from PIL import Image # python里面的图像库
import os
import cv2

# Path for face image database
path = './userImg' # 数据集的路径


# 在OpenCV中,可以用函数cv2.face.LBPHFaceRecognizer_create()生成LBPH识别器实例模型,然后应用cv2.face_FaceRecognizer.train()函数完成训练,最后用cv2.face_FaceRecognizer.predict()函数完成人脸识别。
# https://blog.csdn.net/qq_43069920/article/details/103673125

# LBPH识别器实例模型
recognizer = cv2.face.LBPHFaceRecognizer_create()

# 获取本地安装的cv2目录下的人脸检测级联分类器
detector = cv2.CascadeClassifier(r'C:\Users\hotpotman\.conda\envs\face\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml');

# 定义一个函数 用来获取 LBPH识别器 训练的图像和标签
def getImagesAndLabels(path):
    imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
    # print(imagePaths) # 输出文件夹所有的文件路径
    faceSamples=[]  # 存放人脸
    ids = []       # 存放人脸的ID
    for imagePath in imagePaths:  # 遍历路径
        PIL_img = Image.open(imagePath).convert('L') # convert it to grayscale
        img_numpy = np.array(PIL_img,'uint8')
        print(os.path.split(imagePath)[-1])
        # 获取图片中包含的人脸id
        id = int(os.path.split(imagePath)[-1].split(".")[0]) # 获取ID
        print(id)
        #print(" " + str(id)) # 输入ID
        faces = detector.detectMultiScale(img_numpy)
        for (x,y,w,h) in faces:
            faceSamples.append(img_numpy[y:y+h,x:x+w])
            ids.append(id)
    return faceSamples,ids

print ("\n [INFO] Training faces. It will take a few seconds. Wait ...")
faces,ids = getImagesAndLabels(path)
# 传入图像和标签 ,训练 LBPH识别器
recognizer.train(faces, np.array(ids))

# 将训练好的识别器 导出为 .yml 文件
recognizer.write('./trainer/trainer.yml') # recognizer.save() worked on Mac, but not on Pi

# Print the numer of faces trained and end program
print("\n [INFO] {0} faces trained. Exiting Program".format(len(np.unique(ids))))

  1. 根据训练好的数据,调用摄像头实时进行识别
import cv2
import numpy as np
import os 
 
recognizer = cv2.face.LBPHFaceRecognizer_create()  # 识别器
recognizer.read('./trainer/trainer.yml') # 加载训练集

# 获取本地安装的cv2目录下的人脸识别级联分类器
faceCascade = cv2.CascadeClassifier(r"C:\Users\hotpotman\.conda\envs\face\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml");
 
font = cv2.FONT_HERSHEY_SIMPLEX   # 字体
 
#iniciate id counter
id = 0
 
# 定义图片中的人物名称,根据输入的 id 对应填写
names = ['None', 'zhaww', 'liuss','ligb'] 
 
# 获取摄像头 本地摄像头默认为 0
cam = cv2.VideoCapture(0)
cam.set(3, 640) # set video widht
cam.set(4, 480) # set video height
# 在AGX上不要去直接设置帧率,不好用,主要是opencv默认为YUY2格式的视频流,最高帧率只有40,而这个MJPG格式可以很高
# cam.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
 
# 定义最小识别范围
minW = 0.1*cam.get(3)
minH = 0.1*cam.get(4)
 
while True:
    ret, img =cam.read()  # 读取一帧图像
    # 设置图像对称旋转,-1或1
    img = cv2.flip(img, 1) 
    #img = cv2.flip(img, -1) # Flip vertically
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 转化为灰度图
    
    # 使用级联分类器进行图片人脸检测
    faces = faceCascade.detectMultiScale( 
        gray,
        scaleFactor = 1.2,
        # 图片重复检车次数
        minNeighbors = 5,
        minSize = (int(minW), int(minH)),
       )
 
    for(x,y,w,h) in faces:
        # 根据坐标画出人脸框,蓝色,画笔宽度为2
        cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
        # 根据 LBPH识别器训练好的数据,与当前画面中的人脸进行匹配,返回其 ID 与 置信区间值
        id, confidence = recognizer.predict(gray[y:y+h,x:x+w])
        print("id=%d"%(id))
        # Check if confidence is less them 100 ==> "0" is perfect match 
        if (confidence < 100):
            # print("%id="%(id))
            id = names[id]
            confidence = "  {0}%".format(round(100 - confidence))
        else:
            id = "unknown"
            confidence = "  {0}%".format(round(100 - confidence))
        # 将 id 与 置信区间值 写到图片帧中
        cv2.putText(img, str(id), (x+5,y-5), font, 1, (255,255,255), 2)
        cv2.putText(img, str(confidence), (x+5,y+h-5), font, 1, (255,255,0), 1)  
     
    cv2.imshow('camera',img) 
 
    k = cv2.waitKey(10) & 0xff # Press 'ESC' for exiting video
    if k == 27:
        break
 
# Do a bit of cleanup
print("\n [INFO] Exiting Program and cleanup stuff")
cam.release()
cv2.destroyAllWindows()

5. 远程(http_get)控制舵机上下左右转动

在 nanopc-T4 上使用 web.py 部署 http_server ,用来解析 http_get 请求发送过来的数据,并根据传过来的数据调用舵机控制程序控制舵机上下左右转动。

  1. 使用 natfrp 服务在 nanopc-T4(ubuntu18.04)中搭建内网穿透服务,注意使用 http 协议。
  2. 在 nanopc-T4 上使用 web.py 搭建一个 web 服务器,接受通过内网穿透服务所传递过来的 http_get 请求,请解析出其携带的参数。
  3. 根据解析出的参数,调用舵机控制程序控制舵机上下左右转动。
# python_web 程序

# 接受 http_get 请求并解析出参数
import web
# python 调用 c 所必须
import ctypes 
ll = ctypes.cdll.LoadLibrary   
lib = ll("./duoji")

# 设置路由及其对应的处理类
urls = (
  '/', 'index'
)
# 舵机旋转90度对应值
moveAngle_1=1435

class index():
    def GET(self):
        print(web.input().num)
        # moveAngle_1=lib.fmain(web.input().num,moveAngle_1)

        return moveDUoji(int(web.input().num))

 
def moveDUoji(num):
    # 必须使用 global  声明 moveAngle_1 为全局变量,否则函数内尝试改变全局就会报错
    # https://blog.csdn.net/sinat_40304087/article/details/115701595
    global moveAngle_1
    moveAngle_1=lib.fmain(num,moveAngle_1)
    print(num)
    print(moveAngle_1)


if __name__== "__main__":
    app= web.application(urls,globals())
    app.run()

# 命令行带端口号

6. 舵机使用软件 PWM 驱动

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <softPwm.h>
// gcc -Wall -o demo2 demo2.c -lwiringPi -lwiringPiDev -lpthread -lrt -lm -lcrypt -shared

#define RANGE 200     /* 1 means 100 us , 200 means 20 ms 1等于100微妙,200等于20毫秒 */

void foo(int pinN,int moveAngle);
// 接收一个输入度数
int main(void)
{
    // pinN 为nanopc-T4 开发板上的引脚(以 Wpi脚 计数,通过 gpio readall 命令查看 wpi 引脚标号)
    int pinN_1=7;
    int pinN_2=0;
    int num=-1;
    wiringPiSetup() ;
    //设置舵机控制引脚
 	int	moveAngle_1	= 90;
	int	moveAngle_2	= 90;
	wiringPiSetup();                        /* wiringpi初始化 */
	softPwmCreate( pinN_1, 0, RANGE );     /* 创建一个使舵机转到90的pwm输出信号 */
	softPwmCreate( pinN_2, 0, RANGE );     /* 创建一个使舵机转到90的pwm输出信号 */

    for(;;){
        num=-1;
        printf("请输入移动方向,0表示左,1表示右,2表示上,3表示下\n");
        scanf("%d",&num);
        if(num==0||num==1){
            if(num==0){
            // 每次调节+-5度
            moveAngle_1=moveAngle_1-5;
            }
            if(num==1){
                moveAngle_1=moveAngle_1+5;
            }
            foo(pinN_1,moveAngle_1);
        }

        if(num==2||num==3){
            if(num==2){
            moveAngle_2=moveAngle_2-5;
            }
            if(num==3){
                moveAngle_2=moveAngle_2+5;
            }
            foo(pinN_2,moveAngle_2);
        }
        
        if(moveAngle_1>180||moveAngle_1<0||moveAngle_2>180||moveAngle_2<0){
            printf("已到头!");
            break;
        }
        printf("%d\n", num);
	printf("%d\n", moveAngle_1);
	printf("%d\n", moveAngle_2);

    }
	return 0;
}

void foo(int pinN,int moveAngle){
     
    int degree;
    // 将角度转化为pwm值(0-180:5ms-25ms)
	degree = 5 +  moveAngle  / 180.0 * 20.0;    
    softPwmWrite( pinN, degree ); /* pwm输出脉冲控制舵机旋转 */
    delay(500);
    printf("函数执行完了");
}

7. 解决舵机软件 PWM 驱动造成的抖动的一种方法

在每次引脚输出 pwm 之后,给引脚一个 pwm=0 的值,经测试可以有效的解决舵机抖动的问题。

舵机旋转角度与 pwm 值之间的关系:

nanopc-T4_RK3399 舵机与人脸检测跟踪相关程序-1637667464554-2021112319386.png
/* file name=sg90.c */
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

#include <wiringPi.h>
#include <softPwm.h>

#define RANGE 200     /* 1 means 100 us , 200 means 20 ms 1等于100微妙,200等于20毫秒 */

int move( int pin, int moveAngle )
{
	int degree;
	degree = 5 +  moveAngle  / 180.0 * 20.0;

	softPwmWrite( pin, degree ); /* 再次复写pwm输出 */
	delay( 200 );
	printf("%d\n",degree);
	printf("%d\n",moveAngle);
	// softPwmStop(pin);
	// 输入 pwm 后,给 pwm 为 0,防抖
	softPwmWrite( pin, 0 );
    return 0;
}

int main( void )
{
	int	num;
	int	pinN_1	= 7;
	int	pinN_2	= 0;

	int	moveAngle_1	= 90;
	int	moveAngle_2	= 90;
	wiringPiSetup();                        /* wiringpi初始化 */
	softPwmCreate( pinN_1, 15, RANGE );     /* 创建一个使舵机转到90的pwm输出信号 */
	delay(500);
		softPwmWrite( pinN_1, 0 );
	softPwmCreate( pinN_2, 15, RANGE );     /* 创建一个使舵机转到90的pwm输出信号 */
	delay(500);
	softPwmWrite( pinN_2, 0 );

	for (;; )
	{
		printf( "请输入移动方向,0表示左,1表示右,2表示上,3表示下\n" );
		scanf( "%d", &num );

		if ( !(( num ) >= 0 && ( num ) <= 180) ){
			printf( "degree is between 0 and 180\n" );
			exit( 0 );
		}

		if ( num == 0 || num == 1 ){
			if ( num == 0 ){
				moveAngle_1 = moveAngle_1 - 5;
			}
			if ( num == 1 ){
				moveAngle_1 = moveAngle_1 + 5;
			}
			move( pinN_1, moveAngle_1 );
		}

		if ( num == 2 || num == 3 ){
			if ( num == 2 ){
				moveAngle_2 = moveAngle_2 - 5;
			}
			if ( num == 3 ){
				moveAngle_2 = moveAngle_2 + 5;
			}
			move( pinN_2, moveAngle_2 );
		}
	}
    return 0;
}

本文相关代码见 :https://gitee.com/qiaoyukeji/nanopcT4_used