python轉arduino 超音波感測 問題求解~~~
本帖最後由 albert000789 於 2018-12-13 19:01 編輯這幾天在研究python透過firmata協定在arduino上操作感測器,編譯成功後python數值不正確,這下面為我打的code,麻煩大大指點找錯了!
import pyfirmata
import time
board = pyfirmata.Arduino("/dev/ttyACM0")
trigger = board.get_pin("d:10:o")
echo = board.get_pin("d:9:i")
it = pyfirmata.util.Iterator(board)
it.start()
echo.enable_reporting()
def send_trigger_pulse():
trigger.write(1)
time.sleep(0.001)
trigger.write(0)
def wait_for_echo(value,count):
while echo.read() !=value and count>0:
count=count-1
def get_distance():
send_trigger_pulse()
wait_for_echo(True,5000)
start = time.time()
wait_for_echo(False,5000)
finish = time.time()
pulse_len = finish-start
distance_cm = pulse_len*340*100/2
distance_in = distance_cm/2.5
return(distance_cm,distance_in)
while True:
print("cm=%f\tinches=%f" % get_distance())
time.sleep(1)
firmata 是用 UART 互連的
速度是 57600bps,
也就是就算來回只送一個byte, 也要花約 250us
更何況firmata的協定還不止傳一個byte
用這麼慢的速度去量測音波的來回(1cm 約 60us)
一定會不準的
超新手 發表於 2018-12-14 19:55
firmata 是用 UART 互連的
速度是 57600bps,
也就是就算來回只送一個byte, 也要花約 250us
另外請問有什麼方法可以解決感測器在arduino但是遙控車程式在python上,因為未來需要用到避障功能,不知道二者該如何互通?
目前我可以把arduino上的數據顯示在python上,但是怎麼把那些文字的數據(字串)弄成可以來寫if的讀取值(數值)嗎?因為一些原因我們的感測器必須裝在arduino上,但是遙控車移動的程式碼必須寫在python上 本帖最後由 超新手 於 2018-12-15 16:06 編輯
1)一定要在Arduino 偵測完超音波, 再把值讀回, 值才會準
所以最簡單的方法就是去改寫 Firmata 的程式
例如用你的超音波程式去取代原來讀A/D 的程式
這樣你就可以用Firmata的架構, 不用大改
原本 arduino Firmata讀a/d的程式
Firmata.sendAnalog(analogPin, analogRead(analogPin));
改成
if(analogPin == A0){
// 以下是隨便寫
digitalWrite(Trig, HIGH);
delayMicroseconds(10);
digitalWrite(Trig, LOW);
pulse_len = pulsein(ECH, HIGH, 1000);
Firmata.sendAnalog(analogPin, pulse_len);
} else {
Firmata.sendAnalog(analogPin, analogRead(analogPin));
}
2)上傳的數值不是本來就可以用 if 了嗎
v = get_distance()
if v >= 10:
if v == 100:
3) 那個 %....確定不是寫錯嗎?
print("cm=%f\tinches=%f" % get_distance())
超新手 發表於 2018-12-15 16:05
1)一定要在Arduino 偵測完超音波, 再把值讀回, 值才會準
所以最簡單的方法就是去改寫 Firmata 的程式
例如 ...
我們在arduino上執行超音波程式,然後用python去讀他的序列埠,我們要的是能夠去判斷由這個序列埠讀出來的值
我們的code無法做出判斷(使用if)怎麼把這些字串轉換成數值,拜託大大了><
import serial
ser=serial.Serial('/dev/ttyACM0',9600,timeout=0.25)
try:
while 1:
response = ser.readline()
print(response)
except KeyboardInterrupt:
ser.close()
if response<100:
print("Quit")
response = ser.readline()
a=int(response)
if a <100:
print("Quit")
試試看 本帖最後由 albert000789 於 2018-12-17 21:57 編輯
超新手 發表於 2018-12-17 19:48
response = ser.readline()
a=int(response)
if a
b'6cm\r\n'我們之前跑出來的結果是長這樣,不是純數字
加上a=int(response)之後就出現 ValueError: invalid literal for int() with base 10: b'6cm\r\n'
該怎麼解決 TT,下面是我們arduino上的code,不知道是不是要改這裡的程式
const byte trigPin = 10;
const int echoPin = 9;
unsigned long d;
unsigned long ping(){
digitalWrite(trigPin,HIGH);
delayMicroseconds(10);
digitalWrite(trigPin,LOW);
return pulseIn(echoPin,HIGH);
}
void setup(){
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
Serial.begin(9600);
}
void loop(){
d=ping()/58;
Serial.print(d);
Serial.print("cm");
Serial.println();
delay(250);
}
把
Serial.print(d);
Serial.print("cm");
Serial.println();
改成
Serial.println(d);
頁:
[1]