• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C18 A/D変換 値の表示)

C18 A/D変換 値の表示

このQ&Aのポイント
  • 加速度センサから取得したデータ(x,y)を基に、傾きを知るためにプログラムを作成しました。
  • x,yの値は正常に表示できたのですが、計算結果outg1が上手く表示できませんでした。
  • アドバイスをお願いします。

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

  • ベストアンサー
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.4

見てみましたが気になるのが1~2つと、間違いが1箇所。 >ADCON2 = 0x36; ADFM=左詰 アクイジション時間=16Tad Tad=Tosc/64 #2の補足のソースコードなら16ビットで処理するので右詰めを指定してください。 あとは、TadのTOSCというのがマニュアルから何Mhzなのか探せなかったので問題ないか自信がありません。アクイジション時間を試しに増やしてもだめでしょうか? どうしても、うまく動かないならとりあえず8ビットで正常に動くようになってから再チャレンジしてみてはどうでしょう?8ビットが成功していたら16ビットもうまく動くはずなんですけどね。 >ADCON1 = 0x32; VREF AN2,AN3を使用。 すべてのアナログピンが有効。 問題ありません。ただし、VREFがAN2,AN3ピンで合っていての場合です。 >右詰でいいと思うのですが… そうです。16ビットなら右詰め。8ビットなら左詰めが正しいです。

-TaKaHiRo-
質問者

お礼

以下のプログラムで10bit精度でのA/D変換ができました。 ありがとうございました。 ------------------------------------------------------------------- int g1, g2, g3, g4; double outg1, outg2; //各レジスタの設定 ADCON1 = 0x32; TRISA = 0x2c; TRISF = 0x7C; ADCON2 = 0xB6; //AN4用 加速度センサA1 ADCON0 = 0x11; ADCON0bits.GO = 1; Delay10TCYx(0); while(ADCON0bits.GO); Delay10TCYx(0); g1 = (((int)ADRESH)<<8) + (int)ADRESL; itoa((int)g1, AN4String); //AN7用 加速度センサA2 ADCON0 = 0x1D; ADCON0bits.GO = 1; Delay10TCYx(0); while(ADCON0bits.GO); Delay10TCYx(0); g2 = (((int)ADRESH)<<8) + (int)ADRESL; itoa((int)g2, AN7String); //加速度センサA 傾き計算 出力 outg1 = atan2((double)g2, (double)g1); outg1 = (outg1*180.0f)/3.1415f; itoa((int)(outg1*100.0f), out_g1String); -------------------------------------------------------------------

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.3

>10bit精度で言われた方法で試したのですが、AN7Stirngが0となります。 >また、g1やg2を元に計算した結果も、0とか327567とかが表示されます。 値が変ですね。ちゃんとAD変換されていませんよ。 >(式は outg1 = sin((double)g2/(double)g1); にしました) sinですか?意味が不明なんですが? >気になることがあるのですが、ADCON2のADFM(変換データの格納方法)は、右詰、左詰、どちらにすればよいのでしょうか? >とりあえず、両方とも試したのですが、上の不具合は改善されませんでした。 ちゃんとマニュアルを読んで理解しましょう。 あえて答えを書きませんので、自分で考えてみてください。 後は、PIC18の型番とかクロック周波数とかの詳細の情報を聞いていませんのでADCONの設定が合っているのか判断できません。

-TaKaHiRo-
質問者

補足

>値が変ですね。ちゃんとAD変換されていませんよ。 変換方法に問題はないでしょうか? 8bitの時は、それらしきのが出ていたので… >ちゃんとマニュアルを読んで理解しましょう。 >あえて答えを書きませんので、自分で考えてみてください。 右詰でいいと思うのですが… >後は、PIC18の型番とかクロック周波数とかの詳細の情報を聞いていませんのでADCONの設定が合っているのか判断できません。PIC18F67J60-L/PT(40MHz) 動作クロックは、41.666MHz です。

全文を見る
すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

>単に8bitだけ取り出す(精度8bit)場合は、 >g1 = (double)ADRESH; >では駄目なのでしょうか? それでもOKです。精度がほしかったら g1 = (double)( ((int)ADRESH)<<8 + (int)ADRESL ); にすれば良いかと。 それよりも、 int ig1; (中略). ig1 = ((int)ADRESH)<<8 + (int)ADRESL; itoa(ig1, AN7String); (中略) outg1 = atan2((double)ig2,(double)ig1); とした方がプログラム効率が良く、実行速度も上がります。 なるべくdoubleを使わない。double⇔int間の型変換はできるだけ行わないのがPICでのプログラミングのコツです。

-TaKaHiRo-
質問者

補足

10bit精度で言われた方法で試したのですが、AN7Stirngが0となります。 また、g1やg2を元に計算した結果も、0とか327567とかが表示されます。 (式は outg1 = sin((double)g2/(double)g1); にしました) 気になることがあるのですが、ADCON2のADFM(変換データの格納方法)は、 右詰、左詰、どちらにすればよいのでしょうか? とりあえず、両方とも試したのですが、上の不具合は改善されませんでした。 改良後のソースを記載しておきます。 ------------------------------------------------------------------- int g1, g2, g3, g4; double outg1, outg2; //各レジスタの設定 ADCON1 = 0x32; TRISA = 0x2c; TRISF = 0x7C; // ADCON2 = 0xB6; ADCON2 = 0x36; //AN4用 加速度センサA1 ADCON0 = 0x11; ADCON0bits.GO = 1; while(ADCON0bits.GO); Delay10TCYx(0); g1 = ((int)ADRESH)<<8 + (int)ADRESL; itoa(g1, AN4String); // g1 = (double)ADRESH; // uitoa(*((WORD*)(&ADRESH)), AN4String); //AN7用 加速度センサA2 ADCON0 = 0x1D; ADCON0bits.GO = 1; while(ADCON0bits.GO); Delay10TCYx(0); g2 = ((int)ADRESH)<<8 + (int)ADRESL; itoa(g2, AN7String); // g2 = (double)ADRESH; // uitoa(*((WORD*)(&ADRESH)), AN7String); //加速度センサA 傾き計算 出力 outg1 = sin((double)g2/(double)g1); outg1 = (outg1*180.0f)/3.1415f; itoa((int)(outg1*100.0f), out_g1String); -------------------------------------------------------------------

全文を見る
すると、全ての回答が全文表示されます。
  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

ADRESLとADRESHを16bitデータとして読み込んでいますが、エンディアンは大丈夫ですか? MPLAB C18はデータ格納がリトルエンディアンだと説明書に書いてありますけど。 [資料よりコピペ] MPLAB C18 は"little-endian" フォーマットでデータを保存します。若い番地に下位バイトが保存されます。値を「下位を最初に」を基準に保存します。 データを読むときも同様なので、ADRESL,ADRESHの順番で並んでいないと駄目です。 outg1 = atan(g2/g1); これも前のやつ同様にg1が0になったりすると値が信用できませんが大丈夫ですか?atan2が扱えると思うので、atan2を使ってください。 outg1 = atan2(g2,g1); あと書いてないですが、 double outg1; ですよね?

-TaKaHiRo-
質問者

補足

>データを読むときも同様なので、ADRESL,ADRESHの順番で並んでいないと駄目です。 単に8bitだけ取り出す(精度8bit)場合は、   g1 = (double)ADRESH; では駄目なのでしょうか? >あと書いてないですが、 >double outg1; >ですよね? outg1はdoubleです。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • PIC18でのA/D変換

    PIC18F67J60-l/PT(40MHz)で、C18を使ってA/D変換を行うプログラムを作成しました。 しかし、実際に接続をしてみると上手く動作しませんでした。 具体的には、Web上でA/D変換の結果を表示して確認しているのですが、 結果の値がばらついたり、0か1023が表示され、安定しません。 (1023以上の値が表示されないので、表示するプログラムには問題ないと思います) ピンの接続を何度も確認したり、接続状況を変えたのですが、 問題を解決するまでに至りませんでした。 プログラムに問題があるか、初心者なのでよく分かりません。 参考書や資料を見る限りではプログラムに問題はないと思うのですが、 皆様のご指摘を頂きたいと思います。 宜しくお願いします。 ------------------------------------------------------------------- (前提条件) Vref-はAN2(0V)、Vref+はAN3(3.3V)から取り、 入力をAN4、AN7、AN8、AN9から取り込む。 (作成したA/D変換プログラム)  //各レジスタの設定  ADCON1 = 0x35;  //VREF-はAN2、VREF+はAN3  TRISA = 0x2F;  //AN2,AN3は入力モード  TRISF = 0x1C;  //AN7~AN9を入力にする  ADCON2 = 0xB6;  //AN4用 加速度センサA1  ADCON0 = 0x11;  Delay10TCYx(0);  ADCON0bits.GO = 1;  while(ADCON0bits.GO);  Delay10TCYx(0);  uitoa(*((WORD*)(&ADRESL)), AN4String);  //AN7用 加速度センサA2  ADCON0 = 0x1D;  Delay10TCYx(0);  ADCON0bits.GO = 1;  while(ADCON0bits.GO);  Delay10TCYx(0);  uitoa(*((WORD*)(&ADRESL)), AN7String);  //AN8用 加速度センサB1  ADCON0 = 0x21;  Delay10TCYx(0);  ADCON0bits.GO = 1;  while(ADCON0bits.GO);  Delay10TCYx(0);  uitoa(*((WORD*)(&ADRESL)), AN8String);  //AN9用 加速度センサB2  ADCON0 = 0x25;  Delay10TCYx(0);  ADCON0bits.GO = 1;  while(ADCON0bits.GO);  Delay10TCYx(0);  uitoa(*((WORD*)(&ADRESL)), AN9String);  // AD converter errata work around (ex: PIC18F87J10 A2)  #if !defined(__18F452)  PRODL = ADCON2;  ADCON2bits.ADCS0 = 1;  ADCON2bits.ADCS1 = 1;  ADCON2 = PRODL;  #endif

  • PIC A/D変換での問題

    PIC16F690を使用しLCDにA/D変換をした数値を表示させる物を作ったのですが 抵抗を一定の速度で回しても数値が一定の速度で変化しません。 詳しく説明しますと、今回書いたプログラムは8bitで255までの値を表示させるものです。 抵抗をめいいっぱい回して数値を1にし(0にはどうしてもなりません。おそらく抵抗の問題) そこからゆっくりと一定の速度で抵抗を回すと数値が上がっていきます。 30辺りまでは一定の速度で数値が変化するのですが、そこから少し回すといきなり数値が220ぐらいにまで上がります。(一応30~210までの数値も出ている様なのでいきなり飛んでるわけではない) 抵抗を1Kのものから10Kものに変えてみたりしたのですが症状に変化はありませんでした。 どうしても解決できなかったので質問をした次第です。 解決方法がわかる方がいらっしゃいましたらお教え下さい。 プログラムを載せておきます。 #include<pic.h> #include<stdio.h> #include "lcd.h" unsigned int temp; unsigned int x = 1; unsigned char outString[20]; unsigned char count[20]; void init_a2d(void){ ADCON1=0x10; // A/D Clock Fosc/8 ADCON0=0x01; // A2D 入力をChannel 0 (RA0), // Left justified, A/D をON } // 指定された入力チャネルをA/D変換し8 bitの結果を返す unsigned char read_a2d(unsigned char channel){ channel&=0x0F; // 4 bitsを確認し ADCON0&=0xC3; // 現行入力チャネルをクリア ADCON0|=(channel<<2); // 新入力チャネルを設定 GODONE=1; // 変換開始 while(GODONE)continue; // 変換終了を待つ return(ADRESH); // 8 bitの結果を返 } void main(void) { pic_init(); init_a2d(); // A/D モジュール初期化 lcd_init(); lcd_goto(0x00); while(1) { __delay_us(50); // 50uS待ち(AD充電待ち) temp=read_a2d(0); sprintf(outString,"A/D=%2d",temp); lcd_puts(outString); lcd_goto(0x40); sprintf(count,"Count=%d",x); lcd_puts(count); x++; __delay_ms(100); lcd_clear(); } }

  • PIC16F877を用いたC言語でのAD変換について

    PICを用いてAD変換をしようとしていますが,思うように出力が出ず困っています. 可変抵抗を用いて0-5V間を調整可能な入力をAN0ピンに接続し,AD変換の結果をBポートに出力しようとしています. 使用条件は,mikroC使用,PIC16F877使用,C言語使用,水晶20MHz,Aポート入力(AN0ピンアナログ入力),Bポート出力,Tad=1.6μsです. 以下のプログラムで間違っている点をご指摘いただきたいと考えています. unsigned int out_b; void port_initialize() { INTCON=0; //割り込みなし ADCON0=0x81; ADCON1=0x8E; //AD変換中の入力範囲設定は電源と共有 TRISA = 0x3f; //AD変換用ポート(1で入力) TRISB = 0; //出力用ポート(0で出力) PORTB = 0; } void value_initialize() { out_b=0; PORTB=out_b; } void main() { port_initialize(); value_initialize(); while(1){ //endless ADCON0=0x81; //AD変換bitを選択 Delay_us(24); //アクィジション時間+AD変換後の待ち時間 ADCON0=0x85; //AD変換開始 Delay_us(20); //AD変換待ち時間 out_b=ADC_Read(0); PORTB=out_b; } }

  • 加速度センサーについて

    現在加速度センサーを探しています。 ただ問題がありまして、 傾きを感知できる加速度センサーだと 少々まずいのです。 静的な加速度じゃなくて動的な加速度だけを 測定できる加速度センサーってありますか?? 思いっきりブンって振ったときだけ電圧が 出てほしいので、傾けただけでは 電圧が出力されては困るのです。 どなたかご存じないでしょうか??

  • PIC 出力を持続したい

    鉄道模型のコントローラーを作っています。 マイコンはPIC16F886です。 以下のようなプログラムを作りました。 (ただし、mainよりも前の設定等は今回の質問に関係ないと思われますので、省略してあります) 質問箇所は(1)~(5)です。 while(RC3==0)のときその部分がループされるようになっていまして、ループから抜けた時に(1)(2)(3)で変更された内容は保持されているのですが、(4)(5)はループを抜けた瞬間に0になってしまいます。 たとえば、(1)と(4)の条件を満たしてRA1=1、RB6=1となり、relay1とrelay3がONになります。 しかしループを抜けると、relay1はONのままなのですがrelay3がOFFになってしまいます。 なぜでしょうか。 出力しているピンの問題なのですか? ご回答よろしくお願いします。 以下プログラム (省略) main() { PORTA = 0x00; PORTB = 0x00; PORTC = 0x00; TRISA = 0b11111001; TRISB = 0b00111111; TRISC = 0b11111111; ANSEL = 0b00000001; ANSELH = 0b00111111; ADCON1 = 0b00000000; while(RC3==1); // マスコンを「非常」にしないと動作しない while(1) { if(RC3==0 && SPD==0) // マスコンが非常、かつ車両が停止している時 { while(RC3==0) // マスコンが非常のとき、無限ループ開始 { if(RC4==0) // 方向セレクトSWがRC4の時・・・(1) { RA2 = 0; // relay2をOFF DelayUs(20); RA1 = 1; // relay1をON } else if(RC5==0) // 方向セレクトSWがRC5の時・・・(2) { RA1 = 0; // relay1をOFF DelayUs(20); RA2 = 1; // relay2をON } else if(RC4==1 && RC5==1) // 方向セレクトSWが中立の時・・・(3) { RA1 = 0; // relay1をOFF DelayUs(20); RA2 = 0; // relay2をOFF } if(RC6==0) // 出力セレクトSWがRC6の時・・・(4) { RB6=1; // relay3をON } else if(RC7==0) // 出力セレクトSWがRC7の時・・・(5) { RB6=0; // relay3をOFF } } } ADCON0 = 0b10000001; // 最高速度をAN0から読み込む DelayUs(20); // ADCが安定するまで待つ GODONE=1; // ADC起動 while(GODONE); // ADC終了まで待つ MAX=ADRESH; // ADCの上位8ビットを最高速に代入 if(RA3==0) // マスコンが加速3の時 { ADCON0 = 0b10110101; // 加速度をAN13から読み込む } if(RA4==0) // マスコンが加速2の時 { ADCON0 = 0b10101101; // 加速度をAN11から読み込む } if(RA5==0) // マスコンが加速1の時 { ADCON0 = 0b10100101; // 加速度をAN9から読み込む } if(RC1==0) // マスコンが減速1の時 { ADCON0 = 0b10100001; // 加速度をAN8から読み込む } if(RC2==0) // マスコンが減速2の時 { ADCON0 = 0b10101001; // 加速度をAN10から読み込む } if(RC3==0) // マスコンが非常の時 { ADCON0 = 0b10110001; // 加速度をAN12から読み込む } DelayUs(20); // ADC安定するまで待つ GODONE=1; // ADC起動 while(GODONE); // ADC終了まで待つ ACC=ADRESH; // ADCの上位8ビットを加速度に代入 func01(); } }

  • C18(PIC18)でのシフト演算など

    PIC18で、加速度センサからの値を読み取るプログラムを作成しています。 加速度センサからのパルスを読み取るのに、 以下のようなプログラムを作成しました。 しかし、どうしてもif文がうまく動いてくれません。 (条件が「1100」、「0b1100」、「0xc」、「12」のいずれの場合も引っかかりませんでした。) その他、プログラムをいろいろ見たのですが、 原因を発見することができませんでした。 皆様の、アドバイス、ご指摘お願いします。 ------------------------------------------------------------------- (メインループ)  ↓  リセット命令(コマンド 0000)  ↓  測定開始コマンド(コマンド 1000)  ↓  READコマンド(終了のみ)(コマンド 1100)   flag1 = 0;      「1100」を送る命令の次に    PORTBbits.RB2 = 1; //CLK = 1    Delay10TCYx(10); //待ち時間    PORTBbits.RB2 = 0; //CLK = 0    Delay10TCYx(5); //待ち時間    if(PORTBbits.RB4 == 1) flag1 |= (1 << (3 - 0));    Delay10TCYx(5); //待ち時間    PORTBbits.RB2 = 1; //CLK = 1    Delay10TCYx(10); //待ち時間    PORTBbits.RB2 = 0; //CLK = 0    Delay10TCYx(5); //待ち時間    if(PORTBbits.RB4 == 1) flag1 |= (1 << (3 - 1));    Delay10TCYx(5); //待ち時間    PORTBbits.RB2 = 1; //CLK = 1    Delay10TCYx(10); //待ち時間    PORTBbits.RB2 = 0; //CLK = 0    Delay10TCYx(5); //待ち時間    if(PORTBbits.RB4 == 1) flag1 |= (1 << (3 - 2));    Delay10TCYx(5); //待ち時間    PORTBbits.RB2 = 1; //CLK = 1    Delay10TCYx(10); //待ち時間    PORTBbits.RB2 = 0; //CLK = 0    Delay10TCYx(5); //待ち時間    if(PORTBbits.RB4 == 1) flag1 |= 1;    Delay10TCYx(5); //待ち時間    return flag1;  ↓  メインループ   if(flag1 == 1100){ //「1100」では動きません    11bit分読む命令    11bit分読む命令   } ------------------------------------------------------------------- 加速度センサ(HM55B) http://www.hitachi-metals.co.jp/prod/prod01/p01_13_a.html

  • この式でGに入れるべき値

    加速度センサから取得した情報で歩行情報を検出するためのフィルタとして画像の式が見つかりました ここでGに入れるべき値はどのようなものでしょうか (Gは閾値のようです)

  • C言語でPBYTE型からDOUBLE型へ変換

    以下、角速度、加速度、地磁気をセンシング可能なセンサが3種類あります。 ・ジャイロセンサー(3軸) 検出範囲:±1000 dps、 ・加速度センサー (3軸) 検出範囲:±6G、 ・地磁気センサー (3軸) 検出範囲:0.6 mT、感度:0.3 uT/LSB 今、センサからそれぞれ、1サンプルあたり16バイトの諧調値を表す データがサンプリング周波数毎に送られてきます。 私が実装したのはセンサデータをサンプリング毎に 以下の配列dataに格納するところまでです。 この配列dataに -?~+?のデータが格納されます。 //X軸だけの例 PBYTE data[6]; data[0]→加速度センサX軸の上位バイト data[1]→加速度センサX軸の下位バイト data[2]→角速度センサX軸の上位バイト data[3]→角速度センサX軸の下位バイト data[4]→地磁気センサX軸の上位バイト data[5]→地磁気センサX軸の下位バイト //ここで、質問になります。 この諧調値が入っている配列dataをdouble型配列 に変換したいのです。言語はC言語になります。 固定長から変換するので当然誤差が入って構いません。 おそらく、最上位ビットは符号ビットと思われます。 センサの静止状態で取得してみたデータ例があります。 //取得データ例(すべてX軸) data[0]→128'・' data[1]→162'l' data[2]→0 data[3]→28'' data[4]→255'・' data[5]→190'セ' 私のポンコツ頭では難しいです。 どうか助けてください。よろしくお願いします。

  • 16進数の変換

    visualbasic6.0で加速度センサーから傾きを検出するプログラムを作りたいのですが、初心者のため手探りでやっている状態です。 センサーからの信号は16進数で4バイトずつ送られてきます。 これを10進数に直して、前の2バイトと後ろの2バイトを分けて表示したいのですが解かりません。以下が現段階のコードの1部です。 Private Sub MSComm1_OnComm() Dim bytBuf() As Byte Dim strDisp As String Dim lngCount As Long Select Case MSComm1.CommEvent Case comEvReceive If List1.ListCount = 0 Then MSComm1.InBufferCount = 0 End If Do bytBuf = MSComm1.Input strDisp = "" For lngCount = LBound(bytBuf) To UBound(bytBuf) strDisp = strDisp & Right("00" & Hex(bytBuf(lngCount)), 2) & " " Next List1.List(0) = List1.List(0) & strDisp Loop While MSComm1.InBufferCount <> 0 End Select End Sub

  • 3軸加速度センサの値の出力値について

    三軸加速度センサの出力値についての質問です。 電圧は3.3V 感度は660mV/g 0G出力が1.65V 測定レンジが+-2gとなっています。 加速度センサのz軸を下に置いた状態で値を出力すると x:320 y:330 z:430  と出力されます。 加速度センサのx軸を下においた状態で値を出力すると x:435: y:328 z:327 と出力されます そこで質問なのですが上のx:320 y:330 z:490 、x:485: y:328 z:327 の出力値の単位が(mV/g)ということ、下向きにするとその軸にGがかかる、ということはなんとなくわかるのですがこれらの値の意味(導出方法)がよくわかりません。一通り調べたのですが見つかりませんでした どなたか詳しく説明していただける方はいらっしゃいませんか?

このQ&Aのポイント
  • スマートフォンでは印刷できるのに、PCから印刷しようとするとエラーが発生してしまいます。設定を確認しても解決しないため困っています。
  • お使いのインクジェットプリンター・複合機「MFC-J738DN」は、スマートフォンでは問題なく印刷できますが、PCから印刷する際にエラーが発生してしまいます。
  • 無線LAN接続しているノートパソコンから、インクジェットプリンター・複合機「MFC-J738DN」に印刷しようとするとエラーが出てしまいます。設定を見直しても解決しないため、困っています。
回答を見る