LancerStratos’s blog

第23回ロボットグランプリに向けたロボットランサー”ランサーストラトス”開発記録

ジャイロの出力値(その2)

以前、ジャイロの出力がノイズまみれと書きました。MPU9250が内蔵しているDLPFを試してみましたが改善できません。そこで久しぶりに秋月電子のホームページを見て回ると、3軸ジャイロセンサのAE-L3GD20H(¥480)を見つけました。MPU9250は9軸センサですが、現時点ではZ軸ジャイロしか使ってませんし、値段も安いのでAE-L3GD20Hを試してみようと思います。

ちょうど、ランサーストラトスの基板にはSPI接続用の予備端子を準備していたので実験もやりやすそうですし、AE-L3GD20Hがマイコンと同じSTマイクロの製品なので相性もいいかもしれません。データシート上のジャイロ性能はほぼ同じです。今日は文化の日秋葉原に買い物に行けたのですが、まずはデータシートを読み、プログラムを作ることにしました。

SPI接続ならボーレートが10MHzとれるので現在のI2Cより短時間で処理できます。MPU9250もSPI接続出来るのですが、なぜI2C接続していたかというと、MPU9250が内蔵しているDMPを使いたいと考えていたからです。結局DMPの前のノイズ処理の段階で断念したことになります。

世界的な半導体不足という状況は、少しづつ解消しているようですが、秋月ではSTM32F405が在庫切れ再入荷待ちになって久しいです。いつになったら手軽に購入できる日が来るのでしょうか。それとも来ないのでしょうか。

ジャイロの出力値

友人の率いるチームが飛行ロボットコンテストで3位に入賞した。いつもは現地まで応援に行くのだが今回は訳あって行けなかった。優勝は出来なかったけどお疲れ様でした。

これに触発されたのと、大分涼しくなってきたのでロボット開発を進めなくてはなりません。ランサーストラトスにはMPU9250という9軸センサを搭載しているのですが機体制御に活用できずにいます。ノイズが大きいことが一番の理由で、どうやって滑らかな出力値が得られるのか悩んでいます。今日はMPU9250のマニュアルにDLPFの設定があるのを発見したので実装してみましたが、SDカードでログを取ってみるとマイナス記号が混ざった変な出力になっていました。

ヨー軸ジャイロ出力だけでも使えれば、現在位置をモデル計算して少しばかりスマートな制御に活かせるのではないかと考えていますが道のりは厳しそうです。

 

参照渡し

マーカーセンサー

前回の記事から1か月以上経過してしまいました。この夏の暑さに参って開発から遠ざかっていました。気力を振り絞って開発を再開します。TSL1401のプログラムを改良し、現在コースライン位置のみ検出しているのに加えて、コースライン脇にあるマーカーの検出もできるように改良を試みます。これにより、バンパー下に設置したマーカー読み取りセンサよりも、より早い時点でマーカー検出することができ、コース端コーナー進入時のステアリングと速度の制御を改善したいと思ってます。

先の記事に掲載した関数は、2つの引数に1つの戻り値(ライン位置)でしたが、マーカー検出を加えると戻り値(処理結果)が複数になるため関数の戻り値では表現できません。そこで参照渡しのテクニックを勉強しました。ポインタの理解でつまづきました。が、習うより慣れろで、いろいろソースを編集しているうちにコンパイル時の大量のエラーを少しづつ解消し、参照渡しの骨格を整えることができました。マーカーの検出自体はまだ確認できていません。

今回の勉強の中で、グローバル変数はあまり多用しないほうがいい、という意味を改めて実感することができました。

TSL-1401の使い方(その3)

今回はTSL1401を使って初めて参加した第22回大会の思い出話です。

LancerStratos2の照明

マイコンカーWikiに載っているような理想的な出力を期待してたのに、実際は下のような結果になりました。

TSL1401出力例1

グラフは横軸が128素子の並びで縦軸がADC値です。ロボットランサーのコース色は黒ではありませんが、灰色で、コースラインの白色に比べれば明らかに暗く、そのコントラストは十分にあります。でもグラフが示すように、中央付近にラインを示す鋭いピークが現れるかと思いきや、右側が全体的に明るいという形です。

この原因を探るため色々考えました。レンズの焦点が合ってない?AD変換のタイミングが間違っている?マイコンとモジュールの電源電圧を合わせないと?CLKが早すぎる?モジュール自体が壊れている?などなど・・が、結局大会の前日まで改善することができず、一時は出場をあきらめようとも考えました。

そんな中、ヘンテコながらもコースライン位置との相関と再現性があることが分かりました。下のグラフは、ライン位置をずらしたケースを重ねて表示したものです。

TSL1401出力例2

山の高さはバラバラですが、立ち上がりの斜面がライン位置に対応して左右にずれています。TSL1401の出力を正常にするには時間も知識も足りないので、このヘンテコ出力ありきでプログラムを作成し、何とか低速でライントレースできる状態になったところで時間切れ。大会には出場しましたが、最初のカーブで脱線するという情けない試合結果となってしまいました、が、昔、友人とランサーを作っていた時に、同じように大会直前まで不眠不休でロボット作りをしたことを思い出し、どこか懐かしい気持ちでした。

未だこのヘンテコな出力の原因は解明できていませんが、その後、AOでなくAO0端子(オペアンプを介さないTSL1401の生出力)を使ったところ、明らかにAOよりはピーク位置が明確になったので、原因の一つは、モジュールに付属のオペアンプの出力特性に原因があるのではないかと考えています。また、当時は照明用高輝度LEDを10個しか使っていませんが、現在は24個に増やし、波形の改善と併せて露光時間を短縮(3msec→1msec)できたので、検出対象を均等に照らす”照明”がとても重要な要素だと考えています。

この頃はSDカードを使ったログ機能は装備してなくて、マイコンとPC間のシリアル通信でTSL1401のデータを読み取っていたのですが、通信ケーブルがつながっているため走行中のデータが確認できなかたり、専用のプログラムに書き換えたりと、非常に手間がかかったことが、現在の機体にログ機能を搭載するきっかけになりました。

 

TSL-1401の使い方(その2)

ランサーストラトスのTSL1401制御プログラムは、マイコンカーWikiの画像認識のページに掲載されている参考プログラムが元になっている。これをTSL1401のマニュアルとC言語の本と突き合わせていくと、大体何をどうすればいいのかわかってくる。TSL1401の使い方がイメージできたところで、マイコン(STM32F405)側の設定は以下の通りとしている。

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_10B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

ADC入力端子x1の他、GPIO出力端子x2(SIとCLK用)用意する。これでマイコン側の物理的な接続の準備が整う。TSL1401モジュールには6つの端子があり、AO、SL、CLKとマイコンのそれを相互に接続するだけでよい。もちろん電源+5VとGNDも接続する。

さて、肝心な制御プログラム(関数)は以下の通り。

int16_t TSL1401(int16_t hi, int16_t lo)
{
    uint8_t clk = 0;
    uint8_t i = 127;
    int16_t camera_max = 0;
    int16_t camera[128];
    int16_t line_pos;

    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,1);        //PA2:SI=Hi
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,1);        //PA3:CLK=Hi
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,0);        //PA2:SI=Lo
    while(clk<=127){
          HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,0);    //PA3:CLK=Lo
          if(lo <= i && i <= hi){
              HAL_ADC_Start(&hadc1);
              HAL_ADC_PollForConversion(&hadc1, 1);
              camera[i] = HAL_ADC_GetValue(&hadc1);
              if(camera_max < camera[i]){
                  camera_max = camera[i];
                  line_pos = (int16_t)i;
              }
              }
          else{                  }
          HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,1);    //PA3:CLK=Hi
          clk++;    
          i--;
                }

      HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,0);        //PA3:CLK=Lo

      if(line_pos < 30){line_pos=30;}
      if(line_pos > 90){line_pos=90;}

      return line_pos;
}

TSL1401の仕様通り、SI端子とCLK端子をON OFF操作することでAO端子が128画素分の電圧を逐次出力し、それをAD変換で読み取る動作を繰り返す。白色ラインを読み取った画素は一番高いADC値を示すはずなので、読み取ったADC値の中で最大値だった画素番号をラインの位置として戻り値にする。引数hiとloは、128素子全部を変換してたら時間がもったいないので、AD変換したい範囲を指定するもの。また、最後のところで30から90の範囲で制限をかけているのは、自分のマシンにおける現物合わせ的なもの。

この関数の終了から次にこの関数を呼び出すまでの時間がTSL1401の露光時間になる。写真はブレッドボードでの実験の様子。

TSL1401の実験

 

 

 

 

 

 

TSL-1401の使い方(その1)

ロボットランサーもマイコンカーラリーも、出場マシンの殆どが機体前方に長く突き出たセンサー部をステアリング機構と連動させる方式を採用している。この方式はとても理に適っておりSSMを実装する手段として最適だと考える。がしかし、個人的にはマシン全体としての見た目が好みでないので採用したくないスタイルである。競技で勝ちたいのに、最適な手段を選べない、この葛藤。同じようなことを感じている方も少なくないのではないか。そういう自己矛盾を抱えながらも生きる心の余裕がある証拠だと思うことにしている。

さて、第22回出場マシンから、ラインセンサーとしてTSL-1401を採用している。ロボテナショップでボードレンズと組み合わせたモジュールとして販売されていたものだ。ネットにはTSL-1401の利用方法など多くの情報が転がっているが、特にプログラムについての詳細な記事はあまりない。マイコンのプログラミングにあまり詳しくない者にとってはハードルの高いセンサーだと思う。

自分もセンサーとして利用できるようになるまでに多くの苦労があったので、数回に分けてポイントを紹介していく。写真はロボテナショップの画面(現在同じモデルは在庫切れ)。

TSL1401モジュール

 

シャシーの精度とサスペンション

かなり前に友人とロボットランサー競技に参加した頃は、HPIタミヤのラジコンを流用していた。写真は2004年の第7回大会に参加したランサーで、タミヤTA03R-Sのフロントとリアブロックをポリカーボネイト板のダブルデッキで繋ぎホイールベースを短くし、後輪もステアする4WDS仕様だった。結果は10位だったと記憶している。ラジコンのタイヤにはキャスター角がついているため、アッカーマン方式で操舵すると左右タイヤの接地具合に差が出るが、サス機構が吸収してくれていた。

暫く大会から遠ざかり、2010年の第13回大会に久しぶりに参加しようと思い立ち、マイコンカーラリーの機体を参考にタミヤのギヤボックスを使ってサス機構無しの軽量シンプルな機体を目指した。推進用のタミヤハイスピードギヤボックスをポリカーボネイト板で挟むダブルデッキ構造にしたところ、適当な剛性を得た反面、ポリカ板のねじ穴加工の位置精度が低く組立時のシャシーが僅かに捻れ、その捻じれが4つのタイヤの上下位置の差に現れた。

キャスター角はゼロ設定でキャスター角に起因するステア時のタイヤ接地の変化の問題は無かったが、サスを省略したため4輪の接地圧の差が直進性を悪化させた。ここに工作精度の大切さとサスがもたらす副次的効果を理解し、シャシーの工作精度不足をカバーする程度のサス機構を搭載する必要性を感じた。結果、アクリル板のレーザー加工による部品精度の向上と、シャシー板の切り欠きによるサス効果の確保という、現在のスタイルに至る。

TA03R-Sを流用した第7回大会出場マシン”yariyari2004R"