【技术】smart_car运用下非语音的树莓派声源定位与串口数据传输融合

一、声源定位

smart_car
smart_car的github代码下载
smart_car的video
树莓派USB与PC实现串口通信
python实时绘图
程序实现树莓派自启动

1、github上下载smart_car

在这里插入图片描述
图片中pixels可实现直接运行测试麦克风阵列的驱动是否完全安装好,smart_raspberry是主函数,但其中运行的库文件太多(如opencv)目前暂时不需要,因此小编自己新建了一个主函数,实际代码如下:
在这里插入图片描述

2、复制驱动库

(1)将/home/pi/voice-engine下的的库文件voice_engine复制至smart_car文件夹下
(2)报错头文件文件找不到解决方案(类似问题以此类推)
from .gcc_phat import gcc_phat 改为 from voice_engine.gcc_phat import gcc_phat

3、替换文件

将smart_car下的doa_respeaker_4mic_array和gcc_phat文件替换voice_engine下的同名文件,使其改为非关键字“snowboy”输出定位信息,麦克风阵列周围有声响时用print(amtitude,position)输出角度信息,并有相应位置的led灯闪烁(程序可实现)

4、程序运行

主要运行的main函数如下所示:并且运行后角度和位置输出在输出窗口可查看:
在这里插入图片描述

5、实验现象

当有声响时,响应位置的灯亮起,图片下方顶部的灯亮绿色,其他的灯为蓝色:
在这里插入图片描述
贴代码,是否需要加压缩包

二、串口数据发送

树莓派-pypi-UART串口
Python串口编程(转载)
Python字符串转十六进制进制互转
线程与进程的区别

1、write函数

从串口发送数据
  [串口对象].write([单字节数组])
  发送的数据必须是单字节数据,可以是单字节组成的list,也可以是单字节编码的字符串(如ASCII、UTF-8)。返回的是写入的字节数。
  例1,发送16进制数据:
  list1 = [0x01,0x02,0x03,0x10]
  ser.write(list1)
  会把这几个16进制数依次通过串口发出,另一端会接收到一模一样的数据。
  例2,发送单字节编码的字符串:
  ser.write(b’abcdefg’)
  把字符串’abcdefg’的ascii码发出,另一端收到:0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67。

2、发送数据

程序初始设置好串口条件,在doa函数中调用设置的串口变量str实现写数据
str.write(position)
注意:如果需要将doa_thread和serial_thread同时进行是不可取的,这样会导致doa线程被阻挡,同时不能在线程中设置for循环,对线程而言速度运算要求过高,如果for循环运算阻挡了,线程将无法进行。

3、树莓派自启动

超声波模块使用

超声波模块使用

int led = 13;
float duration;                
float distance;              
//int srfPin = 8;
const int TrigPin = 8;
const int EchoPin = 7;

void setup() 
{
    Serial.begin(9600);
    pinMode(led, OUTPUT); 
    pinMode(9,OUTPUT);
    pinMode(10,OUTPUT);
    pinMode(5,OUTPUT); 
    pinMode(6,OUTPUT);
    pinMode(TrigPin,OUTPUT);
    pinMode(EchoPin,INPUT);
    Serial.println("Ultrasonic sensor");
    
    
}
void loop()
{
    delay(100);               // wait for a second
    if (Serial.available()>0)
    {
      char cmd = Serial.read();
      //Serial.print(cmd);
      switch (cmd)
      {
        case '1':
            Forward();
            break;
        case '2':
            Back();
            break;
        case '3':
            Turn_left();
            break;
        case '4':
            Turn_right();
            break;
        //case '6':
        //    Measure();
        default:
            Stop();
      }
    }
    Measure();
}
void Forward()
{
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
}
void Back()
{
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}
void Turn_right()
{
    digitalWrite(9,LOW);
    digitalWrite(10,HIGH);
    digitalWrite(5,HIGH);
    digitalWrite(6,LOW);
}
void Turn_left()
{
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,HIGH);
}

void Stop()
{
    digitalWrite(9,LOW);
    digitalWrite(10,LOW);
    digitalWrite(5,LOW);
    digitalWrite(6,LOW);
}

void Measure()
{
      
      digitalWrite(TrigPin, LOW);            
      delayMicroseconds(2); 
      digitalWrite(TrigPin, HIGH);           
      delayMicroseconds(10); 
      digitalWrite(TrigPin, LOW);            
      duration = pulseIn(EchoPin, HIGH);         
      distance = duration/58;
      Serial.print(":");       
      Serial.print(distance);
      Serial.println(";");     
      delay(50);  
}

软件安装:arduino

链接:树莓派安装arduino的IDE
在这里插入图片描述

4、python

import serial
import time
import socket
import sys
import threading
import random
import os
import time
import struct
import serial
import numpy as np
import datetime
#import sqlite3

from voice_engine.source import Source
from voice_engine.channel_picker import ChannelPicker
from voice_engine.doa_respeaker_4mic_array import DOA
from pixels import pixels

ser = serial.Serial("/dev/ttyUSB0",9600,timeout=0.5)
ser.write(b"Raspberry pi is ready")

HOST = "0.0.0.0"
PORT = 9004
SOCK_ADDR = (HOST, PORT)
exit_now = 0
distance = 0

moving = False
last_movement_timestamp = datetime.datetime.now()
doa_valid = True
amplitute = 0
position = 0


def exit_signal_handle(sig,stack_frame):  #no
    global exit_now
    print ("EXIT sig")
    exit_now = 1

class serial_thread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        global amplitute,position
        self.running = True
        while self.running:  
            try:
                while True:
                    #print(amplitute,position)
                    #ser.write(amplitute,position)
                    count = ser.inWaiting()
                    if count!=0:
                        recv = ser.read(count)
                        ser.write(recv)
                    ser.flushInput()
                    time.sleep(1)
            except :
                ser.close()

    def stop(self):
        self.running = False

class doa_thread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        global moving,last_movement_timestamp,doa_valid,amplitute,position
        src = Source(rate=16000, channels=4, frames_size=320)
        #ch1 = ChannelPicker(channels=4, pick=1)
        doa = DOA(rate=16000)
        #src.link(ch1)
        src.link(doa)
        src.recursive_start()
        self.running = True
        while self.running:
            try:
                time.sleep(1)
                current_timestamp = datetime.datetime.now()
                if doa_valid == True and ((current_timestamp - last_movement_timestamp).seconds > 2):
                    position, amplitute = doa.get_direction()
                    #str_position = ''.join([chr(i) for i in [int(b, 16) for b in position.split(' ')]])
                    print(position)
                    #ser.write(position)
                    if amplitute > 2000:
                        pixels.wakeup(position)                       
                        if position > 0  and position < 180:
                            pivot_right()
                            time.sleep(position/200)
                            stop()
                        elif position >= 180 and position < 360:
                            pivot_left()
                            position = 360 - position
                            time.sleep(position/200)
                            stop()
                        time.sleep(2)
                        
                    else:
                        pixels.speak()
                else:
                    pixels.think()
            except:
                print(sys.exc_info())
         
        src.recursive_stop()
    def hexShow(argv):
        result = ''
        hLen = len(argv)
        for i in xrange(hLen):
            hvol = ord(argv[i])
            hhex = '%02x'%hvol
            result += hhex+' '
        print (result)
    def stop(self):
        self.running = False

    
        
def main():
    global moving,last_movement_timestamp,doa_valid,distance,amplitute,position
    doa_th = doa_thread()
    doa_th.start()
    #ser_th = serial_thread()
    #ser_th.start()
    
    doa_th.stop()
    doa_th.join()
    #ser_th.stop()
    #ser_th.join()
 

if __name__ == "__main__":
    main()





  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值