こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

PICのA/Dを使うプログラムについて質問です

今、電子ドラムを作っているのですが、プログラムが上手く作動せず困っています。
知恵を貸していただけたら幸いです。
センサー部が叩かれると電圧が上昇するようにしてあるのですが、PICでHighと認識されるほど電圧が上がらないので、A/D変換を使い入力を判定しているのですが、2つ以上の入力のプログラムが上手く行きません。
Pinごとに順番にA/D変換し、一定値以上なら変数にpinごとに割り振った2進数を加算し、入力pinすべての判定が終わったときの変数の値別にswitch文で出力を変え、70ms出力するようなプログラムをつくりました。
入力が1pinだけの同様のプログラムは動くのですが、入力を複数にすると動きません。
このように複数のA/D変換をほぼ同時にする方法は無いでしょうか?
デバイスは16F877/20-SP
言語はCでCCS-Cコンパイラーを使っています。
回答よろしくお願い致します。

投稿日時 - 2007-09-17 23:52:57

QNo.3354498

すぐに回答ほしいです

質問者が選んだベストアンサー

コードを見ましたが、大問題があります。
(1)whileの条件
mainのwhile(0)←これだとループしません。これで反応がなかったのかも知れません。正しく書くならwhile(1)です。
それとint channel;の定義がないですが、エラーになりませんでした?
(2)judgeのoutput
outputが初期化されていませんので、ボタンが押されなかったときに不定値になります。if(value >=380)のelseで必ず0を入れてください。

あとコードが長いのでシンプルにする方法も教えます。
int ch;←先頭で定義をお願いします。
{略}
//アナログチャンネルの処理。
out = 0;
for( ch=0 ; ch<8 ; ch++ ) {←ループで処理します。
set_adc_channel(ch);
out |= judge(ch);←加算ではなく、OR演算が望ましいです。
}
{略}

int judge(int channel)
{
int output;
delay_us(60);
value = read_adc();
if(value >=380)
{
output = 1 << channel;←この場合、シフト演算でswitch文でやりたかったことと同じことができます。
} else {
output = 0;←ボタンが押されなかったら0。
}
return output;
}
//

投稿日時 - 2007-09-19 19:07:48

お礼

ありがとうございます。

投稿日時 - 2009-05-11 00:32:45

ANo.4

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.3

zwi

AD変換のプログラムは、
set_adc_channel(0);
delay_us(60);
an0 = read_adc();
set_adc_channel(1);
delay_us(60);
an1 = read_adc();
といった感じで大丈夫なはずです。
これとは違う書き方のプログラムでしょうか?

>AN0に入力したときにAN1の設定のdelayが入ってて駄目なのだと思うのですがどうでしょうか?
サンプルホールドキャパシタの蓄積時間ことを言っているならdelay_us(60);もやっていてダメな理由は分かりません。
何らかのディレイが必要と感じるなら試しに入れてみてはどうでしょうか?

残念ながら回路図とかプログラムコードを見ないと、これ以上は推測不能ですね。せめて肝心のAD変換部のプログラムコードのだけでも見たいです。

投稿日時 - 2007-09-18 14:34:59

お礼

回答ありがとうございます。
プログラムを抜粋しますと、こんな感じになってます。
int judge(int channel),
int main()
{
long out;
set_tris_a(63);
set_tris_e(7);
set_tris_c(0);
set_tris_d(0);
setup_adc_ports(all_analog);
setup_adc(ADC_CLOCK_DIV_32);
while(0)
{
port_c = 0;
port_d = 0;
out = 0;
set_adc_channel(0);
channel = 0;
out += judge(channel);
set_adc_channel(1);
channel = 1;
out += judge(channel);
set_adc_channel(2);
channel = 2;
out += judge(channel);
set_adc_channel(3);
channel = 3;
out += judge(channel);
set_adc_channel(4);
channel = 4;
out += judge(channel);
set_adc_channel(5);
channel = 5;
out += judge(channel);
set_adc_channel(6);
channel = 6;
out += judge(channel);
set_adc_channel(7);
channel = 7;
out += judge(channel);
      if(out > 0)
{
      switch()
{略}
delay_ms(70),
}
}
return 0,
}
int judge(int channel)
{
int output;
delay_us(60);
value = read_adc();
if(value >=380)
{
switch(channel)
{
case 0: output = 1 ;
break;
case 1: output = 2 ;
break;
case 2: output = 4 ;
break;
case 3: output = 8 ;
break;
case 4: output = 16 ;
break;
case 5: output = 3 2;
break ;
case 6: output = 64 ;
break;
case 7: output = 128;
break;
}
}
return output;
}

別の変数に値を保存しておいて、あとで判定したほうがいいですかね?

投稿日時 - 2007-09-19 18:19:54

ANo.2

zwi

複数入力のコンバートは可能です。
ADコンバータがちゃんと動かないとしたら次の2点が考えられます。
(1)サンプルホールドキャパシタの蓄積時間が不足。チャンネル切り替えごとに20マイクロ秒が必要です。
(2)ADCON1のPCFGの設定ミス。該当ピンがアナログ入力になっていない。
これがちゃんとしていて動かないとしたら、回路に問題があるか、プログラムにAD変換以外の問題があるかだと思います。

投稿日時 - 2007-09-18 09:09:47

お礼

チャンネル設定の後に
delay_us(60)いれてますし、
all_analogにしてあるので大丈夫だとは思うのですが、
私の予想としてはA/D変換での入力複数をループさせているので、AN0に入力したときにAN1の設定のdelayが入ってて駄目なのだと思うのですがどうでしょうか?

投稿日時 - 2007-09-18 12:52:09

ANo.1

トランジスタを使ってもっと昇圧すれば・・・

投稿日時 - 2007-09-18 00:30:40

お礼

回答ありがとうございます。
今回は後先考えずセンサー部を量産してしまっているのでプログラムでどうにかするしかなくて。
現在のセンサーはB級増幅回路のつもりが、何故か無信号時に0V、有信号時に3.5Vくらいまで上がるという回路なのですが…

投稿日時 - 2007-09-18 01:55:41

あなたにオススメの質問