傳送門
上一個部落格的中心是Orangepi 4B
這個部落格則是以arduino配合Orangepi 4B完成電機驅動舵機等的操作
1.C語言/C++基礎
2.arduino IDE軟體的基本操作
3.arduino中json庫(ArduinoJson.h)和多執行緒庫(scoop.h)的使用
4.arduino中UART通訊的方法
5.python中串列埠通訊庫(pyserial)和執行緒庫(threading)的使用
上一個部落格(見上方傳送門)中的所有硬體外加一張arduino uno微控制器(mega328p)幾根杜邦線、一個兩路電機驅動晶片、兩個電機,一個萬向滾珠、一個底座(實際上底盤可以根據經濟決定好壞)當然你也可以再加上一些採集模組讓你的機器人功能更豐富,我這裡加裝了一個DHT11模組(溫溼度採集)。
下載arduino IDE軟體可在arduino中文社群下載中文社群
裡面集中著各種arduino大佬
需要準備庫我給大家準備好了大家解壓到Arduino\libraries目錄下即可
集合下載地址提取碼:3101
python環境下需要下載對執行緒庫(threading)以及串列埠通訊庫(pyserial)
下載方式為開啟終端輸入以下命令
pip install threading
pip install pyserial
#include <ArduinoJson.h> //載入庫檔案
#include <math.h>
#include <SCoop.h>
#include <dht11.h>
#define DHT11PIN 10 //定義模組埠
dht11 DHT11; //範例化 DHT模組
int beep=8; //蜂鳴器引腳定義
int speedleft=5; //左電機速度引腳定義
int speedright=6; //右電機速度引腳定義
int left_motor_go=3; //左電機正轉引腳定義
int right_motor_go=4; //右電機正轉引腳定義
int left_motor_back=2; //左電機反轉引腳定義
int right_motor_back=7; //右電機反轉引腳定義
char control1="停止"; //儲存小車控制命令,初始命令為停止
StaticJsonBuffer<200> jsonsendBuffer; //建立json buffer空間
JsonObject& root = jsonsendBuffer.createObject();//將root定義為json變數
String line =""; //建立字串變數儲存串列埠接收到的字串
defineTaskLoop(myTask1) //任務執行緒1每隔一秒
{
DHT11.read(DHT11PIN); //讀取溫溼度
float tem=(float)DHT11.temperature; //將溫度值賦值給tem
float hum=(float)DHT11.humidity; //將溼度值賦給hum
root["Tempeature"]=tem;
root["Humidity"]=hum;
root.printTo(Serial); //延時一段時間
sleep(1000); //延時一段時間
}
void forward()//小車前進
{
digitalWrite(left_motor_go,HIGH); //左電機正轉
digitalWrite(left_motor_back,LOW);
digitalWrite(right_motor_go,HIGH); //右電機正轉
digitalWrite(right_motor_back,LOW);
}
void backward()//小車後退
{
digitalWrite(left_motor_go,LOW); //左電機反轉
digitalWrite(left_motor_back,HIGH);
digitalWrite(right_motor_go,LOW); //右電機反轉
digitalWrite(right_motor_back,HIGH);
}
void right()//小車單輪左轉
{
digitalWrite(left_motor_go,LOW); //左電機停止
digitalWrite(left_motor_back,LOW);
digitalWrite(right_motor_go,HIGH); //右電機正轉
digitalWrite(right_motor_back,LOW);
}
void left() //小車單輪右轉
{
digitalWrite(left_motor_go,HIGH); //左電機正轉
digitalWrite(left_motor_back,LOW);
digitalWrite(right_motor_go,LOW); //右電機停止
digitalWrite(right_motor_back,LOW);
}
void stopcar()//停車
{
digitalWrite(left_motor_go,LOW); //左電機停止
digitalWrite(left_motor_back,LOW);
digitalWrite(right_motor_go,LOW); //右電機停止
digitalWrite(right_motor_back,LOW);
}
void goright()//小車原地左轉
{
digitalWrite(left_motor_go,LOW); //左電機反轉
digitalWrite(left_motor_back,HIGH);
digitalWrite(right_motor_go,HIGH); //右電機正轉
digitalWrite(right_motor_back,LOW);
}
void goleft()//小車原地右轉
{
digitalWrite(left_motor_go,HIGH); //左電機正轉
digitalWrite(left_motor_back,LOW);
digitalWrite(right_motor_go,LOW); //右電機反轉
digitalWrite(right_motor_back,HIGH);
}
void setup() { //初始化
Serial.begin(115200);
pinMode(speedleft,OUTPUT); //設定引腳輸入輸出
pinMode(speedright,OUTPUT);
pinMode(left_motor_go,OUTPUT);
pinMode(right_motor_go,OUTPUT);
pinMode(left_motor_back,OUTPUT);
pinMode(right_motor_back,OUTPUT);
pinMode(beep,OUTPUT);
analogWrite(speedleft,100); //輸入模擬值進行設定速度
analogWrite(speedright,100);
mySCoop.start();
digitalWrite(right_motor_back,HIGH);
delay(1000)
digitalWrite(right_motor_back,LOW); //初始化完成蜂鳴器響一秒
}
void loop() {
if(control1="goon")
forward();
else if(control1="goback")
backward();
else if(control1="turnleft")
left();
else if(control1="turnright")
right();
else if(control1="turnturnleft")
goleft();
else if(control1="turnternright")
goright();
else if(control1="stop")
stopcar();
else
stopcar();
yield();
}
void serialEvent()
{
if(Serial.available()) //串列埠是否有資料?
{
String line = Serial.readStringUntil('\r');
StaticJsonBuffer<200> jsonreciveBuffer;
JsonObject& data1 = jsonreciveBuffer.parseObject(line);
control1=data1["control"];
data1.printTo(Serial); //測試時使用
}
}
}
依舊在是之前demo上修改
加上多執行緒函數建立執行緒監測從微控制器發來的資訊,並且加上對硬體控制的指令uart通訊等
import threading
import serial
from time import sleep
ser = serial.Serial('/dev/ttyS4', 115200, timeout=0.5) #香橙派4B只開放使用uart4埠
def recv(serial):
while True:
data =serial.read(30)
if data != '':
Tempeature=json.loads(data).get('Tempeature');
Humidity=json.loads(data).get('Humidity');
interrupted = False
def signal_handler(signal, frame):
global interrupted
interrupted = True
def interrupt_callback():
global interrupted
return interrupted
# 回撥函數,語音識別在這裡實現,修改也是在這裡
def callbacks():
global detector
time.sleep(0.2)
your_text=['哎,我在,你說','我來啦,我來啦,我來啦~','我是你的語音助手小貝']
a=random.randint(1,3)
print('小貝'+your_text[a])
play('huda/xiaobeihuida'+ str(a) +'.wav') # 為喚醒詞事先準備好的回答
time.sleep(0.2)
try:
a = get_text()
if a =='嗯' or '':
pass
else:
print('你:'+a)
if '前進' in a:
controldata={'control':'goon'}
control=json.dumps(controldata)
ser.writ(control)
b='前進'
elif '後退' in a:
controldata={'control':'goback'}
control=json.dumps(controldata)
ser.writ(control)
b='後退'
elif '左轉' in a:
controldata={'control':'ternleft'}
control=json.dumps(controldata)
ser.writ(control)
b='左轉'
elif '右轉' in a:
controldata={'control':'ternright'}
control=json.dumps(controldata)
ser.writ(control)
b='右轉'
elif '原地左轉圈' in a:
controldata={'control':'turnternleft'}
control=json.dumps(controldata)
ser.writ(control)
b='原地左轉圈'
elif '原地右轉圈' in a:
controldata={'control':'turnternright'}
control=json.dumps(controldata)
ser.writ(control)
b='原地右轉圈'
elif '停止' in a:
controldata={'control':'stop'}
control=json.dumps(controldata)
ser.writ(control)
b='停止'
elif '室內溫度' in a:
b='當前室內溫度為'+str(Tempeature)+'攝氏度'
elif '室內溼度' in a:
b='當前室內溼度為百分之'+str(Humidity)
else:
b =get_chat_text(a)
print('小貝:'+b)
c = get_voice(b)
play(c)
except Exception:
print('小貝:我沒聽清楚,請重新說一下')
c = get_voice('我沒聽清楚,請重新說一下')
play(c)
@contextmanager
def no_alsa_error():
try:
asound = cdll.LoadLibrary('libasound.so')
asound.snd_lib_error_set_handler(c_error_handler)
yield
asound.snd_lib_error_set_handler(None)
except:
yield
pass
def wake_up():
global detector
model = 'xiaobeixiaobei.pmdl' # 我的喚醒詞為 小貝小貝
# 終止方法為ctrl+c
signal.signal(signal.SIGINT, signal_handler)
# 喚醒詞檢測函數,調整sensitivity引數可修改喚醒詞檢測的準確性
detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
print('正在聆聽... 請說喚醒詞:小貝小貝')
# main loop
# 回撥函數 detected_callback=snowboydecoder.play_audio_file
# 修改回撥函數可實現我們想要的功能
detector.start(detected_callback=callbacks, # 自定義回撥函數
interrupt_check=interrupt_callback,
sleep_time=0.03)
# 釋放資源
detector.terminate()
#程式入口
if __name__ == "__main__":
thread = threading.Thread(target=recv,args=(ser,))
thread.start()
wake_up()