2019年12月28日

磁気エンコーダMLX90316

Melexis社製の14bit磁気エンコーダMLX90316を試食してみました。

先日紹介した3線式SPI通信を使用して磁石の角度情報を読み込んでみました。
結論から言うとMLX90316はダイヤルといったインターフェース向けのエンコーダでモータ制御にはあまり向いていないようです。

Arduinoのサンプルプログラムでは動作しますが、STM32マイコンのSPI通信で実装すると思うように位置情報が読み込めない不具合に遭遇しました。原因を追うとデータシートにその答えがありました。

MLX90316_1.jpg
 MLX90316データシートP.33から抜粋

データシートをよく見るとt1が最小2.3usということで最大クロックは300kHz程度です。さらにt2で1バイトごとに10us以上待機する必要があり、SPI通信で連続してバイトの読み書きができません。また、t5でCS=1状態で300us以上待機する必要があることが書かれています。数MHzのクロックで通信できるSPI通信のメリットがありません。

つまり、位置データ読み込みは数msに1回程度しか読み込めないということになります。MLX90316の仕様でSPI通信対応ということで細かい部分を見逃していました…

CubeMX上でClock Phaseを2Edgeに設定し、SPIのプリスケーラを256に設定してSPIのボーレートを31.25Kbit/sに設定すると正常に位置情報を読み込むことが確認できました。

MLX90316_2.jpg


 uint8_t sdata[4];
 uint8_t rdata[8];
 uint16_t dat[4];

 uint16_t res;
 uint8_t halres; 
 sdata[0]=0xAA;
 sdata[1]=0xFF;


 SPI_1LINE_TX(&hspi1);
 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);
 halres=HAL_SPI_Transmit(&hspi1,sdata,2,0x1000);
 if(halres !=HAL_OK) printf("Transmit Err:%d \n\r",halres);
 SPI_1LINE_RX(&hspi1);
 halres=HAL_SPI_Receive(&hspi1,rdata,8,0x1000);
 if(halres !=HAL_OK) printf("Receive Err:%d \n\r",halres);
 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);
 dat[0] = (rdata[0]<<8) + rdata[1];

 if((dat[0]&0x03)==2){
   // Err Data
  if ( dat[0] & (1 << 4)) {
   //printf("Magnetic Field is Too Strong!\n\r");
  }
  else if ( dat[0] & (1 << 5)){
   //printf("Magnetic Field is Too Weak!\n\r");
  }
 }
 else if((dat[0]&0x03)==1){
  res=(dat[0]>>2);//16bit Angle Data
  printf("RES: %d \n\r",res);
 }



MLX90316_SPI_Wide.jpg




磁気エンコーダをモータ制御として使用する場合、少なくとも1msに1回、理想は100usに1回読み込みたいのでMLX90316の仕様は満足しないことが分かりました。ダイヤルといったインターフェース向けのエンコーダとしては低コストかつシンプルなコマンドで通信できるため、非常によいと思いました。

14bi磁気エンコーダとして癖がなく、高速な処理に対応しているのはやはりAMS社のAS5048Aが個人的にベストな磁気エンコーダだと改めて思いました。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする

2019年12月21日

STM32マイコン UART受信時必須処理

STM32マイコンでUARTの受信をする際に必須となるエラー処理について紹介します。

UARTの送信は一方的にマイコンから送るだけのため、そこまで大変ではありません。一方、受信は調歩同期方式ならではのエラー(フレーミング、バッファ オーバーラン エラー等)が発生するため、エラー処理を入れないとUARTの受信処理の安定性が悪化します。

更に厄介なのがSTM32マイコンのHALライブラリではUARTの受信割込みやDMA転送を使用した際に受信エラーが発生すると以降の受信処理が行われません。コマンドをUARTで処理する場合、受信エラー以降の受信が行われず、応答なし状態となっていまいます。

受信処理を継続して行うためにはエラー処理を加える必要があります。



実装としてはエラーが発生するとHAL_UART_ErrorCallbackが呼び出されます。
※設定によりますが、HAL_UART_ErrorCallbackが呼び出されないエラーがあったため、HAL_UART_ErrorCallback内でクリアせずにwhile内等でのクリア処理に変更しました。

UARTのエラーフラグを確認してクリアするHAL_UART_Abort関数を実行して受信処理を再開させます。
なお、HAL_UART_Abort関数は割込みを解除する関数ですが、各種エラーをクリアさせる機能も入っています。個々のエラーフラグだけをクリアするだけでは再開できないことが多々あるため、HAL_UART_Abort関数でレジスタをクリアさせる方法が確実です。



 if(huart->Instance==USART1){
  if (  __HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) ||
    __HAL_UART_GET_FLAG(&huart1, UART_FLAG_NE) ||
    __HAL_UART_GET_FLAG(&huart1, UART_FLAG_FE) ||
    __HAL_UART_GET_FLAG(&huart1, UART_FLAG_PE) ){
     HAL_UART_Abort(&huart1);
     HAL_UART_Receive_DMA(&huart1, (uint8_t*)&UART_Data, 1);//DMAの場合
     //HAL_UART_Receive_IT(&huart1, (uint8_t*)&UART_Data, 1);//割込みの場合
  }
 }


上記処理をmain.cのwhile内等に配置することでエラー処理することができます。


以前に通常の処理ではうまく受信できるがタイミングによって受信できなくなるといった不具合に悩まされました。原因がフレーミングエラーと分かりました。電源投入直後のノイズ等でエラーが発生してしまったようです。上記の処理を加えることでエラー時に処理を再開させ、安定して通信を継続できるようになりました。

※一部HALライブラリ依存があったため、修正しました
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2019年12月14日

STM32F3マイコンでの3線SPI通信


STM32F3マイコンの3線SPI通信で少し癖があったので少し紹介します。


CubeMX上ではHalf Duplex Masterとして設定します。

SPI.png



3線式ではHalf Duplexとなるため、HAL_SPI_Transmit関数とHAL_SPI_Receive関数を使用します。今回、読み込みコマンドをHAL_SPI_Transmit関数でデバイスに送信してから値をHAL_SPI_Receive関数で読み込みます。その際にHAL_SPI_Receive関数でタイムアウトエラーが頻発し、安定して読み込みできない現象が発生しました。



使用するバージョンにもよりますが、HALライブラリに少し癖があるようです。HAL_SPI_Transmit関数の後に続けてHAL_SPI_Receive関数を呼び出すとRXNEレジスタが変わらず、タイムアウト状態になってしまうようです。
※現時点ではSTM32Cube FW_F3 V1.11.0


3線式ではHalf DuplexではGPIOの入力、出力を随時切り替えて通信する必要があります。上記のタイムアウトを防止するため、強制的に入出力を切り替える関数を呼び出しすとタイムアウトエラーが発生せずに読み込めました。

具体的には下記の通りです。

SPI_1LINE_TX(&hspi1);//強制的に送信モード
HAL_SPI_Transmit(&hspi1,sdata,2,0x1000);
SPI_1LINE_RX(&hspi1);//強制的に受信モード
HAL_SPI_Receive(&hspi1,rdata,4,0x1000);



強制的な入出力を切り替えで読み込めることが確認できました。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2019年12月07日

FTDI2232を用いたJTAG通信 Machxo2書き込み

Lattice社のFPGAの開発環境はインストールパッケージが1GB前後と軽いのが特徴です。それもあってLattice社を好んで使っています。また書き込みツールがFTDIの2232Dなどでそのまま純正書き込みソフトで書き込むことが可能なため、高価な書き込みツールが不要なのも特徴です。
※Machxoシリーズに対応した開発環境Diamond、iCE40に対応したiCECubeともにそれぞれ1GB前後です

今回はLattice社のFPGA、Machxo2(LCMXO2-256HC-4TG100C)の書き込みについて少し紹介します。

秋月のサイトにもMachxo2の書き込み方法(PDF)について紹介されていますが、安定した書き込みができず少し苦労しました。



Machxo2のJTAGポートは弱いプルアップやプルダウンがありますが、安定化のための十分でないため、外部に別途プルアップやプルダウンが必要です。

TDO、TDI、TMSはプルアップ、TCKはプルダウンですが、抵抗値もポイントです。すべて4.7kohmでは安定した書き込みができませんでした。

評価用ボードの回路を確認すると理由が分かりました。TDO、TDI、TMSはプルアップが4.7kohmというのは同じでしたが、TCKのプルダウン抵抗が違いました。純正の評価ボードのTCKは2.2kohmでプルダウンしていました。



jtag_pull.jpg


純正の評価ボードに合わせてTCKを2.2kohmでプルダウンすると安定して書き込みできることが分かりました。
ただ、正直、Machxo2(LCMXO2-256HC-4TG100C)を書き込む際には2232DよりもTinyFPGAプログラマが簡単です。
TinyFPGAプログラマ専用のソフトウェアでの書き込みになりますが、書き込み速度も高速で便利です。
TinyFPGA AX2 Boardでなくても書き込みできました。
なお、Machxo3は識別コードが異なるため、TinyFPGAプログラマ専用のソフトウェアそのままでは書き込みできませんでした。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする