2015年2月20日金曜日

PSoC4でリキッドレベルゲージを作ったよ。

日本サイプレスのブース目当てに
昨年の組み込み総合技術展(通称ET)に行ってきました。

そこで、PSoCで液体の量を測るデモをしていました。


液体の量を測るのは大変でレーザーや電極、超音波など
調整が大変だったり、センサーが高価だったりハードルが高いです。
液体の量を測る事は応用範囲が広いですね。
たとえば冷蔵庫の中にある液体や光に触れる事を避ける液体の量が分かったり
デザインのために液体の量が分からない事を解決したりと
言うような感じ。(医療系でも活用があるかな?)

液体にも少なくとも静電容量ができるはず。
静電容量ができるなら、PSoCにあるCapSenseをうまく使って液体の量を測れるはず。

今回は、ホームセンターで買ったプラスチックのボトルにアルミテープを貼って
アルミテープと液体との静電容量をCapSenseでそこに液体があるかどうかを測る
システムです。



作ろうと思ったきっかけは、コンビニにあるエスプレッソマシンのミルクが切れていた事に店員さんが気づいていないと言うことから。
このシステムの分解能はどうしてもアルミテープの数になってしまうので
1㏄単位での計測はちょっと厳しいかもしれないですね。




(赤線が液体の量です。)
難しいのは、GNDパターンでした。
ピアノの時より液体の場合ではGNDのパターンが重要でした。
始めはスライダー型のパターンにしたのですが、上手くいきませんでした。
これの理由にはCapSenseのアプリケーションノートにヒントがありました。
要は液体の静電容量にはちゃんとPCBのパターンにGND入れろって事でした。
なので、GNDパターンを丁寧に取るようにしました。

CapSenseで液体の量を測る場合では、ボトルが空の状態に
一度ならないといけないので、そう言う部分では改良が必要だと考えられます。
これでもまだ途中で、最終的にはPSoC4BLEを用いて
冷蔵庫の中にある液体がスマートフォンとかで分かるようになったら
いいかなぁと考えています。

2015年1月15日木曜日

Creator3.1環境でsprintf()の%fを使う場合

またも、トラブルシューティングの回です。

PSoC Creator3.1環境で
数値文字変換のSprintf();を使う場合
floatの変換をしたくても、出力されない場合があります。

PSoC Creator3.0では、リンカーが抜けていただけですが
3.1ではそれだけでは済みません。
ヒープサイズも変更してあげることで、3.1環境でも
%fを使うことが出来るようになります。


解決手順
先ず、3.0環境で行ったトラブルシューティング方法をする。

次に、ピンアサインやクロックの設定をする「****.cydwr」を開きます。


開いたら、「System」タブを開きます。

Heap Size(bytes)の項目が標準では0x80(128byte)となっているはずです。

これを0x80から0x200(512byte)に変更します。



変更したら再度コンパイルをして終了です。

3.0環境と比べると確かにヒープサイズの標準設定が小さくなっておりますが
3.0環境の半分の標準設定でもいいのにとつい、思ってしまいます。
リンカーの所も直してほしいです。(;´Д`)

*教えていただいた、のりたんさんありがとうございます。とても助かりました。

2015年1月9日金曜日

ADCを使ってみよう。

今回、ADCを使って高精度温度センサLM61のアナログ値を
キャラクターLCDに表示させます。
まず、必要な物
Vssa,Vddaが外に出ているPSoC5LPボード(今回はCQ出版のボード)
高精度IC温度センサーLM61BIZ 1個
セラミックコンデンサ1μF 1個

出来ればあると良いもの
抵抗330Ω 1個
コンデンサ0.1μF 1個

今回は必ず、PSoC Creater3.0の環境で行ってください。
3.1ではsprintf()のトラブルシューティングが出来ません。
3.1環境でもsprintf()を使うことが出来ます。

さて、PSoCのADCは通常のマイコンとはかけ離れた高級仕様となっています。
普段以上に濃いので、よく見ながら進めて行ってほしいとおもいます。
では、普段通り「空のプロジェクト」を立ち上げたら、以前に書いた

Sprintf()のトラブルシューティングの記事の手続き(別ウインドウ)を済ませます。


そうしたら、表示用のキャラクターLCDをドラッグアンドドロップで入れます。
次は「Analog」⇒「ADC」から「Delta Siguma ADC」を選んで、ドラッグアンドドロップします。

また、アナログの入力ピンも必要なので
「Ports and Pins」から「Analog Pin」を選んで入れます。

どう繋いだか忘れないように外につなぐ部品も「off Chip」から選んで入れておきましょう。入れ終わった段階でこんな感じ。半固定抵抗がセンサーの代わりです。

ピンに入れる前のつなぎ方はこんな感じです。

センサー側で使われる電源はアナログ側の電源のVdda,Vssaを使います。

1μFのコンデンサはADC側で使うのでまだ使いません。
それでは、ΔΣADCの設定をしていきましょう。
設定を開くとこんな感じです。

上から説明していくと

「Modes」では計測を連続、単発にするか、分解能やサンプルレートを設定します。
分解能はどれぐらい電圧を細かく見られるか、
サンプルレートは秒間何個計測できるかとなっています。
ADCでは1番目のキーとなるところで、
分解能が高くてもサンプルレートが正しくなければ誤った計測結果となります。



「Input options - ***」はどれぐらいの幅の電圧を分解するかについてです。
シングルエンド入力、差動入力で異なりますし、基準電圧よっても異なります。
今の状態では差動入力となっています。差動入力とはある2線間において
の電圧を測る場合、交流な電圧を測る場合、また外からのノイズが強い場合において
使われます。

「Reference」はADCが使う基準電圧に付いての設定です。
内蔵の基準電圧を使うことも出来ますし、内蔵の基準電圧にコンデンサを追加することも出来ます。また外部の基準電圧を使うことも出来ます。

今回は差動入力の必要が無いので、先ず「Common」のタブを開いて

「Differetial」のラジオボタンを「Single ended」に切り替えて
シングルエンド入力にしましょう。

元のタブに戻ると「Input options」の所が「Single ended mode」となります。

それでは、詳細な設定を上からしていきたいと思います。
Modesの所では、
「Resolution(bits)」をプルダウンメニューの中から14を選び
「Conersion rate」に20000と入力します。

Input options-***では、
「Input range」のプルダウンメニューからVssa to 2.048Vを選びます。
LM61のセンサーは最大1.6VなのでVssa to Vddaまでは必要ありません。

Referenceでは、
「Referense」のプルダウンメニューから
Internal Bypassed on P3.2(P0.3でも大丈夫)を選びます。
高精度の基準電圧を持っていても、ノイズは避けられません。
よって基準電圧とGNDの間にコンデンサを追加してノイズ対策をします。

全ての設定が終わるとこんな感じになります。


設定が終わってOKをクリックしたら
ΔΣADCのコンポーネントがシングルエンド入力に変わっているはずです。

シングルエンド入力の側とアナログ入力側をつなぎましょう。

これで大まかな設定が終わりました。
次はPSoC5LP全体の設定をしていきましょう。
先ずはピンの設定をしていきましょう。
適当で良いです。
1μFのコンデンサはここで登場します。
繋げ方は下の図のように繋げます。



クロックもそのままでも大丈夫だと思いますが、
PLLは24MHzから48MHzにしておいた方がよいでしょう。

そして、今まで触れていないところに触れたいと思います。
「Pins」のタブと同じ列にある「System」のタブを開きます。

このSystemのタブではプログラムの書き込み、デバッグの方法、
どう言う電圧で稼働させているかについての設定が出来ます。

 Systemの画面をスクロールさせるとVdddやVssaについての設定が出ていきます。
スクロールした状態ではVdddからVddio3まで5.0Vとなっているはずです。

ボードによっても異なりますがCQ出版のボードは3.3Vで動かすため
VdddからVddio3までを3.3と入力します。

ここまで終わったら、1度コンパイルします。
今回は長いのでmain.cを書いておきます。

#include <project.h>
#include <stdio.h>//sprintf()を使うのでこれは追加する
int main()
{
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    LCD_Char_1_Start();
    //確認用なのでここの部分はあっても無くてもいい。
    LCD_Char_1_Position(0,0);
    LCD_Char_1_PrintString("test");
    CyDelay(500);
    LCD_Char_1_ClearDisplay();
    //ここまではあっても無くてもいい
    ADC_DelSig_1_Start();//ΔΣ使うよ宣言
    int32_t get=0,mvout=0;//戻り値を入れる場所
    double temper=0;//電圧値⇒温度変換用
    char outget[10];//文字変換した後に入れる場所
        CyGlobalIntEnable; /* Uncomment this line to enable global interrupts. */
    ADC_DelSig_1_StartConvert();//ΔΣ変換スタート
    for(;;)
    {
        /* Place your application code here. */
        ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_WAIT_FOR_RESULT);//変換まで待つ
        get = ADC_DelSig_1_GetResult32();//変換数値を入れる
        LCD_Char_1_Position(0,0);
        LCD_Char_1_PrintU32Number(get);//uint32をそのまま出力
        mvout = ADC_DelSig_1_CountsTo_uVolts(get);//変換された数値をμVに変換する
        LCD_Char_1_Position(0,8);
        LCD_Char_1_PrintU32Number(mvout);
        LCD_Char_1_PrintString("uV");
        //電圧値を温度用に計算させる
        temper = mvout;
        temper = temper/1000;
        temper = temper-600.0;
        temper = temper/10.0;
        //計算おしまい
        sprintf(outget,"%.2f",temper);//数値を文字変換する。
        LCD_Char_1_Position(1,0);
        LCD_Char_1_PrintString(outget);
        //LCD_Char_1_PutChar(LCD_Char_1_CUSTOM_0);//LCDのカスタムモードで「℃」を作った場合
        LCD_Char_1_PrintString("C");//℃の代わり
       
    }
}

/* [] END OF FILE */


書けたらもう一度コンパイルをして、おしまい。

ピンへの接続が終わったら、書きこんでみましょう。
変換値、電圧値、温度が表記されていれば成功(/・ω・)/。


これでΔΣADCのおおよその全貌が見えてきました。
ADCはサンプルレートが上がる、もしくはビット数が上がれば
ノイズやエリアジングも気にしなければなりません。
今回はビックループでのサンプリングをしましたが
入力のピン数が増えれば、割り込みを使う場合や
サンプリングレートが高ければDMAも使わないと
CPUだけでは正しい計測が出来ません。

高級仕様なのでmb*dの様に簡単には行きませんが
真面目に計測をしたい場合ではこれ位必要でしょう。
また、差動入力も選べますからホイットストーンブリッジも大丈夫です。

私も勉強中ではありますが、これはまだ序の口でしょう…。