Jawaban:
Jawaban singkatnya: Anda TIDAK BISA andal membaca PWM di Raspberry Pi.
Membaca PWM membutuhkan ketelitian mikrodetik (kecuali jika Anda membaca PWM yang sangat-sangat lambat), dan itu tidak tersedia pada Raspberry Pi untuk perangkat lunak userland tanpa bermain-main dengan modul kernel.
Cara termudah untuk menangkap PWM adalah dengan mendapatkan mikrokontroler murah (<$ 0,5) dengan serial atau I 2 C output dan menghubungkannya ke Raspberry Pi Anda dan membaca nilai aktual dari mikrokontroler. Ini akan bekerja dengan sangat andal dan cukup tepat.
Saya dapat melakukan pengukuran lebar pulsa yang cukup akurat menggunakan pustaka piGpio C: http://abyz.me.uk/rpi/pigpio/index.html
Pustaka ini memungkinkan Anda untuk menginstal fungsi panggilan balik yang akan memicu pada setiap transisi tepi pada pin gpio dan memberi Anda cap waktu tingkat mikrodetik untuk setiap transisi. Jangan berpikir Anda bisa mengandalkan ini untuk akurasi mikrodetik - tetapi pengujian saya menunjukkan bahwa akurasi setidaknya +/- 10 us, mungkin lebih baik.
Jauh lebih baik daripada menjalankan loop sibuk polling gpio untuk tingkat ubah sendiri.
Ini adalah pertanyaan yang menarik dan salah satu yang Anda anggap benar dalam mengatakan Google Search tidak memberikan solusi yang jelas! (Saya merindukan hari-hari ketika Google dapat menjawab apa pun yang ingin saya ketahui untuk pendidikan / tugas saya dalam hitungan detik.)
Saya berasumsi Anda memahami prinsip-prinsip PWM . Karena itu, saya tidak akan membahasnya. Namun, saya percaya Anda secara teori bisa membaca nilai PWM pada pin input digital biasa dengan beberapa pengkodean yang cerdas.
Saya akui saya belum mencoba ini sendiri, tetapi Anda harus dapat mengukur waktu pin tinggi dan waktu rendah (memberi Anda bacaan PWM) dan kemudian menggunakan rumus matematika apa pun yang disediakan oleh pemasok sensor. untuk mengubah ini menjadi bacaan yang sebenarnya.
Metode ini bekerja untuk saya pada masalah yang sama di mana saya perlu membaca panjang pulsa dari modul ultrasonik dan kemudian mengubahnya menjadi jarak. Masalah yang bisa saya bayangkan adalah memastikan pembacaan yang andal!
Jika Anda pikir itu akan membantu dan ingin melihat kode yang saya gunakan untuk modul ultrasonik katakan saja, dan saya akan menyalinnya ketika saya pulang.
Saya mulai menyalin kode tetapi karena suatu alasan situs web hanya memperbolehkan saya menyalinnya sebagian kecil saja (dan saya terlalu malas untuk mengeluarkan pi saya dari garasi) jadi di sini ada tautannya. abaikan sebagian besar fungsi di bagian bawah karena terkait dengan penggunaan modul sebagai sensor kedekatan. http://pibot.webnode.com/products/ultrasonic-range-sensor/
Jawaban panjangnya: Anda benar-benar bisa! (baik dengan sedikit bantuan dari teman-teman kita resistor dan kapasitor)
Anda dapat mengonversi output PWM ke level tegangan analog, (DAC) dan membacanya dengan pin ADC pada pi raspberry Anda.
Yang Anda butuhkan adalah resistor 4k7 dan kapasitor 0.1uF:
mensimulasikan rangkaian ini - Skema dibuat menggunakan CircuitLab
Filter low-pass RC sederhana di atas mengubah sinyal PWM ke tegangan yang sebanding dengan siklus kerja yang dapat dibaca oleh raspberry pi Anda sebagai nilai analog.
Jika Anda senang dengan respons yang lambat, Anda dapat membaca PWM cepat dengan undersampling. Cukup baca GPIO dalam satu lingkaran dan terapkan filter low pass. Probabilitas membaca 1 setiap siklus sebanding dengan lebar pulsa. Filter low pass IIR yang mudah diterapkan adalah:
double acc=0.5;
const double k=0.01;
for(;;) {
bool x=GPIO.read();
acc+=k*(x?1:0-acc);
}
Saat k menurun, resolusi meningkat tetapi bandwidth berkurang.
Meskipun jawaban saya bukan dari pin, Anda dapat menggunakan sesuatu berdasarkan Oscilloscope Kartu Suara untuk membaca input berdenyut.
Orang-orang telah menggunakan Kartu Suara di PC desktop selama bertahun-tahun untuk membuat osiloskop. Tampaknya dengan kartu suara internal modern Anda bisa mendapatkan hasil yang dapat digunakan hingga 10kHz. Dengan Kartu Suara yang terhubung dengan Raspberry Pi USB, frekuensi maks Anda mungkin lebih rendah.
Berikut adalah contoh dari satu proyek Oscilloscope Kartu Suara untuk Linux: http://www.yann.com/en/diy-turn-your-gnulinux-computer-into-a-free-oscilloscope-29/09/2010.html
Skrip python yang saya tulis ini berfungsi dengan baik bagi saya untuk membaca sinyal PWM dari RC Receiver. Sinyal PWM frekuensi tinggi jelas tidak akan berfungsi seperti yang telah ditunjukkan.
Saya langsung menghubungkan sepuluh pin sinyal keluar dari penerima RC ke pin Raspberry GPIO. Penerima ini ditenagai oleh pin + 5V dan GND dari RPI.
Saya menyederhanakan skrip karena ia melakukan banyak hal lain, jika Anda menemukan kesalahan atau sisa, beri tahu saya
import RPi.GPIO as GPIO
import time
import numpy as np
inPINS = [2,3,4,14,15,18,17,27,22,23]
smoothingWindowLength=4
def getTimex():
return time.time()
GPIO.setup(inPINS, GPIO.IN)
upTimes = [[0] for i in range(len(inPINS))]
downTimes = [[0] for i in range(len(inPINS))]
deltaTimes = [[0] for i in range(len(inPINS))]
def my_callback1(channel):
i = inPINS.index(channel)
v = GPIO.input(inPINS[i])
#GPIO.output(outPINS[0], v) # mirror input state to output state directly (forward servo value only) - don't set PWM then for this pin
if (v==0):
downTimes[i].append(getTimex())
if len(downTimes[i])>smoothingWindowLength: del downTimes[i][0]
else:
upTimes[i].append(getTimex())
if len(upTimes[i])>smoothingWindowLength: del upTimes[i][0]
deltaTimes[i].append( (downTimes[i][-1]-upTimes[i][-2])/(upTimes[i][-1]-downTimes[i][-1]) )
if len(deltaTimes[i])>smoothingWindowLength: del deltaTimes[i][0]
GPIO.add_event_detect(inPINS[0], GPIO.BOTH, callback=my_callback1)
GPIO.add_event_detect(inPINS[1], GPIO.BOTH, callback=my_callback1)
try:
while True:
ovl = deltaTimes[0][-smoothingWindowLength:] # output first pin PWM
ov = sorted(ovl)[len(ovl) // 2] #ov = np.mean(ovl)
print ov
time.sleep(0.1)
except KeyboardInterrupt:
GPIO.cleanup()
Sangat mungkin dan relatif mudah untuk membaca input PWM di Raspberry Pi menggunakan perpustakaan pigpio C. Jika Anda ingin kinerja yang baik saya sarankan menggunakan C, bukan Python. Saya telah memberikan beberapa kode contoh singkat di bawah ini. Berlawanan dengan apa yang dikatakan beberapa orang, ini memiliki kinerja pengaturan waktu yang sangat baik dan jitter yang cukup rendah. Bacaan secara konsisten dalam 5 us pada RPi 3 B saya dan dapat mengukur pulsa sesingkat 5 us. Perhatikan bahwa kode yang disediakan adalah bukti konsep saja, ia tidak menangani dengan benar tidak adanya pulsa (siklus tugas 0% / 100%) atau sampul 'tick' yang terjadi setiap 72 menit. Program ini berjalan dengan baik dalam mode pengguna tetapi untuk ketahanan terbaik terhadap gangguan waktu menjalankan program Anda pada tingkat negatif baik seperti ini: sudo nice -n -20 ./program
Lihat dokumentasi pigpio di: http://abyz.me.uk/rpi/pigpio/pdif2.html
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include "pigpiod_if2.h"
static uint32_t rise_tick = 0; // Pulse rise time tick value
static uint32_t pulse_width = 0; // Last measured pulse width (us)
// Callback function for measuring PWM input
void pwm_cbfunc(int pi, unsigned user_gpio, unsigned level, uint32_t tick) {
if (level == 1) { // rising edge
rise_tick = tick;
}
else if (level == 0) { // falling edge
pulse_width = tick - rise_tick; // TODO: Handle 72 min wrap-around
}
}
int main(int argc, char **argv)
{
const unsigned int pwm_in = 23; // GPIO Pin # for PWM in, change as reqd
int pi = pigpio_start(0, 0);
if (pi < 0) {
fprintf(stderr, "pigpio initialization failed (%d)\n", pi);
return pi;
}
// Set up callback for PWM input
callback(pi, pwm_in, EITHER_EDGE, pwm_cbfunc);
while (true) {
printf("PWM pulse width: %u\n", pulse_width);
usleep(500000);
}
}
Solusi mudah dengan akurasi tinggi:
Menggunakan Arduino sebagai perangkat iic slave atau UART tampaknya berfungsi dengan baik. Microcontoller mampu membaca informasi melalui metode pulseIn.
Informasi detail kedepan: https://www.youtube.com/watch?v=ncBDvcbY1l4