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

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

ただいまの
回答率

90.74%

  • C

    3444questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

マイコンを用いたA/D変換後のシリアル通信時の波形の乱れ

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 169

sotooki

score 8

 前提・実現したいこと

オシロスコープに出力された波形をdsPICでA/D変換したのち、波形の最大値を求めシリアル通信でPCに送りたいと考えています。

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

図や動画のように計測を開始するとオシロスコープ上の波形が乱れてしまいます。
また、シリアル通信後の値も不定期に別の値に飛んでしまいます。

![波形一覧

計測動画

マイコンの割り込みによる問題が考えられますが、このような現象はあり得ますでしょうか。

ソースコード

#include<p30f3013.h>
#include<dsp.h>
#include<uart.h>
#include<timer.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<spi.h>
#include<adc12.h>
#define UART_RX_TX 0xFBE7
#define UART_ALTRX_ALTTX 0xFFE7
#define CLOCK 117964800 //clock=(7.3728*16)=118MHz
#define Fcy CLOCK/4 //system clock=118/4=30MHz
#define BAUD 115200 //最大で57600bps

/*** dsPIC_config ***/
_FOSC(CSW_FSCM_OFF & XT_PLL16 )//XT_PLL16 or FRC_PLL8
_FWDT(WDT_OFF)
_FBORPOR(MCLR_EN & PBOR_OFF & PWRT_OFF)
_FGS(CODE_PROT_OFF)

/***  ハードウェアピン設定 ***/
#define Green    LATBbits.LATB5
#define Red      LATBbits.LATB4
#define SPI_CS   LATFbits.LATF5
#define dds_CTRL LATDbits.LATD8
#define dds_Int  LATDbits.LATD9
#define A2       LATBbits.LATB8
#define A1       LATBbits.LATB9
#define A0       LATBbits.LATB7
#define Triger   LATBbits.LATB6

/*** 定数定義 ***/
#define PI 3.141593

/***  Grobal変数定義 ***/
unsigned long SetTime1;
unsigned long SetTime2;
unsigned long Fs1;
unsigned long Fs2;
unsigned int cmnd;
unsigned int Data[5];
unsigned int Data_new;
unsigned int Data_old;
unsigned int TopDataV;
unsigned int TopDataf;
unsigned int i=0;
unsigned int n=0;
unsigned int fmin[100];
unsigned int Vmin[100];
unsigned int TX;
unsigned int RX;
unsigned int ch=1;
unsigned int h;
unsigned int count=0;
unsigned int flag=0;
unsigned int ftx=0;
unsigned int frx=0;


/*** ADコンバータ初期設定パラメータ(符号付固定少数で扱う) ***/
unsigned int Config1 = ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_SIGN_FRACT &
                       ADC_CLK_AUTO & ADC_AUTO_SAMPLING_ON & ADC_SAMP_OFF;
unsigned int Config2 = ADC_VREF_EXT_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_1 &
                       ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF;
unsigned int Config3 = ADC_SAMPLE_TIME_5 & ADC_CONV_CLK_SYSTEM &
                       ADC_CONV_CLK_32Tcy;
unsigned int ConfigPort = ENABLE_AN2_ANA;
unsigned int ConfigScan = 0x000;
unsigned int Channel0 = ADC_CH0_POS_SAMPLEA_AN2 & ADC_CH0_NEG_SAMPLEA_NVREF;

/*** UARTの初期設定パラメータ ***/
unsigned int UMODEValue = UART_EN & UART_IDLE_CON & UART_ALTRX_ALTTX & 
                          UART_DIS_WAKE & UART_DIS_LOOPBACK &
                          UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_1STOPBIT;
unsigned int USTAValue =  UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL &
                          UART_TX_ENABLE & UART_INT_RX_CHAR &
                          UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
unsigned int ubrg=(Fcy/(16*BAUD))-1;

/***  SPI設定パラメータ クロック15MHz(Max20MHz) ***/
unsigned int SPICONValue =  FRAME_ENABLE_OFF & FRAME_SYNC_INPUT &
                            ENABLE_SDO_PIN & SPI_MODE16_ON & SPI_SMP_ON & SPI_CKE_ON&
                            CLK_POL_ACTIVE_HIGH & MASTER_ENABLE_ON &
                            SEC_PRESCAL_1_1 & PRI_PRESCAL_1_1;
unsigned int SPISTATValue = SPI_ENABLE & SPI_IDLE_CON &
                            SPI_RX_OVFLOW_CLR;


/*** delay_ms,delay_usの作成 ***/
void delay_ms(unsigned int N)
{
  __delay32((Fcy/1000)*N);
}

void delay_us(unsigned int N)
{
  __delay32((Fcy/1000000)*N);
}

void delay_ns(unsigned int N)
{
  __delay32((Fcy/1000000000)*N);
}


/** DDSの初期設定 **/
void DDSset(void)
{
/* コントロールレジスタ書き込み */
 SPI_CS=0;
 WriteSPI1(0x6F7);
 delay_ns(500);
 SPI_CS=1;
 delay_ns(1000);
/* 開始周波数設定 */
 SPI_CS=0;
 WriteSPI1(0xC312);//LSB
 delay_ns(500);
 SPI_CS=1;
 delay_ns(1000);
 SPI_CS=0;
 WriteSPI1(0xD008);//MSB
 delay_ns(500);
 SPI_CS=1;
 delay_ns(1000);
/* 周波数インクリメント設定 */
 SPI_CS=0;
 WriteSPI1(0x20F3);//LSB
 delay_ns(500);
 SPI_CS=1;
 delay_ns(1000);
 SPI_CS=0;
 WriteSPI1(0x3000);//MSB
 delay_ns(500);
 SPI_CS=1;
 delay_ns(1000);
/* インクリメント数設定 */
 SPI_CS=0;
 WriteSPI1(0x1FA0);
 delay_ns(500);
 SPI_CS=1;
 delay_ns(1000);
/* インクリメント・インターバル設定 */
 SPI_CS=0;
 WriteSPI1(0x4000);
 delay_ns(500);
 SPI_CS=1;
 delay_ns(1000);
}

/***1point measure***/
void OnePoint(void)
{
 Red=0;
 WriteUART1((unsigned int)(0x02));
 while(BusyUART1());
for(h=1; h<=2; h++)
 {
  WriteUART1((unsigned int)(0x41+((Vmin[h]>>12) & 0x000F)));
  while(BusyUART1());
  WriteUART1((unsigned int)(0x41+((Vmin[h]>>8) & 0x000F)));
  while(BusyUART1());
  WriteUART1((unsigned int)(0x41+((Vmin[h]>>4) & 0x000F)));
  while(BusyUART1());
  WriteUART1((unsigned int)(0x41+((fmin[h]>>8) & 0x000F)));
  while(BusyUART1());
  WriteUART1((unsigned int)(0x41+((fmin[h]>>4) & 0x000F)));
  while(BusyUART1());
  WriteUART1((unsigned int)(0x41+((fmin[h]>>0) & 0x000F)));
  while(BusyUART1());
 }
 WriteUART1((unsigned int)(0x03));
 while(BusyUART1());
 CRLF();
 Red=1;
}

/***復帰改行関数***/
void CRLF(void)
{
  WriteUART1((unsigned int)(0x0a));
  while(BusyUART1());
  WriteUART1((unsigned int)(0x0d));
  while(BusyUART1());
}

void dtime (void){delay_ns(1000);}

/*** タイマ1 割り込み処理関数 ***/
void __attribute__((__interrupt__, __shadow__))_T1Interrupt(void)
{
 IFS0bits.T1IF=0;//割込みフラグクリア
 OnePoint();//1point送信
}

/*** タイマ2 割り込み処理関数 ***/
void __attribute__((__interrupt__, __shadow__))_T2Interrupt(void)
{

 IFS0bits.T2IF=0;//割込みフラグクリア
 dds_CTRL=1;
 delay_ns(200);
 dds_CTRL=0;
 SigIn[0] = ReadADC12(0);// Input to A/D converter ()
 Data_new = SigIn[0]+0x8000;//0~FFFFで与える 
 n=n+1;

 // 最大値検出(トーナメント) //
 if(Data_new > TopDataV)
 {
  TopDataV = Data_new;
  TopDataf = n;
 }

/***  掃引終了判定* **/
 if(n>=4000)
 {
  Green=1;
  count=count+1;
  Vmin[count]=TopDataV;
  fmin[count]=TopDataf;
  TopDataV=0;
  TopDataf=0;

  dds_Int=1;
  delay_ns(200);
  n=0;
  dds_Int=0;

 }
}

/*** メイン関数 ***/
void main(void)
{
  /// UART初期設定
 OpenUART1(UMODEValue,USTAValue,ubrg);
 IPC2bits.U1TXIP=5;
 IPC2bits.U1RXIP=6;

 /// PORT初期設定
 ADPCFG=0xFFFF;//アナログなし
 TRISB=0x0007;//0,1,2入力用,他出力用
 TRISF=0x0000;//RF(2,3,6)SPI出力用
 TRISD=0x0000;//RD8-SPI出力,RD9-INT0入力用
 TRISC=0x1000;//UARTRX用(RC13=High)
 PORTB=0xFFFF;//all LED off
 PORTF=0xFFFF;//RF3=High
 PORTD=0xFFFF;//RD8=High

  /// Open SPI クロック 30MHz/1=30MHz(33ns)
 OpenSPI1(SPICONValue,SPISTATValue); 
 INTCON1bits.NSTDIS=1;//多重割り込み禁止
 SPI_CS=1;
 dds_CTRL=1;

 /** DDSの初期設定 **/
 DDSset();
 dds_Int=0;
 CloseSPI1();

  /// ADC初期設定 
 OpenADC12(Config1,Config2,Config3,ConfigPort,ConfigScan);    
 SetChanADC12(Channel0);

 ///DDS tart
 //タイマ2設定,OPEN
 Fs2=240000;//Tscan=0.2s_20000,Tscan=0.05s_80000
 SetTime2 = ((Fcy/Fs2)+1);
 OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_1 & T2_SOURCE_INT , SetTime2);
 ConfigIntTimer2(T2_INT_PRIOR_3 & T2_INT_ON); 

 while(1)
 {
  while(!DataRdyUART1());
  cmnd = ReadUART1();
  ///受信コマンドの処理
  switch(cmnd)
  {     
     case'1':

    ///1point measure
     OnePoint();
     break;

     case'2':

     break;

      default : break;
    }

 }

}

 試したこと

最大値を求めるアルゴリズムを変更してみました。
しかし、根本を解決しないことには問題であると考えます。

 補足情報(FW/ツールのバージョンなど)

イメージ説明
4ピンへの入力回路:TIAによる電流電圧変換、包絡線検波回路による搬送波除去

イメージ説明
dsPIC周辺

イメージ説明
STコネクタより波形発生器で生成された交流電圧の周波数を掃引

回路動作

①波形発生器から一定範囲(1M~3MHz)の交流電圧の周波数を掃引、STより出力する
②モノがその電流を受け取った際、アナログ素子として回路上に設置したコイルとモノの抵抗、静電容量によって共振回路が生成され、STから出力された周波数を用いて共振点(オシロスコープの波形の最大値)が検出される。
③RX部分から共振点が決まった波形が入力され、12bitのA/D変換を行った後、A/D変換の最大値を求め、Bluetooth通信でPCに送信する。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • sotooki

    2018/06/08 17:23

    補足させていただきました。オシロスコープは入力回路のENVタグで計測しています。

    キャンセル

  • ozwk

    2018/06/08 17:35

    原理的に、波形発生機の周波数がインクリメントされない期間があると、観測波形に平坦な部分ができますか?

    キャンセル

  • sotooki

    2018/06/08 17:53

    はい、メイン関数で周波数発生の割り込みタイミングを決めています。

    キャンセル

回答 3

checkベストアンサー

0

波形が平らな部分が出るのをどうにかしたいという話だとして、
波形が平らになるには波形発生機の周波数インクリメントが止まっているはずで、
その波形発生機の周波数インクリメントはT2の割り込みでやっているので、
割り込みが何らかの理由で発生していないんでしょう。

で、UARTが動いていると波形が平らな部分がたまに出るということなので(ですよね?)
そのあたりをよく見直してください。
正直コード見てても結果をPCに送るタイミングが測定と全然同期していないように見えます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 18:15

    確かに、波形発生器をオシロスコープで観察すると高周波なので見にくいですが、挙動がおかしい部分が見受けられます。
    確認させていただきます。

    キャンセル

0

まず、dsPICのデータシートを見ると、A/D入力ピンは、アナログSWを介した後、直接S/H回路に入っていることが見て取れます。
で、このおかげで信号源インピーダンスは最大2.5KΩと規定されているようです

ということで、この入力回路では、A/Dの動作状況によって、入力電圧が振られてしまうのは想像に難くありません

で、不定期に別の値に飛ぶというのも、なにか動作不良を匂わせるものなので、まずはソフト面から、この別の値に飛ぶバグを潰してしまいましょう
#もしかしたらこのバグで波形が乱れているということも考えられる

ここらへんをしっかりデバッグし、出力数値も入力電圧に追従している、という状況にした後、この波形が乱れるというのをどうにかすることにしましょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/08 18:28

    やはりデータシートを見ないといけないですね(笑)
    正直、マイコンの動作が理解できていないのも問題かと思います。
    身につくように取り組みたいと思います。

    キャンセル

0

パッと絵を見た感じでは、A/Dからデータ取り込みに失敗しています。データを取りこぼしているように見えます。

1sec ぶんだけまとめてデータ処理する仕様として、1secのデータをCPUが処理している間もデータ取り込みを並行して行う必要があります。
その並行処理がうまくできていないために、取りこぼしがあり、結果が不連続になっています。
測定開始0.0secから1.0を取り込み、処理している途中、1.0後から1.2はデータを取りこぼし、再び1.2から2.2secの部分を取り込む.. 
みたいな。

対策としては、

  1. とにかく長い今のプログラムを1/10くらいの長さを目標に短くする。
  2. 実際に取り込めたデータの総サンプル数が、サンプル期間とあっているか考える。
  3. データ取り込みの割り込み処理がメインタスクの影響を受けていないかデバッグする。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.74%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    Arduinoの関数を呼び出し

    実行したいこと 下記の関数をループ処理の時に実行する これは、Arduinoのスピーカーを使用して音階(ド~高いドまで)を鳴らすプログラムです。 ド~高いドまでを出力したら、

  • 解決済

    「素数の足し算で」の解き方を教えてください

     はじめに いつもお世話になっております。 件名の解き方についてアドバイスを下さい。 これはCodeIQに投稿されていた問題だったのですが、どうしても解けませんでした。

  • 受付中

    C:大きな数の計算方法,オーバーフロー回避

    C言語で3^80の計算をしたいのですが、数が大きすぎてオーバーフローしてしまいます。各桁ごとに配列を置けばいいのかとも思いましたが、いまいちよくわかりません。 解決方法が分かる方

  • 解決済

    配列の要素間の和を全パターン求めるプログラムを作成したい。

    皆様ありがとうございました。 前提・実現したいこと <CもしくはC++> 配列の要素間の和を全パターン求めるプログラムを作成したい。 【例】 /*-------------

  • 受付中

    【C言語】冗長だと思う数字入力プログラムを改善したい

    以下のプログラムは3つの数字をスペース区切りで入力して、入力した数字を改行区切りで出力するというコードです。 C言語はあまり慣れていないので、以下のコードに冗長さを感じますが何か改

  • 解決済

    char型の配列変数にchar型の変数を代入したい

    使用言語 C 環境 Visual Studio 2017 初めての質問です。 独学でプログラミングを始めたのですがわからないところがあり困っています。 char型の配列変数の使い方

  • 解決済

    ビットの回転について

    前提 現在書籍でc言語を学習している者です。 その書籍の演習問題は解答が存在しておらず(著者の意図的に) 学習を進めることが困難な時があるので、問題のヒント等を教えていただきたいで

  • 解決済

    fscanfがうまく動作しない

    前提・実現したいこと テキストファイルから情報を取り込みたい。 中身は Dbrenlhsij,11,162.2,55.9 Ijnpwthy,14,163.8,62.6 Csaztv

同じタグがついた質問を見る

  • C

    3444questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。