データシートに目を通すのは大事っていう話

今回は、回路設計をする際にここを見ておけばstm32f405rgマイコンを燃やす可能性や、書き込みができない可能性をさげるためにデータシートのここは見ておこうという話をしていきたいと思います。

まずは、ブートモードからチェックしていきます。

f:id:sora_siro:20190404150850p:plain

f:id:sora_siro:20190404150902p:plain

usartで書き込みをしたい場合は、boot1を0(Low),boot1を1(High)にしようねってことがわかります。

また、boot1 pinがどこにあるかもしっかりと探しましょう。stm32f405rgの場合は、PB2のピンがboot1に割り当てられていました。

stlink書き込みや、詳しくデータを知りたい場合は、AN2606や、stlinkのことの書いてあるデータシートを読みましょう。私は、まだ自作基板を用いて一度もstlinkで書き込みをしたことがないです。後日、stlinkによる書き込みをやってみたいと考えています。

続いて、設計するときのコンデンサの配置は、

f:id:sora_siro:20190404151321p:plain

電源について書いてあるところがあるので、探してみましょう!!

これをみることで、つないだらやばそうなところがわかると思います。

V_CAPとGNDをつないでしまったら確実にやばそうですね・・・

 

この記事を書いた理由

先日、知り合いの方が回路設計をしたクラシックマウスのマイコンの書き込みができない、レギュレータが熱くなるという話を聞き、回路のデバッグを手伝いました。回路図を見えてもらった際に明らかにおかしなところがありました。話を聞いたところデータシートを読んでいない、マイコン周りのコンデンサの配置や、コンデンサをつけているピンがstm32f1と全く同じ。さらに、やらかしてもデータシートを読まないで新しい基板にはんだ付けをして、また壊すを何回も繰り返したと・・・。

言葉を失いました。

 

最後に

データシートはちゃんと確認しましょう(ブーメラン)

 

参考文献

www.st.com

https://www.mouser.jp/datasheet/2/389/stm32f405rg-956214.pdf

 

電通大プチコンに参加しました!

電通大プチコンに参加してきました。

初めて、今調整しているハーフマウス、クラシックマウスを大会に近い環境で走らせました。プチコン前にたてた目標にセンサ値以外は調整しなくても走るパラメータ調整をするという個人的な目標も達成することができました。

結果は、

f:id:sora_siro:20190318095625j:plain

出場した競技すべてで優勝することができました。

マウスを初めて、初めて頂いた賞なので大切にします。

クラシックマウスは過去問で、前回の優勝タイムが3.31だったそうですが、それよりもタイムを短くすることができました!

今回の走行で直したい点がいくつか見つかったので、問題点の洗い出しをしていきたいと考えています。

走行動画↓

youtu.be

 

交流会ではいろいろとお話を聞けて楽しかったです。

 

最後に、運営をしていただいた電通大の皆様ありがとうございました。

とても楽しかったです。

 

ps.

ブログネタを募集しています。なにかあれば教えていただきたいです。

 

 

 

STM32 HALライブラリ + SPI 通信でICM-20602と通信をしてみる

 今回は、K.Sato(@SatoMouse) さんのICM-20602搭載三軸加速度三軸ジャイロセンサモジュール - スイッチサイエンス を使用しました。

ICM-20602のパッケージはパッドが横に出ていないので手はんだはほぼ無理(気合でできるといううわさもあり)なので、リフローをしないとつけることはできません。おうちにリフローセットがある家は一般的な家庭ではないと思うので、こういうキットがあるといいですよね。

今回は、MPU6500の記事にデータシートを読み解きながらやっていこうという内容と被る点が多いため、私が重要?だと思った点のみデータシートの写真を載せて紹介をしていこうと思います。

sora-siro.hatenablog.com

 

データシートに、SPIの通信は次のようになっていると書いてありました

f:id:sora_siro:20190304115704p:plain

通信はMSB First,書き込みをするときはアドレスの先頭ビットを0、読み込みをするときは先頭ビットを1,通信は8bitずつだそうです。

通信のルールがわかったので、cubeMXでSPIの設定をしていきます。書き込みの最大速度は1MHz,読み込みの最大速度は20Mhzなので、私は書き込み時にわざわざ周期を変えるのが面倒だと感じたため、1Mhz程度の通信速度に設定をしました。これでも通信速度的には問題がない速度であると思います。

 

プログラムは以下のようになりました。

/**
* ICM 20602.h
* @author Sora
*/

#ifndef __ICM_20602_H
#define __ICM_20602_H

#include <stdint.h>

typedef struct {
float omega_x;
float omega_y;
float omega_z;
float accel_x;
float accel_y;
float accel_z;
}GYRO_DATA;

extern GYRO_DATA gyro;

void ICM20602_init( void );
void ICM20602_DataUpdate( void );

#endif /* __ICM_20602_H */

 

/**
* ICM 20602.c
* @author Sora
*/

#include "spi.h"
#include <stdio.h>
#include "ICM20602.h"

GYRO_DATA gyro;
static uint8_t set_flag = 0;

uint8_t read_byte( uint8_t reg )
{
uint8_t ret,val;
HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET ); //cs = 0;
ret = reg | 0x80;
HAL_SPI_Transmit( &hspi1, &ret,1,100 );
HAL_SPI_Receive( &hspi1,&val,1,100 );
HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET ); //cs = 1;
return val;
}

void write_byte( uint8_t reg, uint8_t val )
{
uint8_t ret;
ret = reg & 0x7F ;
HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET );
HAL_SPI_Transmit( &hspi1, &ret,1,100 );
HAL_SPI_Transmit( &hspi1, &val,1,100 );
HAL_GPIO_WritePin( LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET );
}

void ICM20602_init( void )
{
uint8_t who_am_i = 0;
// check WHO_AM_I (0x75)
who_am_i = read_byte(0x75);

// who am i = 0x12
printf( "\r\nwho_am_i = 0x%x\r\n",who_am_i );

// recheck
if ( who_am_i != 0x12 ){
HAL_Delay( 100 );
who_am_i = read_byte(0x75);
if ( who_am_i != 0x12 ){
while( 1 ){
printf( "gyro_error\r");
}
}
}

// set pwr might
// PWR_MIGHT_1 0x6B
write_byte( 0x6B, 0x00 );

HAL_Delay( 50 );
 
// PWR_MIGHT_2 0x6C
write_byte( 0x6C, 0x00 );

HAL_Delay( 50 );

// set gyro config
// GYRO_CONFIG 0x1B
write_byte( 0x1B, 0x18 ); // use 2000 dps

HAL_Delay( 50 );

// ACCEL_CONFIG 0x1C
write_byte( 0x1B, 0x18 ); // use pm 16g

HAL_Delay( 50 );

set_flag = 1;

}

float ICM20602_GYRO_READ( uint8_t H_reg )
{
int16_t data = (int16_t)( ((uint8_t)read_byte(H_reg) << 8) | (uint8_t)read_byte(H_reg+1) );
float omega = (float)(data / 16.4f);

return omega;
}

float ICM20602_ACCEL_READ( uint8_t H_reg )
{
int16_t data = (int16_t)( ((uint8_t)read_byte(H_reg) << 8) | (uint8_t)read_byte(H_reg+1) );
float accel = (float)(data / 2048.0f);

return accel;
}

void ICM20602_DataUpdate( void )
{
if ( set_flag == 1 ){
// get yawrate
gyro.omega_x = ICM20602_GYRO_READ( 0x43 );
gyro.omega_y = ICM20602_GYRO_READ( 0x45 );
gyro.omega_z = ICM20602_GYRO_READ( 0x47 );

// get accel
gyro.accel_x = ICM20602_ACCEL_READ( 0x3B );
gyro.accel_y = ICM20602_ACCEL_READ( 0x3D );
gyro.accel_z = ICM20602_ACCEL_READ( 0x3F );
}


}

main.c内

~INIT() などは省略
 
ICM20602_init();
/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */

while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
ICM20602_DataUpdate();

printf( "gyro x : %5.5f, y : %5.5f,z : %5.5f, accel x : %5.5f, y :%5.5f, z : %5.5f\r",
gyro.omega_x, gyro.omega_y, gyro.omega_z, gyro.accel_x, gyro.accel_y, gyro.accel_z );
 
}

 

さいごに

データシートを読もう!!

MPU-6500とほとんど変わらない雰囲気で使用をすることができました!

自分ではんだ付けをせずにポン乗せで使えるのはやっぱりいいですね。(n回目)

 

クラッシクサイズ マイクロマウス まとめ[2018]

あけましておめでとうございます。

前年度のマシンの設計のまとめについて書いていきたいと思います。

先日、WMMCでDCモーターを初めてやる際にはまった点について話した内容をしっかりとまとめていきます。

 

クラッシクマウスをDCで始めるにあたって。

・辛くても諦めないようにする心を持つ

・回路図を最初に引いて部品を購入して作らざるを得ない状況を作る

マイコンなどは先に評価基板などで動作確認をしておく)

・マイクロマウスをやっている方のブロブをたくさんあさる。

・機械設計や電子回路設計は周りに知っている人がいれば聞く。

→わからないことは聞く!

・進捗は目に見える形で残す(モチベーションアップやどこまで進んでいたか確認が取れるため。)

・プログラムはバージョン管理をする。

githubなどを使うとプログラムの一行ごとの変更ポイントがわかるので自分がプログラムを変えておかしくなったとき、古いプログラム焼きなおしてみてハードウェアが悪いのか、ソフトウェアが悪いのかの確認が可能になる。)

・調整・走り込みは大切

(走り込みをしなかった結果、毎回大会会場で長く走らせていたらマシンが壊れるということをやり、前日の夜または大会当日の朝に動かないといいながらはんだ付けやらなんやらを毎回やる羽目になりました。)

 

機械設計

2DCADで設計を行いました。3DCADで設計はしていないので画像はありません。

設計図は上、横から見た図を描きました。

ギアのバックラッシはM0.5で約0.1mmピッチ円から離してギアの回転が軽くなるようにしました。(力の伝達効率は落ちているとおもいます。)

 

電子回路設計

回路図

 pdfファイルでリンクを張りました。

モーターグラウンドとその他のグラウンドは分離して一点接地をしたほうがいいと思います。私は今年度ノイズに苦しめられました。

 

最後に

全日本大会出場マシンデータ

length : 100mm

width : 72mm

high : 20mm

MCU : stm32f405rgt

MotorDriver : DRV8835

Sensor ST-1KL3A, SFH-4550

Power :  OK Tahmazo REシリーズ リポバッテリー LP2S1P250RE

    2Cell 250mah

 

 

f:id:sora_siro:20190101132130j:plain

マシンの画像

 

これしか画像がなかった・・・

こんな感じです。

 

その他

迷路探索はほとんどがシミュレーターで動作チェックをして実際のマシンに組み込むということを行っています。

使用しているのはVisual Studio Community 2017 + DXライブラリです。

最短経路まで出せると迷路アルゴリズムがただしく動いているかどうかの確認が楽でいいです!

シミュレーター - YouTube

 

 

 

 

 

 

 

 

 

stm32f405rgtとhalライブラリを使用してエンコーダモードを使ってみる

 

今回は stm32f4 + hal(stm32cube)でtimをエンコーダモードに設定してエンコーダの値を取得の仕方をかいていきます。

例によって、stm32cubeを開き、timをエンコーダモードに設定しましょう!
次に、configurationのタブのエンコーダモードに設定したtimの設定を行います。
periodを16bitの最大値である65535に設定します

f:id:sora_siro:20181210113157p:plain

Pin設定

f:id:sora_siro:20181210113224p:plain

設定

あとは、エンコーダの値を確認するためにusartを有効にしてprintfを表示できるようにしました。

 printfに関してはこちらのエントリに書いています

stm32 halライブラリ、makefileでprintf(float型)を使えるようにする! - sora blog

 

そしたらcubeからソースコードを作成してプログラムを書いていきます。

私は、tim.c内のusercode begin - end 内にこのような関数を実装しました。

void update_encoder( t_enc_value *enc )
{

uint16_t enc_l_buff = TIM4->CNT;
uint16_t enc_r_buff = TIM3->CNT;
TIM3->CNT = 0;
TIM4->CNT = 0;

if( enc_l_buff > 32767 ){
enc->left = -1 * (int16_t)enc_l_buff;
} else {
enc->left = -1 * enc_l_buff;
}
 
if ( enc_r_buff > 32767 ){
enc->right = (int16_t)enc_r_buff;
} else {
enc->right = enc_r_buff;
}

 エンコーダのカウントはTIM構造体のCNTにカウントされいていくので、毎回値を確保した後に0にリセットをしています。そのため、定期的に値を取得するということを行うためにこの関数を割り込み内で動かしています。

また、カウントの最大値は先ほど設定した値になります。(詳しくはstm32のマニュアルを読んでください。)

したがって、65535が最大値となっています。

ここで、左側にマイナスがついている理由についてですが、マイクロマウスの場合マシンが直進する際にはモーターの主軸の回転方向が逆になるためです。

if 文についてはint16_tがたの最大値より大きいかどうかを判断して正方向か逆方向化判断して値を取得できるようにしています。

また、t_enc_valueは次のように定義しています。

// enc value
typedef struct {
int16_t left;
int16_t right;
}t_enc_value;

 

そしたら、ちゃんと動いているかどうかを確認していきます。

stm32f4xx_it.cのvoid SysTick_Handler(void)

内でこの関数をよび、int mainのwhileループの前に

HAL_TIM_Encoder_Start( &htim1, TIM_CHANNEL_ALL ); // encoder
HAL_TIM_Encoder_Start( &htim8, TIM_CHANNEL_ALL ); // encoder

 を読んでからprintfで確認をしてみてください。

 

マイクロマウスの場合はここから速度をだして使われることが多いです。私は角速度に直してから速度に変換しています。

方法はいくつかあるのでちゃんと正しい値が返ってくればいいのではないかと考えています。

 

最後に

知見のあるかたでここがおかしいといったことがあれば教えていただきたいです。

 

ところどころ適当になってしまって申し訳ないです。

疲れました・・・

 

stm32f405rg + hal ライブラリ を使用してmpu6500とお話する 

こんばんわ!

先日Twitterでアンケートを取ったところ需要があるという意見を多数いただいたので書いていこうと思います。

実際私自身もはまったのでそれも踏まえて書いていきたいと思います。

最初のstm32 cubeでの設定などに関しては下記のリンクなどを参照してください。

 

sora-siro.hatenablog.com

 

まず初めにmpu 6500 のデータシートを見て設定をするうえで必要そうなことが書いてある場所を探します。この記事では必要そうなところを大まかにピックアップして載せていきます。

いきなりこうだよねみたいな書き方をしていたらデータシートを各自でみて確認してみてください。データシートを読む練習?になると思います。

間違ってたらごめんなさい。ご指摘いただければと思います。

まずは、MPU-6500 Product Specification Revision 1.1 のデータシートから読んでいきます!

f:id:sora_siro:20180915214208p:plain

このページを見ると、2000deg/s にするためには FS_SEL = 3, スケール調整をするために 16.4 で割ればいいということがわかりました。

f:id:sora_siro:20180915214628p:plain

ここをみるとspiの書き込み時は1MHz,読み込みだけなら20MHzまで対応していることがわかります。

先ほど設定したSPIの通信速度をみて間違っている場合は各自直しておきましょう。

f:id:sora_siro:20180915221511p:plain

パワーモードはこんな感じらしいです。

f:id:sora_siro:20180915215244p:plain

この前に通信の際にこのデバイスを指定するときはこのデバイスにつないでるcsPinをLowにしてあげて、このようにすればいいみたいです。

8bit 送って 8bit 送るという16bit 刻みでの通信を行う必要があるそうです。

まずは、アドレスを指定する8bitを送ります。

ただし、最上位ビットでR(Read)/W(Write) : bit 1 / 0 + アドレス、書き込みなら書き込む内容、読み込みならダミーを送信すればいいようです。

ここまでの内容から通信に必要なソースコードを書いてみると以下のようになりました。

読み込みは以下のようになります。

uint8_t read_byte( uint8_t reg )
{
uint8_t ret,val;
HAL_GPIO_WritePin( gyro_cs_GPIO_Port, gyro_cs_Pin, GPIO_PIN_RESET ); //cs = 0;
ret = reg | 0x80;
HAL_SPI_Transmit( &hspi2, &ret,1,100 ); // 読み込みアドレス
HAL_SPI_Receive( &hspi2,&val,1,100 );
HAL_GPIO_WritePin( gyro_cs_GPIO_Port,gyro_cs_Pin, GPIO_PIN_SET ); //cs = 1;
return val;
}

HAL ライブラリには SPI_Receive という便利な関数があったのでそれを使っちゃいました!

続いて書き込みです。

///////////////////////////////////////////////////////////////////////
// spi write 1 byte
// [argument] Register
// [Substitutiong] write data
// [return] nothong
///////////////////////////////////////////////////////////////////////
void write_byte( uint8_t reg, uint8_t val )
{
uint8_t ret;
ret = reg & 0x7F ;
HAL_GPIO_WritePin( gyro_cs_GPIO_Port, gyro_cs_Pin, GPIO_PIN_RESET ); //cs = 0;
HAL_SPI_Transmit( &hspi2, &ret,1,100 ); // 書き込みアドレス
HAL_SPI_Transmit( &hspi2, &val,1,100 );
HAL_GPIO_WritePin( gyro_cs_GPIO_Port,gyro_cs_Pin, GPIO_PIN_SET ); //cs = 1
}

書き込みのときは書き込みのアドレスが上位ビットだけ送信になるので ret = reg & 0x7Fとして最上位ビットは絶対に0になるようにしてます

これで書き込み、読み込みができました。続いてお話しするためには設定が必要になるみたいなのでそれを見ていきたいと思います。

 

次に、MPU-6500 Register Map and Descriptions Revision 2.1を見ていきましょう!

私はこのページに載っているアドレスで必要なものだけマクロ定義をしています。

すべてマクロ定義をしてもOKだと思います。

そうじゃないと確認する際に面倒だと思います。

 

さて、レジスタの詳しい内容を見ていきましょう。

今回設定やチェックをする必要がありそうな内容は

Who Am I ( 君の名は(映画は関係ありません) ) 0x70

2000deg/secに設定する

Z Axis を読み込む

パワー(ジャイロモード)をOnにする

データの出力を許可する

といったところだと思うのでこれらをできるようにそれぞれのレジスタに書き込んだり読み込んだりをできるようにしましょう

 

順番的には

Who Am I

パワーをON

データの出力を許可する

2000 deg / sに設定する

Z 軸のデータを読み込むといったところでしょうか?

 

まずは who am i からいきます。

who am i のレジスタを読みこむ。 以上

はい簡単ですね。

つづいてパワーをON にしましょう

adder 0x6B  PWR_MGMT_1

f:id:sora_siro:20180915222825p:plain

よし、すべてに0をいれれば動くということで0x00を代入します。

ソフトで表すと

write_byte( MPU6500_PWR_MGMT_1, 0x00 );

こんな感じです。

 データの出力を許可するの設定も同様にデータシートを見ていきます。

f:id:sora_siro:20180915223440p:plain

FIFO,LPFは使用する必要がないのですべてに0を代入してしまいましょう!

write_byte( MPU6500_CONFIG, 0x00 );

 

2000 deg / sec の設定の仕方も同様にして

f:id:sora_siro:20180915223725p:plain

2000 deg / sec にするためには 4:3 に 11 をたてればいいみたいです。

書き込む内容は0x18 ですね。

write_byte(MPU6500_GYRO_CONFIG, 0x18);

さて、ここまでで書き込みができたので次は読み込みをしましょう。

ジャイロのデータは16bit で一つのデータになりますが、なんどmpu 6500 は上位と下位でレジスタが分かれてしまっているためなんとかして16bitのデータにまとめる必要があります。なのでビットシフトとキャストを使用してデータの結合、取得を行います!

float MPU6500_read_gyro_z( void )
{
int16_t gyro_z;
float omega;

gyro_z = (int16_t)( ( read_byte(MPU6500_RA_GYRO_ZOUT_H) << 8 )
| read_byte(MPU6500_RA_GYRO_ZOUT_L) );
 
omega = (float)( gyro_z / GYRO_FACTOR);

return omega;
}

こんな感じになります。

gyro_z でジャイロのデータを読み込んで、omegaではdeg/sに直すために定数で割っています。

あとは割り込み関数内で

prev_omega, machine_degree は global変数なり,static でそのファイル内でのみの静的な変数なり毎回リセットされないようにして

now_omega = MPU6500_read_gyro_z();

machine_degree += ( now_omega + prev_omega ) / 2.0f * dt;

prev_omega = now_omega;

とでもすればマシンの角度が取得できると思います。

ただし、この生のデータの値を使用すると0点ドリフトに角度が影響を受けてすごい勢いで大きくなることや小さくなるといった現象に見舞われる可能性があるのでその場合はオフセットを入れましょう。

これは各自考えてみてください。

ヒントはデータをある一定周期で取得してそのデータを足し合わせて・・・です。

 

最後に

データシートはしっかり読みましょう( 自分への戒め )

 

知見のあるかたで、ここをこうしたほうがいいということがあればご指摘していただきたいです。よろしくお願いします。

 

 

マイクロマウス東日本地区大会報告

マイクロマウス東日本地区大会に参加してきました。

これまでマイクロマウスの話は一切出していませんでしたが、stm32マイコンを使うきっかけになった競技がマイクロマウス、ロボットトレーサーでした!

とても楽しかったです!

結果報告になりますが、ロボトレ、マイクロマウスともに完走をすることができ全日本大会の切符(認定証)を手に入れることができました!!

今後はマイクロマウスのことも書いていけたらと思っています。

次は学生大会に参加をする予定です。

また、マイクロマウスの迷路探索シュミレーターを作ってみました。動画を挙げておきます。まだまだ製作途中という感じですが今後の進化を楽しみに!!

まだまだ探索の効率が悪い、最短経路のパスを作ることができてないのでここからが正念場かなと思ってます。

youtu.be

それではまた。

 

youtu.be

迷路探索シミュレーターいろいろと進化!

2018 11/19追記

最短経路の線を近日中に引く予定!