No.5ベストアンサー
- 回答日時:
DATAが1000とか4000 とか、これが無茶です。
H8/3664F は RAMが2KBしかないのですから。
例えば
#define DATA 1050
int A[DATA];
と書いた時点で、intが16bit(=2Byte)なら2 * 1050 = 2100 で既に2KB越えてます。intが32bitならその倍のRAMを使おうとしています。DATA=1007ならOKで、1008だとNGなのも、1007*2 = 2014 とスタックやその他のメモリ消費分をあわせてこのあたりがぎりぎりいっぱいの値だからだと思います。
さらに、ご質問に書かれている
> いろいろ試した結果,配列を定義するとA/D変換を行ってくれないようです。
というのも、配列の要素数が多すぎてRAMが不足していることによるものだと思います。
さて対策案です。
(a) 相関の計算をPCで行う
相関はどうしてもH8の中で計算しなくてはいけないのでしょうか?
PC側で計算すればすむことなら、大量のデータをH8の中にため込まずに少し測ってはPCに送り、PC側で計算してしまったほうが楽です。これなら、データ点数を5000点にしても10000点にしても、どうせ計算するのはPCですからH8のRAMが不足する心配や、H8の計算速度の心配をする必要がありません。
(b) データ点数を減らす
どうしてもH8の内部で相関を求める必要がある場合、データ点数は1000~4000点も本当に必要でしょうか?
計測対象信号の周波数の2倍の周期までサンプリングレートを落として、必要最低限のデータ点数を見直してみましょう。
(c) データ型に小さなものを使う
データ点数を減らしただけではまだ足りないのなら、AD変換した値を保存するデータ型を unsigned char にしてはどうでしょうか。H8のADコンバータの精度は10bitですが、最下位2bitはノイズレベルの値ですから多少目をつぶって良い部分だと思います。unsigned charなら8bitですから、16bitのデータ型の倍のデータ点数を扱えるようになります。
(d) マイコンをRAMの多いものに差し替える + 外部RAMを使う
それでもサンプリングしたデータが2KBを越えてしまうのなら、もっと大きなRAMを持っているH8を使ってはいかがでしょうか。例えば、H8/3052Fの内蔵RAMは8KBありますし、バスがあるので外にDRAMを増設すればKBではなくMB単位のRAMを使えるようになりますから、RAMの心配をする必要がなくなります。
秋月のH8キット一覧
http://akizukidenshi.com/catalog/renesas/
私がお勧めする順序で対策案を挙げてみました。
ご丁寧に何度もご指導いただきましてありがとうございました。
検討した結果。(a),(b),(c)は仕様上できないので(d)案を採用することにしました。
No.4
- 回答日時:
AD変換の設定がスキャンモードになっていること、AN0,AN1が読み取り対象であることはわかりました。
こうしてみるとAD変換そのものには問題無いように見えます。では何が悪いか考えようと思ったら、ANo.2のお礼に書かれているソースコードは、全体の一部抜粋のようですね。ご質問の雰囲気からして学生さんだと思いますが、ちゃんとコンパイルが通るソースコードを全部上げていただいた方が解決しやすいと思いますので、差し支えなければ見せてください。
> A/D変換を行ってくれません。
この場合、どのような値が入っていますか?
とりあえず相関の計算はちょっと置いておいて、AD変換して得られた加工前の値がどうなっているか、X,Yの値を全部シリアル通信でPCに送って確認してみてください。
また、これも AD変換とは別の話なのですが、信号を計測するのにサンプリング時間が考慮されていないようですね。計測対象となる信号の周期はどれくらいですか? たぶん、サンプリング定理とかナイキスト周波数といえば何の事を言っているのかわかっていただけるかと思います。
> 相互相関の計算方法でi=0~DATAまでとしたとき
> X[i]*Y[i]の総和を計算するためオーバーフローするのではと考えたので
AD変換して得られる値は10bitなので10進数でいえば1024が最大値。この値を2乗しても高々1048576で、unsigned long など32bitのデータ型に入れておけばざっくり4000回くらい足してもオーバーフローしないんじゃないでしょうか。 unsigned longで扱える値の最大値は、limits.hの ULONG_MAXというマクロ定義をみて確認してください。
計算時間を気にしなくていいなら、浮動小数点使っても問題ないのでここは流していただいて結構です。浮動小数点演算は「すごく」遅いということだけ覚えておいてくださいね。
参考:H8における浮動小数点演算の速度
http://mobile-robots.way-nifty.com/daily_report/ …
この回答への補足
全体のプログラムはをあげるのは少々問題があるので問題がある部分を除いた物で
よろしいでしょうか。それでよろしいのであれば↓に記載します。
#include<3664.h>
#defineDATA 4000 //相関処理するデータ数//
#defineSR 31250 //サンプリングレート//
#defineL 99.79623//センサ間距離//
int flag1 = 0,flag2 = 0, d_num = 0, space1 = 0, space2 = 0;
double vh = 0,a1 = 0,b1 = 0,a2 = 0,b2 = 0;
typedef enum{
BR2400 = 207,
BR4800 = 103,
BR9600 = 51,
BR19200 = 25,
BR38400 = 12,
BR57600 = 8,
BR115200 = 3,
}BaudRate;
/*IO初期化*/
void IO_init(void)
{
IO.PCR8 = 0xff;
}
/*A/D変換器初期化*/
void AD_init(void)
{
AD.ADCSR.BIT.ADF = 0;//A/Dエンドフラグクリア//
AD.ADCSR.BIT.SCAN = 1;//スキャンモード選択//
AD.ADCSR.BIT.CKS = 1;//クロックセレクト:134ステート選択//
AD.ADCSR.BIT.CH = 1;//チャネルセレクト:CH0,CH1選択//
}
/*SCI初期化*/
void SCI_init(BaudRate b)
{
int i;
IO.PMR1.BIT.TXD = 1;
SCI3.SCR3.BYTE = SCI3.SMR.BYTE = 0;
SCI3.BRR = b;
for(i=0;i<3000;i++);
SCI3.SCR3.BYTE = 0x30;
SCI3.SSR.BYTE = 0x80;
}
/*タイマA初期化*/
void timerA_init(void)
{
TA.TMA.BYTE = 0x13;
IRR1.BIT.IRRTA = 0;
IENR1.BIT.IENTA = 0;
}
/*相関処理*/
void s_soukan(double X[DATA],double Y[DATA],int dt)
{
・
・ ←この部分で相互相関を行い,遅れ時間を算出しています
・
}
/*データ送信*/
void SCI3_out(int dt)
{
int i,j,k = dt,l,m=0;
for(i=1;i<=6;i++)
{
while(SCI3.SSR.BIT.TDRE == 0);
for(j=5;j>=i;j--)
{
k /= 10;
}
l = k/10;
l *= 10;
m = (k-l)+0x30;
SCI3.TDR = m;
}
SCI3.TDR = 0x0A;
}
int main(void)
{
int i=0,dt = DATA;
double vhb, X[DATA], Y[DATA];
IO_init();
SCI_init(BR19200);
AD_init();
timerA_init();
d_num = 0;
while(1)
{
IO.PDR8.BYTE = 0x01;
if(IRR1.BIT.IRRTA == 1)
{
IRR1.BIT.IRRTA = 0;
AD.ADCSR.BIT.ADST = 1;
while(AD.ADCSR.BIT.ADF == 0);
AD.ADCSR.BIT.ADF = 0;
X[i] = ((AD.ADDRA & 0xFFC0) >> 6)/1000;
Y[i] = ((AD.ADDRB & 0xFFC0) >> 6)/1000;
i++;
}
if(i>=DATA)
{
IO.PDR8.BYTE = 0x00;
s_soukan(X,Y,dt);
SCI3_out(dt);
d_num++;
i = 0;
if(dt != DATA)
{
vhb = vh;
vh = L*3600/1000000/dt*SR;
if(vh >= vhb)
flag1 = 0;
else
flag1 = 1;
}
}
}
}
> A/D変換を行ってくれません。
この場合、どのような値が入っていますか?
↑については時数の関係でお礼の部分に記載します。
>> A/D変換を行ってくれません。
>この場合、どのような値が入っていますか?
↓のようなプログラムを作成し,動作確認をしました。
#include<3664.h>
#define DATA 1050
typedef enum{
BR2400 = 207,
BR4800 = 103,
BR9600 = 51,
BR19200 = 25,
BR38400 = 12,
BR57600 = 8,
BR115200 = 3,
}BaudRate;
void IO_init(void)
{
IO.PCR8 = 0xff;
}
void timerA_init(void)
{
IRR1.BIT.IRRTA = 0;
TA.TMA.BYTE = 0x17;
IRR1.BIT.IRRTA = 0;
IENR1.BIT.IENTA = 0;
}
void AD_init(void)
{
AD.ADCSR.BIT.ADF = 0;//A/Dエンドフラグクリア//
AD.ADCSR.BIT.SCAN = 0;//スキャンモード選択//
AD.ADCSR.BIT.CKS = 1;//クロックセレクト:134ステート選択//
AD.ADCSR.BIT.CH = 0;//チャネルセレクト:CH0,CH1選択//
}
void SCI_init(BaudRate b)
{
int i;
IO.PMR1.BIT.TXD = 1;
SCI3.SCR3.BYTE = SCI3.SMR.BYTE = 0;
SCI3.BRR = b;
for(i=0;i<3000;i++);
SCI3.SCR3.BYTE = 0x30;
SCI3.SSR.BYTE = 0x80;
}
void SCI_out(int A[DATA])
{
int h,i,j=0,k=0,l=0;
for(l=0;l<=DATA-1;l++)
{
for(h=0;h<=10;h++)
{
j=A[l];
for(i=h;i<10;i++)
{
j /=10;
}
k=j/10;
j=j-k*10+0x30;
while(SCI3.SSR.BIT.TDRE == 0);
SCI3.TDR = j;
}
while(SCI3.SSR.BIT.TDRE == 0);
SCI3.TDR = 0x0A;
}
while(SCI3.SSR.BIT.TDRE == 0);
SCI3.TDR = 0x0A;
}
int main(void)
{
int A[DATA],i=0;
AD_init();
SCI_init(BR19200);
while(1)
{
for(i=0;i<=DATA-1;i++)
{
AD.ADCSR.BIT.ADST = 1;
while(AD.ADCSR.BIT.ADF == 0);
AD.ADCSR.BIT.ADF = 0;
A[i] = (AD.ADDRA>>6)&0x03FF;
}
if(i >= DATA)
SCI_out(A);
}
return 0;
}
このとき,DATAの個数が1007個まではPCにデータが正しく送信されてきます。
しかし,1008個になるとデータが00000031010 や 0000000000/ のような
おかしなデータが送信されるようになります。(正しい時は00000001023)
さらに,DATAの個数を1050以上にするとPCにデータが送信されなくなってしまいました。
No.3
- 回答日時:
IO_init, AD_init の中身はどうなっていますか?
AD変換の動作モードが「単一モード」なのか「スキャンモード」なのか、AD_initのなかでどのように設定しているか見せてください。
予想としては、単一スキャンモードをつかっているのではないかと。
また、ADCの動作ではないのですが、
> X[i] = ((AD.ADDRA & 0xFFC0) >> 6)/1000;
> Y[i] = ((AD.ADDRB & 0xFFC0) >> 6)/1000;
これ考え直した方がいいかもしれません。というのは、
(AD.ADDRA & 0xFFC0) >> 6 で、AD変換された値が10bitで取得できますが、10bitで得られる値は最大1024で、これを1000で割っていますから割り算の結果(商)は 0 か、1 です。X, Y がdoubleで定義いされていても、X, Y に代入される前の計算は整数のままです。
明示的にdoubleにキャストするか、割る数を 1000.0 にすれれば計算が浮動小数点で行われますが、その前に 1000 で割る必要性についても少し説明してください。(私は、割る必要ないのでは?と思っています)
この回答への補足
A/D変換の初期化は
/*A/D変換器初期化*/
void AD_init(void)
{
AD.ADCSR.BIT.ADF = 0;//A/Dエンドフラグクリア//
AD.ADCSR.BIT.SCAN = 1;//スキャンモード選択//
AD.ADCSR.BIT.CKS = 1;//クロックセレクト:134ステート選択//
AD.ADCSR.BIT.CH = 1;//チャネルセレクト:CH0,CH1選択//
}
としているため,スキャンモードを選択しています。
また,1000で割ることは私の間違いで実際には浮動小数点で行おうと
考えていました。理由としては相互相関の計算方法でi=0~DATAまでとしたとき
X[i]*Y[i]の総和を計算するためオーバーフローするのではと考えたので
浮動小数点で扱おうと考えていました。
No.2
- 回答日時:
では、具体的にどのような処理を行っているのか、AD変換に関連する部分だけでよいので書いてください。
また、使っている開発環境(コンパイラなど)も明記してくださいね。抽象的に書いてしまい,申し訳ありませんでした。
処理の内容は
int main(void)
{
int i=0;
double vhb, X[DATA], Y[DATA];
IO_init();
SCI_init(BR19200);
AD_init();
timerA_init();
d_num = 0;
while(1)
{
IO.PDR8.BYTE = 0x01;
if(IRR1.BIT.IRRTA == 1)
{
IRR1.BIT.IRRTA = 0;
AD.ADCSR.BIT.ADST = 1;
while(AD.ADCSR.BIT.ADF == 0);
AD.ADCSR.BIT.ADF = 0;
X[i] = ((AD.ADDRA & 0xFFC0) >> 6)/1000;
Y[i] = ((AD.ADDRB & 0xFFC0) >> 6)/1000;
i++;
}
if(i>=DATA)
{
IO.PDR8.BYTE = 0x00;
s_soukan(X,Y,dt); /*XとYの相互相関を行い遅れ時間を算出*/
SCI3_out(dt); /*算出した遅れ時間をPCに送信*/
i = 0;
}
}
}
というように2つの信号を取得して,その信号の相互相関を行い,遅れ時間を
計算するプログラムを作成してマイコンに書き込んだんですがうまく
動きませんでした。
ちなみにコンパイラはGDL(GCC Developer Lite)のVer.2.0.1.8を使用しています。
ライタはGDLの設定方法が悪いためか,GDLでマイコンにライトできなかったため,
別のライタソフトのH8 writer Ver.0.37を使用してマイコンにライトしています。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- フリーソフト フォルダ、ファイル名の一括変換について 3 2023/03/16 09:23
- Excel(エクセル) 【VBA】指定フォルダに格納中のテキストファイルをエクセルで処理し結果のエクセルを新規フォルダに保存 1 2022/03/25 14:19
- 工学 オペアンプによる増幅回路でのノイズ対策について 5 2022/03/22 16:06
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- Visual Basic(VBA) VBA 検索と入力 Excel ブック ぶぶぶ シート ししし 列V 検索対象の列です 最終行は、お 6 2023/05/17 01:40
- Excel(エクセル) Excelシフト表 固定シフトの自動変換化 1 2022/04/14 16:10
- 数学 フーリエ変換後の負の周波数成分の扱いについて 4 2022/09/03 10:18
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- Excel(エクセル) 列を挿入しても式の一部を固定するには 6 2023/05/31 21:57
- フリーソフト フリーソフト[フリーオンライン動画兼音声変換ソフト]縦長になってしまう 2 2022/07/11 08:11
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
O(n log n)について2
-
16進数 加算 減算 C言語
-
三菱シーケンサ(Aシリーズ)で...
-
ExcelでPC(パソコン)によって...
-
c languageで 簡単な質問があ...
-
VB.net Double と...
-
C言語でセルオートマトンを作成...
-
Log関数に関する質問
-
VBAでミリ秒まで出力する方法
-
距離から緯度経度を求める方法
-
乱数 なぜ剰余を使うのか
-
大きすぎる数値になるとE+にな...
-
色の判定
-
【C言語】RGBと輝度の計算に関して
-
100桁の計算ができなくて困って...
-
16進数とかわからないです
-
”/”を使わずに割り算したいんで...
-
データ型 double の桁数について
-
計算に誤差が出る?
-
【VBA、VBS】何故False・・・?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
16進数 加算 減算 C言語
-
c languageで 簡単な質問があ...
-
VB.net Double と...
-
”/”を使わずに割り算したいんで...
-
三菱シーケンサ(Aシリーズ)で...
-
ExcelのINT関数の計算結果がお...
-
有効数字について 以前質問をし...
-
ExcelでPC(パソコン)によって...
-
除算を使わずに10で割りたい。
-
EXCELの関数"STDEV(標準偏差)"...
-
floatの有効桁数
-
VBAでミリ秒まで出力する方法
-
100桁の計算ができなくて困って...
-
2進数の足し算(C言語)
-
VB6.0での小数点の扱いについて
-
VBAでの割り算の余りの求め方
-
コンピューターは指数関数をど...
-
距離から緯度経度を求める方法
-
BCD・HEX・BINについて
おすすめ情報