Raspberry PiのPWM入力


10

Raspberry PiのピンからPWM信号を読み取る方法はありますか?

グーグルで試しましたが、PWM 出力だけが見つかり、入力は見つかりませんでした。

回答:


4

短い答え:Raspberry PiでPWMを確実に読み取ることはできません。

PWMの読み取りにはマイクロ秒の精度が必要です(非常に遅いPWMを読み取っている場合を除く)。これは、カーネルモジュールをいじらないと、ユーザーランドソフトウェアのRaspberry Piでは利用できません。

PWMをキャプチャする最も簡単な方法は、シリアルまたはI 2 C出力を備えた安価な(<0.5ドル)マイクロコントローラーを入手し、それをRaspberry Piに接続して、マイクロコントローラーから実際の値を読み取ることです。これは非常に確実に機能し、非常に正確です。


1
そのようなICをどこで手に入れればいいですか?
Pepijn、2015年

@Pepijnが探しているのは、A / Dコンバーター(ADC)です。私が非常に頻繁に使用する非常に一般的なものは、MCP3008 8チャネル、10ビットユニットです。また、PerlソフトウェアのPiをユニットテストで永続的に使用しているものは、ADS1115 4チャネル、16ビットユニットです。後者は少しはんだ付け作業が必要ですが、前者は必要ありません。これらのユニット(C、Python、Perlなど)の両方を使用するためのコード例は多数あります。そのため、独自のコードを作成したくない、または作成できない場合は、簡単に始めることができます。
stevieb 2017

どんな単純なマイクロコントローラーでも十分です。私はこの種のものにマイクロチップ製品を使用していました。Arduinoの登場により、AVRチップが再び人気を博しました。今は、マイクロコントローラーとチップが必要とするあらゆる生命維持装置を含む小さなブレークアウトボードを使用しています。私のお気に入りは、Teensy 3.xシリーズです。
NomadMaker 2018

3

私はpiGpio Cライブラリを使用して、かなり正確なパルス幅測定を行うことができます。 http://abyz.me.uk/rpi/pigpio/index.html

このライブラリを使用すると、gpioピンのエッジ遷移でトリガーされるコールバック関数をインストールし、各遷移のマイクロ秒レベルのタイムスタンプを取得できます。マイクロ秒の精度でこれを当てにできるとは思わないでください。ただし、私のテストでは、精度は少なくとも+/- 10usであり、おそらくそれより優れていることが示唆されています。

レベルの変更を自分でgpioにポーリングするビジーループを実行するよりもはるかに優れています。


+1精度はCPU負荷(特にシングルコア)に基づいて多少異なる場合があることに注意してください。:)
Jacobm001

stevec氏に感謝します。この答えは、「それができない」と言うよりもはるかに優れています。実際のコード(非常に短い)を含む詳細については、別の回答を参照してください。
ジョージー

2

これは興味深い質問であり、Google検索は明確な解決策を提供していないとあなたが正解している質問です。(私がGoogleが私の教育/課題について知りたいすべてのことを数秒で答えることができた日を逃しています。)

PWMの原理を理解していると思います。したがって、私はそれについては触れません。ただし、理論上は、通常のデジタル入力ピンのPWM値を巧妙なコーディングで読み取ることができると思います。

私はこれを自分で試したことはありませんが、ピンが高い時間と低い時間を測定し(PWMの読み取り値を与える)、センサーのサプライヤーが提供する数式を使用できるはずですこれを実際の読み値に変換します。

この方法は、超音波モジュールからパルス長を読み取り、それを距離に変換する必要がある同様の問題で私に役立ちます。私が想定できる問題は、信頼できる測定値を確実にすることです!

あなたがそれが役立つと思い、超音波モジュールに使用したコードを確認したい場合は、そのように言ってください。帰宅したらコピーします。

私はコードのコピーを開始しましたが、何らかの理由で、ウェブサイトは一度に小さなセクションしかコピーできません(そして私はガレージからpiを取り出すのが面倒なので)ここへのリンクです。モジュールを近接センサーとして使用することに関連しているため、下部にあるほとんどの機能は無視してください。http://pibot.webnode.com/products/ultrasonic-range-sensor/


それはコードを見るのに良いでしょう、それで私が自分のコードを始めるためのベースを手に入れることができます、ここに貼り付けることができれば私は非常に感謝しています^^
Caio Keto

この提案の問題は、Linuxカーネルが典型的なRC PWMデューティサイクル(通常16ミリ秒ごとに1000〜2000マイクロ秒)を十分な精度で読み取るための十分なタイミングを提供しないことです。カーネルモジュールでGPIOピンの変更用の割り込みハンドラーをインストールし、高/低遷移のタイムスタンプをキャプチャできる場合、これは便利なソリューションになる可能性があります。
Jon Watte 2017

1

長い答え:実際にできます!(まあ私たちの友人の抵抗器とコンデンサーから少し助けて)

PWM出力をアナログ電圧レベル(DAC)に変換し、ラズベリーパイのADCピンで読み取ることができます。

必要なのは、4k7の抵抗と0.1uFのコンデンサです。

概略図

この回路のシミュレーションCircuitLabを使用して作成された回路

上記のシンプルなRCローパスフィルターは、PWM信号をデューティサイクルに比例する電圧に変換します。これは、ラズベリーパイでアナログ値として読み取ることができます。


4
ADCピン?そして、それはどちらでしょうか?
ガニマ

@Ghanimaさて、新しいMicrosoft Lightningドライバーは開発中ですが、この目的を十分に果たします(ページに記載されています)。私はBCM2837のために見つけた何それは... GPIO0(悲しいことに、この1は、任意のヘッダーピンにリンクされていない)上にあるハードウェアのADCを持っている可能性があるために、少なくとも彼らは、ハードウェアのPWMチャネルリンク
クエストを

0

遅い応答に満足している場合は、アンダーサンプリングによって高速PWMを読み取ることができます。GPIOをループで読み取り、ローパスフィルターを適用するだけです。各サイクルで1を読み取る確率は、パルス幅に比例します。IIRローパスフィルターの実装は簡単です。

double acc=0.5;
const double k=0.01;
for(;;) {
  bool x=GPIO.read();
  acc+=k*(x?1:0-acc);
}

kが減少すると、分解能は向上しますが、帯域幅は減少します。


0

私の答えはピンからではありませんが、サウンドカードオシロスコープに基づくものを使用して、パルス入力を読み取ることができます。

人々は何年もデスクトップPCでサウンドカードを使用してオシロスコープを作成しています。最新の内蔵サウンドカードを使用すると、10kHzまで使用可能な結果が得られるようです。Raspberry Pi USB接続のサウンドカードを使用すると、最大周波数が低くなる可能性があります。

Linux用のサウンドカードオシロスコーププロジェクトの例を以下に示します。http//www.yann.com/en/diy-turn-your-gnulinux-computer-into-a-free-oscilloscope-29/09/2010.html


0

私が書いたこのPythonスクリプトは、RCレシーバーのPWM信号を読み取るのに適しています。すでに指摘したように、高周波PWM信号は明らかに機能しません。

RCレシーバーの10本の信号出力ピンをRaspberry GPIOピンに直接接続しました。レシーバは、RPIからの+ 5VおよびGNDピンによって給電されます。

他の多くのことを行うため、スクリプトを簡略化しました。間違いや残り物を見つけた場合は、お知らせください

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()

0

Raspberry PiのPWM入力を、pigpio Cライブラリを使用して読み取ることは非常に可能で、比較的簡単です。優れたパフォーマンスが必要な場合は、PythonではなくCを使用することをお勧めします。以下の短いサンプルコードを提供しました。一部の人が言うところとは対照的に、これは優れたタイミングパフォーマンスと非常に低いジッターを備えています。読み取り値はRPi 3 Bで一貫して5 us以内であり、5 usほどの短いパルスを測定できます。提供されたコードは概念実証のみであり、パルスの欠如(0%/ 100%デューティサイクル)または72分ごとに発生する「ティック」ラップアラウンドを適切に処理しないことに注意してください。プログラムはユーザーモードで問題なく実行されますが、タイミンググリッチへの抵抗を最大にするには、プログラムを次のような負のniceレベルで実行します。sudo nice -n -20 ./program

http://abyz.me.uk/rpi/pigpio/pdif2.htmlにあるpigpioのドキュメントを参照してください。

#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);
    }
}

-3

高精度の簡単なソリューション:

ArduinoをiicスレーブまたはUARTデバイスとして使用すると、問題なく動作するようです。マイクロコントローラーは、pulseInメソッドを介して情報を読み取ることができます。

詳細情報:https : //www.youtube.com/watch?v=ncBDvcbY1l4


ラズベリーパイへようこそ!これは理論的には質問に答える可能性がありますが、答えの本質的な部分をここに含め、参照用のリンクを提供することが望ましいでしょう。ここでは、情報なしのリンクのみの回答に関する新しいポリシーを試みています。この投稿が編集されて回答として成り立つ情報が含まれていない場合、最低でも48時間以内にコミュニティWikiに変換され、コミュニティによる修正が簡単になります。
ガニマ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.