センサ・フュージョンもディープ・ラーニングも!
ラズパイ用ハードウェア・アクセラレート基板「PiSoC」
 写真3 本誌と同時発売のTSoC専用拡張ボード「PiSoC」
写真3 本誌と同時発売のTSoC専用拡張ボード「PiSoC」
付録基板とラズベリー・パイを組み合わせて動かすことができる.ビット・トレード・ワンのオンライン・ショップで購入できる(
ADCQ1904)
●こんなボード
 付録基板にLinuxコンピュータ・ボードのラズベリー・パイを合体させれば,話題のIoT(Internet of Things)端末として使えるようになり,インターネット上のクラウド・サービスとも連携できます.画像処理やAIのディープ・ラーニングなど,今どきのアプリケーションも試せるようになります.PSoCは,ラズベリー・パイが苦手なアナログ入出力機能を豊富に備えているので,合体することで弱点を補えます.
●基本構成

 図1 PiSoCの全体ブロック
図1 PiSoCの全体ブロック
 図2 PiSoCの部品配置
図2 PiSoCの部品配置
裏面に±50ppmの高精度クロックを供給する水晶発振器を搭載
・
回路図はこちら
・
端子一覧はこちら
▼
シリアル通信機能
 この基板は,次に示す3つのシリアル通信機能を持っています.いずれもPSoCのSCB(Serial Communication Block)コンポーネントを使って通信します.
(1)USBシリアル変換アダプタ経由でパソコンと通信するUARTインターフェース(SCB0)
(2)ラズベリー・パイと通信するUARTインターフェース(SCB1)
(3)キャラクタLCDと通信するI2Cインターフェース(SCB2)
▼
電源
 PiSoCの電源は,パソコン通信用UARTインターフェースのJP2から供給します.
 ラズベリー・パイと合体すれば,ラズベリー・パイ接続コネクタJP1から供給できます.
▼
ブザー
 ブザーLS1は,PWM信号の出力ピンに接続されています.TCPWMコンポーネントを配置して,周波数を設定するだけで,ブザーを鳴らすことができます.
▼
アナログ入力
 ボリュームVR1は,アナログ入力の1つとして搭載しています.基本的なA-Dコンバータの実験や,アナログ的に設定値を入力するときに役立ちます.
 この基板は,静電容量式タッチ・センサ・コントローラ(CapSense)を内蔵するPSoCを搭載しています.この機能を試せるように,CapSense用のタッチ・パッドを配置しています.
 端子台TB1~4とGroveコネクタCN1に接続されているANALOG1~4,GROVE1,2の6本の信号は,いずれもA-Dコンバータへ入力できます.
▼
ユニバーサル・ランド
 この基板だけでPSoCの全機能を網羅するのは厳しいので,自分のほしい回路を後付けできるようにユニバーサル・ランドを用意しました.
 スペースはあまり広くありませんが,自由に回路うを追加したり,改造したりすることができます.
▼
水晶発振器
 基板の裏面には,水晶発振器を実装しました.
 TSoCに搭載されているPSoC 4100Sは,クロック発振回路を内蔵していますが,周波数の精度は±2%とあまり高くありません.A-Dコンバータで使うと,サンプリング周波数の偏差やジッタの問題になります.
 水晶発振器は,周波数の精度が保証されているので,高精度なA-D変換ができるようになります.
▼
書き込み機能
 PiSoCは,PSoC専用のプログラマ・デバッガMiniProg3を接続するデバッガ・コネクタCN3を備えています.廉価な評価基板のPSoC Pioneer Kitに付属するおまけのプログラマ・デバッガKitProgも接続できます.
使い方
 実際にPiSoCを動かしながら,各機能を使ってみるための資料を作成しました.
●ステップ1:ブザーを鳴らす
 最初は,LEDをチカチカさせながらブザーを鳴らしてみます.
▼
手順1:新規プロジェクトを作成する
 PSoC Creatorを起動して,空の新規プロジェクトを作成します.新規プロジェクトの作成方法は特設 第3章を参照してください.
▼
手順2:Pinコンポーネントの配置と設定
 LEDとブザーを駆動するために,出力ピンを設定します.ワークスペース・エクスプローラの[TopDesign.cysch]をダブルクリックして,スケマチック・デザイン画面を開きます.コンポーネント・カタログ内の[Ports and Pins]-[Digital Output Pin]を選択して,スケマチック・デザイン画面へドラッグ&ドロップします.ここでは,LED用とブザー用の2つのピンを配置します.
 LED用のPinコンポーネントをダブルクリックして,設定画面を開きます.
図3のように「Digital output」にチェックを入れ,「HW connection」のチェックを外します.ここではピン名を「Pin_LED」にしました.
 図3 LED用Pinコンポーネントの設定
図3 LED用Pinコンポーネントの設定
 同じくブザー出力ピンも設定します.Pinコンポーネントをダブルクリックして設定画面が開いたら,「Digital output」と「HW connection」にチェックを入れます.ピン名は「Pin_Buzzer」としました.
▼
手順3:TCPMWコンポーネントの配置と設定
 いろいろな周波数でブザーを鳴らせるように,TCPWMコンポーネントを配置します.
 コンポーネント・カタログ内の[Digital]-[Finctions]-[PWM(TCPWM mode)]を選択してドラッグ&ドロップします.コンポーネント名は「PWM_1」のままとしました.
 TCPWMコンポーネントを駆動するクロックを準備します.コンポーネント・カタログ内の[System]-[Clock]を選択してドラッグ&ドロップします.Clockコンポーネントの設定画面を開き,「Frequency」の設定を「1MHz」にします.コンポーネント名は「Clock_1」のままとします.
 TCPWMコンポーネントをダブルクリックして,設定画面を開きます.
図4のように[Configuration]タブの画面で「PWM」にチェックを入ます.次に,[PWM]タブの画面で分周周期を設定します.「Period」を「1000」,「Compare」を「500」にしました.
 これでデューティ50%,1kHzの方形波が出力されます.
 図4 TCPWMコンポーネントの設定画面
図4 TCPWMコンポーネントの設定画面
▼
手順4:配線
 スケマチック・デザイン画面で,
図5のようにClock_1とPin_BuzzerをPWM_1に接続します.
 コンポーネント同士を配線する方法は,特設 第3章を参照してください.
 図5 各コンポーネントの配置と配線
図5 各コンポーネントの配置と配線
▼
手順5:Bootloadableコンポーネントの配置
 USBシリアル変換アダプタ経由でパソコンからプログラムの書き込みが行えるように,Bootloadableコンポーネントを配置します.
 Bootloadableコンポーネントの設定方法は,特設 第3章を参照してください.
▼
手順6:ピン配置
 図6に示すとおりPSoC 4100Sのピン配置を設定します.
 ワークスペース・エクスプローラの[Design Wide Resouces]-[Pins]を選択して,ピン設定画面を開きます.
 Pin_Buzzerは[P3-4]に設定します.Pin_LEDは[P0-3]に設定します.
 図6 ピン配置の設定
図6 ピン配置の設定
▼
手順7:ハードウェアをビルドする
 メニュー・バーから[Build]-[Buildプロジェクト名]を選択するか,Buildをクリックして,ハードウェアをビルドします.
 実行時にエラーが出なければ,ハードウェア設計はこれで完了です.
▼
手順8:プログラムを作る
 リスト1に示すプログラムを作成します.
 ワークスペース・エクスプローラ内の[main.c]をダブルクリックして,テキスト・エディタ画面を開きます.
 最初にLチカのプログラムを記述します.LEDピンは次のように記述すれば制御できます.
・点灯時      :Pin_LED_Write(1);
・消灯時      :Pin_LED_Write(0);
・ウェイト(500ms):CyDelay(500)
 次にブザーを鳴らすプログラムを記述します.ブザー用のピンは次のように記述すれば制御できます.
・鳴動時:PWM_1_Start()
・消音時:PWM_1_Stop()
リスト1 ブザー鳴動プログラム(main.c)
    
        
            | #include "project.h" 
 int main(void)
 {
 CyGlobalIntEnable; /* Enable global interrupts. */
 
 for(;;)
 {
 Pin_LED_Write(1);
 PWM_1_Start();
 CyDelay(500);
 Pin_LED_Write(0);
 PWM_1_Stop();
 CyDelay(500);
 }
 }
 | 
    
 プログラムの作成が完了したら,再度ビルドしてください.実行時にエラーが出なければ,プログラムの作成は完了です.
▼
手順9:書き込み
 ブートローダ用書き込みツール「Bootloader Host」を起動し,ビルドで作成されたバイナリ形式の書き込みファイル(.cyacdファイル)を書き込みます.
 ファイルのパスを指定して,書き込みボタンをクリックすると,書き込みが実行します.
 TSoCのジャンパ・ピンを右側(ブートローダ・モード)にすることを忘れないようにしてください.
●ステップ2:キャラクタLCDを表示させる
 PiSoCは,8文字×2列のI
2CキャラクタLCDモジュールAQM0802A-RN-GBW(秋月電子通商)が搭載されています.ここでは,このLCDに文字を表示させます.
 キャラクタLCDの制御は,SCBコンポーネントを使ってI
2C通信で行います.PSoC 4100Sには,キャラクタLCDを駆動するための専用コンポーネントが用意されているので,これも使います.
図7に示すのは,各コンポーネント配置後のようすです.
 図7 キャラクタLCD制御機能を追加した後の各コンポーネントの配置と配線
図7 キャラクタLCD制御機能を追加した後の各コンポーネントの配置と配線
▼
手順1:SCBコンポーネントの配置と設定
 コンポーネント・カタログの[Communications]-[I2C]-[I2C(SCB mode)]を選択して,スケマチック・デザイン画面にドラッグ&ドロップします.
 I2Cコンポーネントをダブル・クリックして設定画面を開きます.[I2CBasic]タブを選択して,「Mode」を[Master]にします.「Data rate(kbps):」は[400]にします.モジュール名は「I2C_1」のままとします.
▼
手順2:LCDコンポーネントの配置と設定
 コンポーネント・カタログから[Display]-[Character LCD with I2C interface]を選択してドラッグ&ドロップします.
 I2C_LCDコンポーネントをダブルクリックして設定画面を開きます.[General]タブの「I2C master instance name」は,初期設定の「I2C_1」のままにします.「Default I2C address(8bit)」は,キャラクタLCDのスレーブ・アドレス「0x7c」に設定します.「Command fomat」の「Custom format」にチェックを入れます.
 [Custom Commands]タブをクリックして,今回使うLCDモジュールのカスタム・コマンドを追加します.追加内容は
図8のとおりです.ここでは,モジュール名を「I2C_LCD」にしました.
 図8 キャラクタLCDのカスタム・コマンド設定(拡大)
図8 キャラクタLCDのカスタム・コマンド設定(拡大)
▼
手順3:ピン配置
 ワークスペース・エクスプローラの[Design Wide Resouces]-[Pins]を選択して,ピン設定画面を開きます.
 
図9のように,SCLは「P1-2」に設定します.SDAは「P1-3」に設定します.
 図9 キャラクタLCDとのI2C通信ピンの配置
図9 キャラクタLCDとのI2C通信ピンの配置
▼
手順4:ハードウェアをビルドする
 メニュー・バーから[Build]-[Buildプロジェクト名]を選択するか,Buildをクリックして,ハードウェアをビルドします.
 実行時にエラーが出なければ,ハードウェア設計はこれで完了です.
▼
手順5:プログラムを作成する
 リスト2に示す,簡単な文字表示をさせるプログラムを作成します.
 ワークスペース・エクスプローラ内の[main.c]をダブルクリックして,テキスト・エディタ画面を開きます.
 最初に次のコマンドを記述して,I2CコンポーネントとI2C_LCDコンポーネントを動作開始します.
I2C_1_Start();
I2C_LCD_Start();
リスト2 キャラクタLCDに文字を表示させるサンプル・プログラム
    
        
            | #include "project.h" 
 
 void I2C_LCD_Initialize(){
 I2C_LCD_Function_set();
 I2C_LCD_Function_setEX();
 I2C_LCD_Internal_OSC_frequency();
 I2C_LCD_Contrast_set();
 I2C_LCD_Power_ICON_Contrast_control();
 I2C_LCD_Follower_control();
 CyDelay(200);
 I2C_LCD_Function_set();
 I2C_LCD_Display_ON_OFF_control();
 I2C_LCD_ClearDisplay();
 CyDelay(10);
 }
 
 void I2C_LCD_Cursol_Position(uint8 row, uint8 col) {
 if(row == 0){
 I2C_LCD_SetDDRAM(0x80 + col);
 }else{
 I2C_LCD_SetDDRAM(0xC0 + col);
 }
 }
 
 
 int main(void)
 {
 CyGlobalIntEnable; /* Enable global interrupts. */
 I2C_1_Start();
 I2C_LCD_Start();
 
 I2C_LCD_Initialize();
 
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("HELLO");
 
 CyDelay(500u);
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintString("PiSOC!!");
 
 
 for(;;)
 {
 Pin_LED_Write(1);
 PWM_1_Start();
 CyDelay(500);
 Pin_LED_Write(0);
 PWM_1_Stop();
 CyDelay(500);
 }
 }
 | 
    
 これでLCDモジュールと通信できるようになります.通信を開始したら,まずはLCDモジュールを初期化します.
 LCDモジュールを初期化した後は,文字を表示させる記述を行います.キャラクタLCDの表示コマンドは,LCDコンポーネントで用意しているので,次に示すようなとても簡単な記述で文字を表示できます.
 I2C_LCD_PrintString("文字列");
 数字を表示させたいときは,次のように記述します.
 I2C_LCD_PrintNumber(数値)
▼
LCDモジュール初期設定の意味
 LCDモジュールAQM0802A-RN-GBWは,3.3V電源による駆動を推奨していますが,PiSoCの電源は5Vです.LCDモジュールだけのためにわざわざ3.3Vを準備するのは効率が悪いので,PiSoCでは5V駆動としています.
 LCDモジュールは,初期状態だと3.3Vでの駆動が前提となっているので,内部の昇圧回路が有効になっています.PiSoCでは,初期設定で昇圧回路を停止させて使います.供給電圧の変更に伴い,コントラスト設定値も調整しています.
●ステップ3:アナログ入力の値をLCDに表示させる
 A-Dコンバータでアナログ電圧を読み込んで,結果(電圧値)をキャラクタLCDに表示してみましょう.
 ここでは,端子台TB1~4とボリュームVR1の電圧をA-Dコンバータで読み込んでみます.
▼
手順1:ADCコンポーネントの配置と設定
 A-Dコンバータのコンポーネントを用意します.今回は一度に2つのアナログ信号を読み込むので,チャネル切り替えが可能な逐次比較型A-Dコンバータを使います.
 コンポーネント・カタログから[Analog]-[ADC]-[Sequencing SAR ADC]を選択して,スケマチック・デザイン画面にドラッグ&ドロップします.
 ADC_SAR_SEQコンポーネントをダブルクリックして,設定画面を開きます.
図10のように,[General]タブをクリックして,「Clock frequency」を「1000」kHz(1MHz),「Vref select」を[VDDA](電源電圧,PiSoCでは5V)に設定しました.
 図10 逐次比較型A-Dコンバータの設定画面を開いてアナログ信号を取り込めるように設定する(拡大)
図10 逐次比較型A-Dコンバータの設定画面を開いてアナログ信号を取り込めるように設定する(拡大)
 次に[Channels]タブの[Sequences channels]を「5」にします.これでA-Dコンバータが5チャネル使えるようになります.設定画面の下に表示されている表のチャネル数が増えるので,0~4までの「Enable」にチェックを入れます.
図11のように,「Resolution」は12ビット,「Mode」はすべて「Single」にします.
 コンポーネント名は「ADC」にしました.
 図11 [Channels]タブを開いて逐次比較型A-Dコンバータのチャネル数,分解能,モードを設定する
図11 [Channels]タブを開いて逐次比較型A-Dコンバータのチャネル数,分解能,モードを設定する
▼
手順2:アナログ・ピンの配置
 アナログ信号を入力するアナログ・ピン・コンポーネントを用意します.
 アナログ・ピンは,端子台TB1~4と,PiSoCに実装されているボリューム
VR1の5個分を用意します.
 コンポーネント・カタログから[Ports and Pins]-[Analog Pin]を選択し,スケマチック・デザイン画面にドラッグ&ドロップします.配置するのは1つだけです.
 アナログ・ピン・コンポーネントAnalog Pin_1をダブルクリックして,設定画面を開きます.コンポーネント名を「AD1」に変更し,[Pins] タブを開いて「Number of pins」を「5」にします.するとPinが5チャネル分用意されます.
 「Type」は[Analog]にチェックを入れます.するとワーニングが出るので,[Mapping]タブの[Contiguous]のチェックを外します.
▼
手順3:配線
 スケマチック・デザイン画面で
図12のように各コンポーネントを配線します.
 図12 逐次比較型A-Dコンバータ追加後の各コンポーネントの配置・配線
図12 逐次比較型A-Dコンバータ追加後の各コンポーネントの配置・配線
▼
手順4:ピン配置
 ワークスペース・エクスプローラの[Design Wide Resouces]-[Pins]を選択して,ピン設定画面を開きます.
 各端子とピン・コンポーネントの接続は
図13のとおり設定します.
・AD0:ボリューム
VR1が接続されている「P2-0」
・AD1:端子台TB1が接続されている「P2-1」
・AD2:端子台TB2が接続されている「P2-2」
・AD3:端子台TB3が接続されている「P2-3」
・AD4:端子台TB1が接続されている「P2-4」
 図13 A-Dコンバータのピン配置
図13 A-Dコンバータのピン配置
▼
手順5:ハードウェアをビルドする
 メニュー・バーから[Build]-[Buildプロジェクト名]を選択するか,Buildをクリックして,ハードウェアをビルドします.
 実行時にエラーが出なければ,ハードウェア設計はこれで完了です.
▼
手順6:プログラムの作成
 リスト3に示すのは,PiSoCのボリューム
VR1の値,および端子台TB1~4の値を500ms間隔でLCD表示するプログラムです.このプログラムを作成します.
 ワークスペース・エクスプローラ内の[main.c]をダブルクリックして,テキスト・エディタ画面を開きます.
 まずはA-D変換を開始するコマンドを記述します.次の記述でA-Dコンバータ・コンポーネントをスタートさせます.
ADC_Start();
ADC_StartConvert();
 A-D変換が完了するのを待つ記述は次のとおりです.
ADC_IsEndConversion(ADC_WAIT_FOR_RESULT);
 A-D変換が完了したら,次の記述でA-D変換値を取得します.
Aval[ch] = (uint16)ADC_GetResult16(ch);
 リスト3のプログラムは,AD0~4までのアナログ値を表示した後,ブザーを1 回鳴らすようにしています.
 基板上のGroveコネクタCN1のピンも,同じ要領でアナログ入力として使えます.
リスト3 A-Dコンバータでアナログ信号を取り込んだ値をLCDに表示させるプログラム
    
        
            | #include "project.h" 
 void I2C_LCD_Initialize(){
 I2C_LCD_Function_set();
 I2C_LCD_Function_setEX();
 I2C_LCD_Internal_OSC_frequency();
 I2C_LCD_Contrast_set();
 I2C_LCD_Power_ICON_Contrast_control();
 I2C_LCD_Follower_control();
 CyDelay(200);
 I2C_LCD_Function_set();
 I2C_LCD_Display_ON_OFF_control();
 I2C_LCD_ClearDisplay();
 CyDelay(10);
 }
 
 void I2C_LCD_Cursol_Position(uint8 row, uint8 col) {
 if(row == 0){
 I2C_LCD_SetDDRAM(0x80 + col);
 }else{
 I2C_LCD_SetDDRAM(0xC0 + col);
 }
 }
 
 int main(void)
 {
 uint16 Aval[5];
 
 CyGlobalIntEnable; /* Enable global interrupts. */
 I2C_1_Start();
 I2C_LCD_Start();
 I2C_LCD_Initialize();
 
 ADC_Start();
 ADC_StartConvert();
 
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("HELLO");
 
 CyDelay(500u);
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintString("PiSOC!!");
 
 for(;;)
 {
 ADC_IsEndConversion(ADC_WAIT_FOR_RESULT);
 for(int8 ch=0; ch<=4; ch++){
 Aval[ch] = ADC_GetResult16(ch);
 }
 I2C_LCD_ClearDisplay();
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("Volume");
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintNumber(Aval[0]);
 CyDelay(500);
 for(int8 ch=1; ch<=4; ch++){
 I2C_LCD_ClearDisplay();
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("Analog:");
 I2C_LCD_PrintNumber(ch);
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintNumber(Aval[ch]);
 CyDelay(500);
 }
 Pin_LED_Write(1);
 PWM_1_Start();
 CyDelay(100);
 Pin_LED_Write(0);
 PWM_1_Stop();
 }
 }
 | 
    
●ステップ4:UARTでパソコンとシリアル通信
 ステップ3では,A-Dコンバータで取得したアナログ信号の値をキャラクタLCDに表示していましたが,UARTを使えば外部のコンピュータにもデータを送信できます.PiSoCは,USBシリアル変換アダプタを使えばパソコンと通信できます.
 ここでは,UARTを使ってステップ3で取得したアナログ・データをパソコンに送信してみます.パソコンでは,ターミナル・ソフトを使ってUART信号を受信します.ここではTera Termを使います.
▼
手順1:UARTコンポーネントの配置と設定
 図14のように,コンポーネント・カタログから[Communications]-[UART(SCB mode)]を選択してドラッグ&ドロップします.
 図14 UART通信機能を追加した後の各コンポーネントの配置・配線
図14 UART通信機能を追加した後の各コンポーネントの配置・配線
 UARTコンポーネントをダブルクリックして,設定画面を開きます.ここではコンポーネント名を「UART_PC」にしました.
 [UART Basic]タブの「Baud rate(bps)」を[9600]に設定します.
▼
手順2:ピン配置
 ワークスペース・エクスプローラの[Design Wide Resouces]-[Pins]を選択して,ピン設定画面を開きます.
 各端子とピン・コンポーネントの接続は
図15のとおり設定します.RXは「P1-0」に,TXは「P1-1」に設定します.
 図15 UARTインターフェースのピン配置
図15 UARTインターフェースのピン配置
▼
手順3:ハードウェアをビルドする
 メニュー・バーから[Build]-[Buildプロジェクト名]を選択するか,Buildをクリックして,ハードウェアをビルドします.
 実行時にエラーが出なければ,ハードウェア設計はこれで完了です.
▼
手順4:プログラムの作成
 リスト4に示すのは,端子台TB1~4で取得したアナログ電圧値をパソコンに出力するプログラムです.このプログラムを作成します.
 ワークスペース・エクスプローラ内の[main.c]をダブルクリックして,テキスト・エディタ画面を開きます.
 次の記述でUARTを動作開始させます.
UART_PC_Start();
 次の記述でパソコンのターミナル上に文字を表示させます.
UART_PC_UartPutString("文字列");
 ターミナル上で文字を改行させたいときは,次のように記述して改行コードを送信します.
UART_PC_UartPutCRLF(1);
リスト4 A-Dコンバータで取り込んだ値をUART送信するプログラム
    
        
            | #include "project.h" 
 void I2C_LCD_Initialize(){
 I2C_LCD_Function_set();
 I2C_LCD_Function_setEX();
 I2C_LCD_Internal_OSC_frequency();
 I2C_LCD_Contrast_set();
 I2C_LCD_Power_ICON_Contrast_control();
 I2C_LCD_Follower_control();
 CyDelay(200);
 I2C_LCD_Function_set();
 I2C_LCD_Display_ON_OFF_control();
 I2C_LCD_ClearDisplay();
 CyDelay(10);
 }
 
 void I2C_LCD_Cursol_Position(uint8 row, uint8 col) {
 if(row == 0){
 I2C_LCD_SetDDRAM(0x80 + col);
 }else{
 I2C_LCD_SetDDRAM(0xC0 + col);
 }
 }
 
 void UART_PC_PutDec4(uint16 c)
 {
 if (( c > 0) && (c < 10000)){
 if (c >= 1000){
 UART_PC_UartPutChar((c/1000)+'0');
 }
 else UART_PC_UartPutChar(0+'0');
 c = c%1000;
 if (c >= 100){
 UART_PC_UartPutChar((c/100)+'0');
 }
 else UART_PC_UartPutChar(0+'0');
 c = c%100;
 if (c >= 10){
 UART_PC_UartPutChar((c/10)+'0');
 }
 else UART_PC_UartPutChar(0+'0');
 c = c%10;
 UART_PC_UartPutChar(c+'0');
 }
 else UART_PC_UartPutChar(0+'0');
 }
 
 int main(void)
 {
 uint16 Aval[5];
 
 CyGlobalIntEnable; /* Enable global interrupts. */
 I2C_1_Start();
 I2C_LCD_Start();
 I2C_LCD_Initialize();
 
 ADC_Start();
 ADC_StartConvert();
 
 UART_PC_Start();
 UART_PC_UartPutString("Hello!!  PiSoC");
 UART_PC_UartPutCRLF(1);
 UART_PC_UartPutString("UART TEST");
 UART_PC_UartPutCRLF(1);
 
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("HELLO");
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintString("PiSOC!!");
 
 CyDelay(500u);
 for(;;)
 {
 ADC_IsEndConversion(ADC_WAIT_FOR_RESULT);
 for(int8 ch=0; ch<=4; ch++){
 Aval[ch] = ADC_GetResult16(ch);
 }
 I2C_LCD_ClearDisplay();
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("Volume");
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintNumber(Aval[0]);
 CyDelay(500);
 for(int8 ch=1; ch<=4; ch++){
 I2C_LCD_ClearDisplay();
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("Analog:");
 I2C_LCD_PrintNumber(ch);
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintNumber(Aval[ch]);
 CyDelay(500);
 }
 
 for(int8 ch=1; ch <=4; ch++){
 UART_PC_UartPutString("Analog");
 UART_PC_UartPutChar(ch+'0');
 UART_PC_UartPutString(":");
 UART_PC_PutDec4(Aval[ch]);
 UART_PC_UartPutString(", ");
 }
 UART_PC_UartPutCRLF(1);
 
 Pin_LED_Write(1);
 PWM_1_Start();
 CyDelay(100);
 Pin_LED_Write(0);
 PWM_1_Stop();
 }
 }
 | 
    
 ここでは,
UART_PC_UartPutChar()を使って,簡単な関数を作って,パソコンに文字を送信しました.
 
図16に示すのは,UARTでPiSoCから文字データを受信したパソコンのターミナル画面です.このデータをCSV形式で保存すれば,表計算アプリケーションで読み込んで加工できます.
 図16 PSoCの逐次比較型A-Dコンバータで取り込んだ値をUART経由でパソコンで表示させたようす
図16 PSoCの逐次比較型A-Dコンバータで取り込んだ値をUART経由でパソコンで表示させたようす
▼
ラズベリー・パイとの通信方法
 PiSoCには,もう1つのSCBコンポーネント(UART)でラズベリー・パイと通信できるようにしています.
 ラズベリー・パイとの通信に使うピンは,TXDが「P3-1」,RXDが「P3-0」です.UARTの設定や使い方は,ここで説明した内容とまったく同じです.
●ステップ5:静電容量式タッチ・センサを試す
 PSoCの大きな特徴は,静電容量式タッチ・センサ・コントローラ(CapSense)を備えている点です.
 ここでは,PiSoCに用意されているタッチ・パッドを使って,CapSense機能を試してみましょう.
▼
手順1:CapSenseコンポーネントの配置と設定
 コンポーネント・カタログから[CapSense]-[CapSense]を選択して,
図17のようにスケマチック・デザイン画面にドラッグ&ドロップします.
 図17 タッチ・センサ機能追加後の各コンポーネントの配置・配線
図17 タッチ・センサ機能追加後の各コンポーネントの配置・配線
 Capsenseコンポーネントをダブルクリックして設定画面を開きます.コンポーネント名は「CapSense」にしました.「CSD Tuning mode」は[SmartSence(Full Auto-Tune)]のままにします.
 
図18のように,[Basic]タブの「リスト」にある[+]をクリックすると,CapSenseのボタンが追加できます.ここでは,タッチ・パッドの種類が選べます.今回は[Button]を選択します.
 
 図18 CapSenseコンポーネントの設定画面
図18 CapSenseコンポーネントの設定画面
▼
手順2:ピン配置
 ワークスペース・エクスプローラの[Design Wide Resouces]-[Pins]を選択して,ピン設定画面を開きます.
 各端子とピン・コンポーネントの接続は
図19のとおり設定します.CapSence:Snsは「P2-5」に,CapSense:Cmodは「P4-1」に設定します.
 図19 タッチ・パッドのピン配置
図19 タッチ・パッドのピン配置
▼
手順3:ハードウェアをビルドする
 メニュー・バーから[Build]-[Buildプロジェクト名]を選択するか,Buildをクリックして,ハードウェアをビルドします.
 実行時にエラーが出なければ,ハードウェア設計はこれで完了です.
▼
手順4:プログラムの作成
 リスト5に示すのは,タッチ・パッドのサンプル・プログラムです.タッチ・パッドに触れると,1回だけアナログ電圧値を取得し,キャラクタLCDとパソコンにデータを送信します.送信後は,次の指示を待ちます.このプログラムを作成します.
 ワークスペース・エクスプローラ内の[main.c]をダブルクリックして,テキスト・エディタ画面を開きます.
 ここでは,サイプレス セミコンダクタのリファレンス・マニュアルの内容を流用してCapSenseを動かしてみます.
 次の記述でCapSenseコンポーネントの動作とスキャンを開始します.
CapSense_Start();
CapSense_ScanAllWidgets();
 次の記述で,タッチ・パッドの取得判別を行います.
if(CapSense_NOT_BUSY == CapSense_IsBusy()){
  CapSense_ProcessAllWidgets();
  CapSense_RunTuner();
  if(CapSense_IsSensorActive(0,0)){
    //この部分に,タッチされたときの処理を記述
  }
  CapSense_ScanAllWidgets();
}
リスト5 タッチ・パッドのサンプル・プログラム
    
        
            | #include "project.h" 
 //LCDを初期化するための関数
 void I2C_LCD_Initialize(){
 I2C_LCD_Function_set();
 I2C_LCD_Function_setEX();
 I2C_LCD_Internal_OSC_frequency();
 I2C_LCD_Contrast_set();
 I2C_LCD_Power_ICON_Contrast_control();
 I2C_LCD_Follower_control();
 CyDelay(200);
 I2C_LCD_Function_set();
 I2C_LCD_Display_ON_OFF_control();
 I2C_LCD_ClearDisplay();
 CyDelay(10);
 }
 
 void I2C_LCD_Cursol_Position(uint8 row, uint8 col) {
 //LCDのカーソルを移動させる関数 rowとColを設定します
 if(row == 0){
 I2C_LCD_SetDDRAM(0x80 + col);
 }else{
 I2C_LCD_SetDDRAM(0xC0 + col);
 }
 }
 //UARTで数値4ケタを出力する関数
 void UART_PC_PutDec4(uint16 c)
 {
 if (( c > 0) && (c < 10000)){
 if (c >= 1000){
 UART_PC_UartPutChar((c/1000)+'0');
 }
 else UART_PC_UartPutChar(0+'0');
 c = c%1000;
 if (c >= 100){
 UART_PC_UartPutChar((c/100)+'0');
 }
 else UART_PC_UartPutChar(0+'0');
 c = c%100;
 if (c >= 10){
 UART_PC_UartPutChar((c/10)+'0');
 }
 else UART_PC_UartPutChar(0+'0');
 c = c%10;
 UART_PC_UartPutChar(c+'0');
 }
 else UART_PC_UartPutChar(0+'0');
 }
 
 int main(void)
 {
 uint16 Aval[5];
 uint8 CSstate = 0;
 uint8 AD_En = 0;
 
 CyGlobalIntEnable; /* Enable global interrupts. */
 I2C_1_Start();
 I2C_LCD_Start();
 I2C_LCD_Initialize();
 
 ADC_Start();
 ADC_StartConvert();
 
 UART_PC_Start();
 
 CapSense_Start();
 CapSense_ScanAllWidgets();
 
 UART_PC_UartPutString("Hello!!  PiSoC");
 UART_PC_UartPutCRLF(1);
 UART_PC_UartPutString("UART TEST");
 UART_PC_UartPutCRLF(1);
 
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("HELLO");
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintString("PiSOC!!");
 
 CyDelay(500u);
 for(;;)
 {
 //CapSense検出動作
 if(CapSense_NOT_BUSY == CapSense_IsBusy()){
 CapSense_ProcessAllWidgets();
 CapSense_RunTuner();
 if(CapSense_IsSensorActive(0,0)){
 if(CSstate == 0){
 CSstate = 1;
 //CapSense検出時の動作内容 本プログラムでは2個のフラグを1に設定
 AD_En = 1;
 }
 }
 else {
 CSstate = 0;
 }
 CapSense_ScanAllWidgets();
 }
 
 if(AD_En == 1 ){
 AD_En = 0;
 
 Pin_LED_Write(1);
 PWM_1_Start();
 CyDelay(100);
 Pin_LED_Write(0);
 PWM_1_Stop();
 
 //AD値取得処理
 ADC_IsEndConversion(ADC_WAIT_FOR_RESULT);
 for(int8 ch=0; ch<=4; ch++){
 Aval[ch] = ADC_GetResult16(ch);
 }
 //ボリュームのAD値をLCDに表示
 I2C_LCD_ClearDisplay();
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("Volume");
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintNumber(Aval[0]);
 CyDelay(500);
 //端子台のAD値をLCDに表示
 for(int8 ch=1; ch<=4; ch++){
 I2C_LCD_ClearDisplay();
 I2C_LCD_Cursol_Position(0,0);
 I2C_LCD_PrintString("Analog:");
 I2C_LCD_PrintNumber(ch);
 I2C_LCD_Cursol_Position(1,0);
 I2C_LCD_PrintNumber(Aval[ch]);
 CyDelay(500);
 }
 
 //端子台のAD値をパソコンに表示
 for(int8 ch=1; ch <=4; ch++){
 UART_PC_UartPutString("Analog");
 UART_PC_UartPutChar(ch+'0');
 UART_PC_UartPutString(":");
 UART_PC_PutDec4(Aval[ch]);
 UART_PC_UartPutString(", ");
 }
 UART_PC_UartPutCRLF(1);
 }
 }
 }
 | 
    
●ステップ6:外付けの水晶発振器で動作させてみる
 PSoC 4100Sは,クロック発振回路を内蔵していますが,周波数の精度は±2%と低いです.
 PiSoCは,裏面に20MHzの水晶発振器を備えています.
これを使えば,PSoCを±50ppm精度のクロックで駆動できます.A-Dコンバータのサンプリング周波数の精度向上が期待できます.
▼
設定方法
 外付けの水晶発振器を使うための設定を行います.
 ワークスペース・エクスプローラの[Design Wide Resouces]-[Clocks]をダブルクリックして,クロック設定画面を開きます.[SysCLK]の欄をダブルクリックすると,「Configure System Clocks」という画面が開きます.
 
図20のように,「ExtCLK」にチェックを入れて,「Freq(MHz)」で周波数を「20」MHzに設定します.「Accuracy」で誤差を「±50ppm」に設定します.
 「IMO」のチェックを外して無効にし,「HFClk」のクロック選択を[ExCLk(20MHz)]にします.これでクロック源が外付けの水晶発振器になります.
 図20 クロック経路の設定画面(拡大)
図20 クロック経路の設定画面(拡大)
▼
ビルド時にエラーが出た場合
 静電容量式タッチ・センサ・コントローラのCapSenseで内蔵クロックを使う設定になっていると,ビルド時にエラーになります.
 CapSenseコンポーネントの設定画面で[Advanced]タブを選択し,「Modulator clock frequency(kHz)」を「24000」から「20000」に変更します.
▼
ハードウェアをビルドする
 メニュー・バーから[Build]-[Buildプロジェクト名]を選択するか,Buildをクリックして,ハードウェアをビルドします.
 実行時にエラーが出なければ,ハードウェア設計はこれで完了です.
 外部クロックExtClkは,クロック入力専用ピンであるP0-6に自動的に割り振られます.
         * * *
 PiSoCには,そのほかにもユニバーサル・ランド側のTP4,5にOPアンプの入力ピン用の端子を設けています.
 ユニバーサル・ランドを使ってアナログ回路を追加するときに使えるようになっています.ユニバーサル・ランドの周辺には,5V電源とグラウンドも配置しています.
◆参考文献◆
(1)https://itcorp24.blogspot.com/2013/09/i2clcd.html