2021年05月15日

PIC32MX+Harmony3+I2C通信

今回はPIC32MX250F128BをターゲットにMPLAB X v5.45+Harmony3を使用してI2C通信を行いました。その際にポイントとなる設定について紹介します。I2C接続の温湿度センサHS3001の読み込みを行いました。なお、ターゲットへの書き込みはPickit3を使用しまし、MPLAB Xには予め、MPLAB Harmony 3 Launcher(旧名称 MPLAB Harmony Configurator 3)をインストールしています。


@プロジェクトファイル作成
MPLAB XのFile→New ProjectからMPLAB Harmony 3のプロジェクトを作成します。

hi2c1.jpg

AHarmony 3設定
Tools→Embedded→Harmony Configurator 3を選択します。左下のAvailable ComponentsからI2C2をクリックし、I2C2を追加します。SPI1が追加されると左上(Active Components)及び中央(Project Graph)にI2C2が表示されます。
中央(Project Graph)のI2C2をクリックし、右のConfiguration Optionsの設定項目を必要に応じて変更します。通常はデフォルトで問題ありません。

また、今回はデバッグ用途にprintfを使用してuartからデバッグ情報を出力するため、UART2とSTDIOを追加しています。必要に応じてUART2のボーレートを右のConfiguration Optionsから変更してください。

hi2c2.jpg

hi2c3.jpg

Bピンアサイン設定
MHC→Tools→Pin Configurationを選択します。Pin DiagramからI2CのSDA2、SCL2を割り付けします。Pin SettingsからI2Cの外付けプルアップ抵抗を省略するためにRB2、RB3のプルアップを有効にしました。

hi2c4.jpg

Cコード生成
設定完了後にGenerate Codeでコードを生成します。

hi2c5.jpg

DI2C通信関数
I2C通信をするためのコードを追加します。I2C通信関数はSource Files/config/default/peripheral/i2c/master内のplib_i2c2_master.cで定義されています。I2C初期化関数は既にinitialization.cに追加されているため、接続するデバイスに応じてI2C読み書き関数を追加します。I2C読み書きを同時にする場合はI2C2_WriteRead関数、読み込みのみの場合はI2C2_Read、書き込みのみの場合はI2C2_Writeの関数を使用します。なお、STM32のHALライブラリでは8bitアドレス(R/Wのbitを含める)で定義しますが、Harmony3のI2Cアドレスは7bitアドレスを定義します。


#define HS300X_ADDR (0x88>>1)

void Get_HS300X_Data(volatile int16_t *tmp, volatile int16_t *hmd)
{
 uint8_t dat[4];
 int16_t tmp_dat,hmd_dat;
 float tempf;
 float humdf;
 I2C2_Read(HS300X_ADDR,dat,4);
 while(I2C2_IsBusy()==true);
 I2C2_Write(HS300X_ADDR,NULL,0);
 while(I2C2_IsBusy()==true);
 tmp_dat = (dat[2]<<8)+dat[3];
 tmp_dat = tmp_dat>>2;
 hmd_dat = ((dat[0]&0x3F)<<8)+dat[1];
 humdf=(float)hmd_dat/(16383.0f)*100.0f;
 tempf=((float)tmp_dat)/(16383.0f)*165.0f-40.0f;
 *hmd = (int16_t)(humdf*100.0f);
 *tmp = (int16_t)(tempf*100.0f);
 return;
}

温湿度センサHS3001は温湿度を読み出しする際、アドレスのみ書き込みすると測定開始される少し特殊な仕様です。そのため、 I2C2_Write ( HS300X_ADDR, NULL, 0)という空データを書き込む処理が入っています。



posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年05月08日

PIC32MX+Harmony3+SPI通信

今回はPIC32MX250F128BをターゲットにMPLAB X v5.45+Harmony3を使用してSPI通信を行いました。その際にポイントとなる設定について紹介します。SPI接続のSRAM(IS62WVS5128FB)の書き込み、読み込みを行いました。なお、ターゲットへの書き込みはPickit3を使用しまし、MPLAB Xには予め、MPLAB Harmony 3 Launcher(旧名称 MPLAB Harmony Configurator 3)をインストールしています。

@プロジェクトファイル作成
MPLAB XのFile→New ProjectからMPLAB Harmony 3のプロジェクトを作成します。

hspi1.jpg

AHarmony 3設定
Tools→Embedded→Harmony Configurator 3を選択します。左下のAvailable ComponentsからSPI1をクリックし、SPI1を追加します。SPI1が追加されると左上(Active Components)及び中央(Project Graph)にSPI1が表示されます。

中央(Project Graph)のSPI1をクリックし、右のConfiguration Optionsの設定項目を必要に応じて変更します。通常はデフォルトで問題ありません。SPIのデフォルトクロック周波数が低いため、1MHz程度に変更します。

また、今回はデバッグ用途にprintfを使用してuartからデバッグ情報を出力するため、UART2とSTDIOを追加しています。必要に応じてUART2のボーレートを右のConfiguration Optionsから変更してください。

hspi2.jpg

hspi3.jpg

Bピンアサイン設定
MHC→Tools→Pin Configurationを選択します。Pin DiagramからSPI1のSDO1、SDI1、SCK1を割り付けします。また、Pin SettingsからCSとしてRA0をGPIO設定しました。Pin TableからRA0を出力に設定し、通信を安定させるためにプルアップを有効にしました。

hspi4.jpg

hspi5-1.jpg



hspi5.jpg

Cコード生成
設定完了後にGenerate Codeでコードを生成します。

hspi6.jpg

DSPI通信関数
SPI通信をするためのコードを追加します。

hspi7.jpg



SPI通信関数はSource Files/config/default/peripheral/spi/spi_master内のplib_spi1_master.cで定義されています。SPI初期化関数は既にinitialization.cに追加されているため、接続するデバイスに応じてSPI読み書き関数を追加します。SPI読み書きを同時にする場合はSPI1_WriteRead関数、読み込みのみの場合はSPI1_Read、書き込みのみの場合はSPI1_Writeの関数を使用します。なお、SPI1のConfiguration Options、Enable Interrupts設定はデフォルトで有効となっています。そのため、書き込み、読み込みした後はSPI1_IsBusy関数でSPI処理の完了を確認するか、SPI処理後に呼び出す関数をSPI1_CallbackRegisterで事前に登録する必要があります。SPI1_CallbackRegisterのサンプルはこちらに上がっているため、詳細の説明は省略します。今回はSPI1_IsBusy関数でSPI処理の完了を確認しました。

また、SPI通信で必要なCSは自動に設定(通信するときのみCSが自動でLOWになる)できますが、今回は手動でIO操作にしました。ピンアサイン設定でRA0を出力に設定したため、自動でHeader Files/config/default/peripheral/gpio内のplib_gpio.hにGPIO_RA0_Set関数やGPIO_RA0_Clear関数が追加されます。追加されたGPIO関数でCSを操作します。SRAMと通信するための全体のコードは下記です。main.cに下記のコードを追加しました。

#define SRAM_WRITE_CMD 2
#define SRAM_READ_CMD 3


void SramWrite(unsigned char *data, unsigned short length)
{
 unsigned char wcmd[4];
 wcmd[0]=SRAM_WRITE_CMD;
 wcmd[1]=0;//High Addr
 wcmd[2]=0;//Mid Addr
 wcmd[3]=0;//Low Addr

 GPIO_RA0_Clear();
 SPI1_Write(wcmd,4);
 while(SPI1_IsBusy()==true);
 SPI1_Write(data,length);
 while(SPI1_IsBusy()==true);
 GPIO_RA0_Set();
}

void SramRead(unsigned char *data, unsigned short length)
{
 unsigned char wcmd[4];
 wcmd[0]=SRAM_READ_CMD;
 wcmd[1]=0;//High Addr
 wcmd[2]=0;//Mid Addr
 wcmd[3]=0;//Low Addr
 
 GPIO_RA0_Clear();
 SPI1_Write(wcmd,4);
 while(SPI1_IsBusy()==true);
 SPI1_Read(data,length);
 while(SPI1_IsBusy()==true);
 GPIO_RA0_Set();
}


SPI1CONCLRやSPI1CONSET、LATACLR等のレジスタを操作してSPI通信やIO操作を行っていましたが、Harmony3でハードレイヤーが抽象化され、コード自動生成時点で最低限の関数が既に実装されています。設定によってはコード自動生成直後にも関わらず、ビルドエラーが発生してコードの修正が必要な場合がありますが、以前に比べると大分、改善しているように感じました。なお、SDカードといったHarmony3の機能や設定によってはSPI1_ReadやSPI1_Writeといった関数名が変わるため、注意が必要です。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年05月01日

STM32マイコンUART拡張機能

STM32F7、L4、H7シリーズではUART通信をする際に非常に便利な拡張機能があります。今回はUART拡張機能について紹介します。例えばUARTを利用する際に基板のTXとRXを間違えて逆転させてしまったり(回路上でTXとRXをクロスさせることを忘れていた)、フォトカプラを接続するので論理を逆転させたい(通常は論理反転のバッファICやトランジスタ等で追加ハードウェアで論理反転させる)、DMA受信時のエラー処理を無効にしたい(デフォルトではSTM32のUART受信でフレームエラー等が発生するとクリアするまで受信できない)といったことが多々あると思います。そのような場合にUART拡張機能を利用することでハードウェア追加や修正なしにソフトウェア側の設定変更のみで切り替えることが可能です。

UART拡張機能は下記の通りです。

名称機能
UART_ADVFEATURE_TXINVERTTX論理反転
UART_ADVFEATURE_RXINVERTRX論理反転
UART_ADVFEATURE_DATAINVERTデータビット論理反転
UART_ADVFEATURE_SWAPTX、RX入れ替え
UART_ADVFEATURE_RXOVERRUNDISABLE受信エラー無効
UART_ADVFEATURE_DMADISABLEONERRORDMA受信エラー無効
UART_ADVFEATURE_AUTOBAUDRATEオートボーレート有効
UART_ADVFEATURE_MSBFIRSTMSB有効


UART拡張機能の定義はstm32XX_hal_uart.hで下記のように定義されています。

/*!< No advanced feature initialization */
#define UART_ADVFEATURE_NO_INIT 0x00000000U

/*!< TX pin active level inversion */
#define UART_ADVFEATURE_TXINVERT_INIT 0x00000001U

/*!< RX pin active level inversion */
#define UART_ADVFEATURE_RXINVERT_INIT 0x00000002U

/*!< Binary data inversion */
#define UART_ADVFEATURE_DATAINVERT_INIT 0x00000004U

/*!< TX/RX pins swap */
#define UART_ADVFEATURE_SWAP_INIT 0x00000008U

/*!< RX overrun disable */
#define UART_ADVFEATURE_RXOVERRUNDISABLE_INIT 0x00000010U

/*!< DMA disable on Reception Error */
#define UART_ADVFEATURE_DMADISABLEONERROR_INIT 0x00000020U

/*!< Auto Baud rate detection initialization */
#define UART_ADVFEATURE_AUTOBAUDRATE_INIT 0x00000040U

/*!< Most significant bit sent/received first */
#define UART_ADVFEATURE_MSBFIRST_INIT 0x00000080U


実際に使用する場合はCubeMXで設定するか、下記のコードをUART初期化関数MX_USARTX_UART_Initに追記して使用します。CubeMXで設定する場合は下記のようにUARTの設定項目のAdvanced Featuresから有効/無効を設定します。

uart.jpg

コード上から修正する場合はデフォルトでUART_ADVFEATURE_NO_INITとなっているため、必要な項目を追加して各項目を有効化して使用します。

デフォルト
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;

追加例
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_TXINVERT_INIT | UART_ADVFEATURE_SWAP_INIT;
huart1.AdvancedInit.TxPinLevelInvert = UART_ADVFEATURE_TXINV_ENABLE;
huart1.AdvancedInit.Swap = UART_ADVFEATURE_SWAP_ENABLE;

STM32F7、L4、H7シリーズのみ対応しているのが残念ですが、UART拡張機能の中でもTXとRXの入れ替え機能は非常に便利だと思いました。TXとRXをクロスさせて回路設計することを忘れていたり、クロスさせたはずが回路上で間違えていたり、クロスケーブルがなく、ストレートケーブルしか準備できていなかったり、UARTのTX、RX絡みでよくあるトラブルがソフトウェア上で解決できるのは非常に便利です。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年04月24日

Node-redを用いたシリアルカメラ画像取込

今回はシリアルカメラPTC06をNode-Redを用いて画像として取り込んでみました。シリアルカメラPTC06は高画質や高フレームレートは全く期待できませんが、UARTから気軽に画像データを取得することができます。組込マイコンとの接続や簡易的な遠隔監視といった用途に最適です。Node-Redのシリアルポートを使用して画像を取り込んでみました。なお、シリアルポートのノードを使用するため、Node-Redはクラウド版でなく、オンプレミス版を使用する必要があります。

フローの全体は下記です。

serial_camera_node_red.jpg

必要に応じて、最初に解像度設定等のコマンドを実行(Inject)した後でResetコマンドでリセットします。画像を取得したいタイミングでCapture Imageコマンドを実行します。取得した画像を確認するためにはRead Data Lengthコマンドを実行してファイルサイズを取得します。その後でRead Image Dataコマンドを実行します。一括で取得できるデータは200Byte前後のため、Read Image Dataコマンドではファイルを分割してメモリから取得し、Jpegファイルを生成しています。


img.jpg

実際に取得したファイルです。至近距離のため、ぼやけていますが、3秒程度でファイルを取得できました。画像サイズは320x240で12kBとなりました。今回のNode-Redのフローはこちらにアップしています。640x480の場合は40kB前後で15秒程度取得に時間を要します。

Node-Redを用いてシリアルカメラの初期化、設定、画像取得までできました。PTC06のデータシートの記載ミスなのか分かりませんが、画像取得コマンドが56,00,32,0C,00,0D...と記載されていますが、このコマンドでは取得できませんでした。他のシリアルカメラと同様に56,00,32,0C,00,0A...とすると取得できるようになりました。ファーム等によっても若干、挙動が異なるようです。

今回は使用しませんでしたが、Node-RedのDashboardと組み合わせれば、ファイルとして画像を取得するだけでなく、ボタンとtemplate等を活用してDashboardにボタン操作で表示することも可能です。時間を見つけて実装してみたいと思います。
posted by Crescent at 00:00| Comment(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする

2021年04月17日

WindowsAppによるPython環境、Jupyter Notebook構築

Python環境を構築する場合、AnacondaやWSL、Docker等で環境を構築した方が便利です。PC環境によってはAnacondaやWSL、Docker等を使用できない場合もあります。今回は敢えてWindowsAppでPython環境を構築、jupyter notebookをインストールする場合のポイントについて紹介します。

特に注意点としてWindowsAppの場合、デフォルトではPythonインストールディレクトリにユーザー権限が与えられていないため、pip等で他のソフトをインストールする際に制約があります。

@PythonAppインストール
スタートボタン→Microsoft Storeから検索でPythonをクリック、インストールします。

WinApp0.jpg

単にPythonだけ使用する場合は@のインストール作業だけで十分です。直接、python.exeにアクセスしたい場合は必要に応じてA以降の設定を行います。

Aディレクトリ権限変更
WindowsAppのPythonは下記のディレクトリにインストールされます。ただ、デフォルトではWindowsAppsフォルダにアクセスするユーザー権限が与えられていないため、コマンドラインやエクスプローラからアクセスできません。権限を変更してアクセスできるようにします。

C:\Program Files\WindowsApps\pythonsoftwarefoundation.python.*.**\python.exe


WinApp1.jpg

WindowsAppのフォルダを右クリックして、セキュリティから詳細設定をクリックします。

WinApp2.jpg

画面真ん中の所有者の「変更」をクリックします。

WinApp3.jpg

詳細設定から検索を押して、現在ログインしているユーザを探し、選択してOKを押します。オブジェクトにユーザ名が選択されていればOKです。OKボタンを押して閉じます。


C:\Program Files\WindowsApps以下にあるpythonsoftwarefoundation.python.*.**のPythonフォルダに対しても同様にユーザ権限を付与します。

WinApp5.jpg

アクセス許可エントリから追加をクリックします。

WinApp4.jpg

プリンシパルから検索をクリックし、同様に現在ログインしているユーザを選択して、フルコントロールの権限にチェックを入れてOKを押します。なお、前回と異なる点として権限変更時に「サブコンテナーとオブジェクトの所有者を置き換える」にチェックを入れます。

WindowsAppのフォルダを右クリックして、セキュリティタブのユーザ名に現在ログインしているユーザを選択して、フルコントロールにチェックが入っていることを確認します。これでC:\Program Files\WindowsAppsフォルダ、WindowsApps以下にあるpythonsoftwarefoundation.python.*.**のPythonフォルダにアクセスできるようになりました。

Bjupyter notebookインストール
下記のコマンドでjupyter notebookをインストールします。
"c:\program files\windowsapps\pythonsoftwarefoundation.python.*.**python.exe" -m pip install notebook

インストール後、下記のコマンドでjupyter notebookがインストールされたフォルダを確認します。
"c:\program files\windowsapps\pythonsoftwarefoundation.python.*.**python.exe" -m pip show notebook

今回は下記のようなディレクトリに格納されていました。
C:\Users\(ユーザ名)\AppData\Roaming\Python\Python38\Scripts\jupyter.exe notebook

Cjupyter notebookショートカット作成
毎回コマンドを打ち込むのは面倒なのでショートカットを作成しました。上記で確認したjupyter.exeフォルダにエクスプローラで確認し、jupyter.exeに対して右クリックで「送る」から「ショートカットをデスクトップに作成」をクリックます。デスクトップで作成されたショートカットのリンク先に「~~\jupyter.exe」から「(半角空白)notebook」を追記して「~~\jupyter.exe notebook」に変更してOKボタンを押して設定を反映させます。

winApp7.jpg

これでショートカットをダブルクリックするだけでjupyter notebookにアクセスできるようになりました。
posted by Crescent at 00:00| Comment(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする