LancerStratos’s blog

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

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の実験