質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Q&A

解決済

2回答

3886閲覧

RaspberryPiのGPIOでパルス幅の短いパルスを読み取る方法

megaman

総合スコア5

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

0グッド

0クリップ

投稿2020/01/26 07:33

編集2020/01/26 10:31

前提・実現したいこと

RaspberryPiのGPIO でパルスを受け取り、コールバック関数(gpioSetAlertFunc)を用いてカウントするプログラムを作成しています。
使用言語は C++、使用ライブラリは pigpio です。

発生している問題・エラーメッセージ

ここで問題が起こっています。
コールバック関数(gpioSetAlertFunc)のサンプリングレートはデフォルトで5μ秒であるのに対して、
GPIO に入力されるパルスの幅は600nsであり、読み落としてしまう事が予想されます。

600nsのパルス幅のパルスを読み取れるようにサンプリングレートを設定する、もしくは他の関数で読み取りを実現できる方法はないでしょうか。

私自身も探しましたが解決策を見つける事ができませんでした。
どなたか知っている方がいらっしゃいましたらご教授願います。

GPIO1,GPIO2でEVENT,OVERFLOWの2つの割り込みに待機して、割り込みが発生したらそれぞれのカウントを増やします。
また、EVENT割り込みが発生した際はGPIO3からGPIO10より、2進数8bitのデータを読み込み、表示します。

c++

1#include <stdio.h> 2#include <stdlib.h> 3#include <pigpio.h> 4#include <unistd.h> 5#include <time.h> 6#include <string> 7#define locate(x,y) printf("\033[%d;%dH",x,y) 8#define clr printf("\033[2J") 9 10 11unsigned long EventPulse = 0x00000000; 12int ETCounter[256]; 13int OverFlow; 14int Event; 15char date[64]; 16unsigned char num = 0x00; 17int ret1; 18int ret2; 19 20// callback1 21void CallbackEvent(int GPIO, int level, uint32_t tick){ 22 char buffer[50]; 23 sprintf(buffer,"%d%d%d%d%d%d%d%d",gpioRead(3),gpioRead(4),gpioRead(5),gpioRead(6),gpioRead(7),gpioRead(8),gpioRead(9),gpioRead(10)); 24 int num=strtol(buffer,NULL,2); 25 ETCounter[num]++; 26 Event++; 27 28 29 locate(9,1); 30 for(int i=0;i<=255;i=i+16){ 31 for(int j=0;j<=15;j++){ 32 printf("%4d",ETCounter[i+j]); 33 } 34 printf("\n"); 35 } 36 //Event 37 locate(26,4); 38 printf("Event : %d",Event); 39 40} 41 42//callback2 43void CallbackOverFlow(int GPIO, int level, uint32_t tick){ 44 OverFlow++; 45 46 47 //OverFlow 48 locate(28,4); 49 printf("OverFlow : %d",OverFlow); 50 51 52} 53 54 55 56 57//main 58int main(){ 59 60 if(gpioInitialise()<0){ 61 return 1; 62 } 63 gpioSetMode(1,PI_INPUT); 64 gpioSetMode(2,PI_INPUT); 65 gpioSetMode(3,PI_INPUT); 66 gpioSetMode(4,PI_INPUT); 67 gpioSetMode(5,PI_INPUT); 68 gpioSetMode(6,PI_INPUT); 69 gpioSetMode(7,PI_INPUT); 70 gpioSetMode(8,PI_INPUT); 71 gpioSetMode(9,PI_INPUT); 72 gpioSetMode(10,PI_INPUT); 73 74 gpioSetPullUpDown(1,PI_PUD_DOWN); 75 gpioSetPullUpDown(2,PI_PUD_DOWN); 76 77 78 callback1=gpioSetAlertFunc(1,CallbackEvent); 79 callback2=gpioSetAlertFunc(2,CallbackOverFlow); 80 81 while(1){ 82 83 84 clr; 85 locate(30,5); 86 printf("A : END OBSERVATION"); 87 //Counter 88 locate(9,1); 89 for(int i=0;i<=255;i=i+16){ 90 for(int j=0;j<=15;j++){ 91 printf("%4d",ETCounter[i+j]); 92 } 93 printf("\n"); 94 } 95 //Event 96 locate(26,4); 97 printf("Event : %d",Event); 98 //OverFlow 99 locate(28,4); 100 printf("OverFlow : %d",OverFlow); 101 //GetTime 102 locate(5,3); 103 time_t t = time(NULL); 104 strftime(date, sizeof(date), "%Y %m %d %H %M %S", localtime(&t)); 105 printf("STARTTIME = %s\n\n", date); 106 107 int a=getchar(); 108 if(a =='A'){ 109 110 locate(30,5); 111 printf("A : END OBSERVATION"); 112 //Counter 113 locate(9,1); 114 for(int i=0;i<=255;i=i+16){ 115 for(int j=0;j<=15;j++){ 116 printf("%4d",ETCounter[i+j]); 117 } 118 printf("\n"); 119 } 120 //Event 121 locate(26,4); 122 printf("Event : %d",Event); 123 //OverFlow 124 locate(28,4); 125 printf("OverFlow : %d",OverFlow); 126 //GetTime 127 locate(6,3); 128 time_t t = time(NULL); 129 strftime(date, sizeof(date), "%Y %m %d %H %M %S", localtime(&t)); 130 printf("ENDTIME = %s\n\n", date); 131 } 132 gpioTerminate(); 133 return 0; 134 } 135} 136 137 138 139 140 141

変更不可な部分
・RaspberryPi
・C++
・パルス幅600ns

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

割り込みかけたいならgpioSetISRFunc()です。

投稿2020/01/26 10:37

ozwk

総合スコア13528

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

megaman

2020/01/26 11:23

回答ありがとうございます。 gpioSetAlertFunc→gpioSetISRFunc(gpio番号,RISING_EDGE,0,コールバックする関数) に変更し、実行してみましたが、割り込みが発生しません。 第3引数はタイムアウト を発生させないために0に設定しました。 他にも変更すべき点がもしございましたら教えていただきたいです。 この関数に関しましてもパルス幅に関する記述を見つける事ができませんでした。
ozwk

2020/01/26 12:45 編集

スイッチなりジャンパー線なりでピンを操作して割り込みが発生しますか?(つまり、長いパルスであれば割り込みが発生しますか?) 出力するパルスが鈍ってませんか? 出力パルスの電圧レベルはラズパイのgpioと合っていますか? パルスは本当に出力されていますか?
megaman

2020/01/26 13:33

回答ありがとうございます。 指示を頂いた項目をチェックしているうちに一つ疑問点が浮かんだので検証しました。 今回パルスを発生させる装置の動作電圧は5Vで、RaspberryPiのGPIO から給電していました。 しっかり5V出力できているか確認したところ、5V出力できておりませんでした。 そこでACアダプターを交換し再度確認したところ、5V出力を確認し、また問題点であったイベント割り込みの発生も確認する事ができました。ありがとうございます。 つまり、今回の問題はコードの内容ではなく、ハード面の不備にありました。 ozwk様のような視点で物事を検証できるよう精進します。 改めてありがとうございました。
guest

0

GPIOとして読むなら、そのパルスを確実に読む方法はありません
そのパルスが来たということを知るだけなら、割り込み入力としてGPIOを設定し、割り込みが発生したかどうかでパルスの有無を判定できます

それが可能なのか、どのピンが割り込み入力に出来るか、は別途調べましょう

投稿2020/01/26 07:40

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

megaman

2020/01/26 10:27

コメントありがとうございます。 今回GPIOに入力されるパルスのパルス幅が600nsと決まっているので、サンプリングレートを600nsよりも小さくする事で確実に割り込み入力する事ができるのではないかと考えていました。 誤解を生むような質問をしてしまい、大変申し訳ありません。 コードを追記しましたので、ご覧になっていただけると幸いです。
y_waiwai

2020/01/26 13:30

サンプリングレートをその周期より小さく出来るなら、取りこぼすことはありません。 で、現状はどうなのでしょうか。 ラズパイをベアメタルでプログラムしている、というのであれば、600ns以下の周期でサンプリングするのも可能でしょう。それを検出するのになんの障害もありません。 で、現状はどうなの?(二回目
megaman

2020/01/26 13:47

現状はgpioSetAlertFunc()のデフォルトのサンプリングレート5μsで実装しております。 疑問はサンプリングレートを600nsよりも小さくする方法はあるか。という事でした。 たびたび申し訳ありませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問