2016年12月22日

冬コミ出展告知


今回は直近のイベントを告知させて頂きます。


12/29(木)  東京ビックサイトにて開催される
コミックマーケットにProjectionBallを出展します。


クラウドファンディング時に支援して頂いた親方様からお誘いを受け、
出展することになりました。


Projection Ballの技術解説やクラウドファンディングの経験など
まとめた記事を寄稿させて頂きました。

1日目参加される方はお立ち寄りいただければと思います。
1日目 木曜日 西1ホール む13aでお待ちしております。


**************
コミックマーケットC91
12/29(木)1日目 @東京ビックサイト
西1ホール む13a
親方プロジェクト
**************


よろしくお願いいたします。
posted by Crescent at 00:00| Comment(0) | TrackBack(0) | イベント | このブログの読者になる | 更新情報をチェックする

2016年12月18日

距離センサVL53L0X動作テスト

今回は距離センサVL53L0Xを試食してみたので、
ご紹介します。

先日、素子単体が秋月でも発売されたようですが、
電圧が標準2.8Vで素子が小さいため、
変換基板がないと少し厳しいかもしれません。


IMG_3732_.jpg



環境はこれまで同様、
・STM32F303K8
 +SW4STM32(System Workbench for STM32)
 +STM32CubeMX(F3_1.6.0)
です。


距離センサVL53L0XはST製の評価用基板セット(2個入り)を使用しました。

STから提供されているライブラリは
キャリブレーションやジェスチャなどコードが膨大なため、
動作テストに必要なコードのみ引き出したコードを使用してテストしてみました。
正規のキャリブレーションを行っていないため、
動作の保証はできません。
あくまでテスト確認用です。



コード例は下記の通りです。

#include "stm32f3xx_hal.h"

#define VL53L0X_Address    0x52
#define VL53L0X_REG_IDENTIFICATION_MODEL_ID         0xc0
#define VL53L0X_REG_IDENTIFICATION_REVISION_ID      0xc2
#define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD   0x50
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
#define VL53L0X_REG_SYSRANGE_START                  0x00
#define VL53L0X_REG_RESULT_INTERRUPT_STATUS         0x13
#define VL53L0X_REG_RESULT_RANGE_STATUS             0x14



uint8_t buf[16];


uint16_t VL53L0X_decode_vcsel_period(short vcsel_period_reg) {
  uint16_t vcsel_period_pclks = (vcsel_period_reg + 1) << 1;
  return vcsel_period_pclks;
}

uint16_t convuint16(int lsb, int msb) {
    return ((msb & 0xFF) << 8) | (lsb & 0xFF);
}

void write_byte_data_at(uint8_t reg, uint8_t data) {
     uint8_t val[1];
     val[0]=data;
     HAL_I2C_Mem_Write(&hi2c1, VL53L0X_Address, reg, I2C_MEMADD_SIZE_8BIT, val, 1, 1000);
}

uint8_t read_byte_data_at(uint8_t reg) {
    uint8_t value;
    HAL_I2C_Mem_Read(&hi2c1, VL53L0X_Address, reg, I2C_MEMADD_SIZE_8BIT, &value, 1, 1000);
  return value;
}

void read_block_data_at(uint8_t reg, int sz) {
    HAL_I2C_Mem_Read(&hi2c1, VL53L0X_Address, reg, I2C_MEMADD_SIZE_8BIT, buf, sz, 1000);
}



void Vl53L0X_Test(void){

     uint8_t val1 ;
   //CHK Param
      val1 = read_byte_data_at(VL53L0X_REG_IDENTIFICATION_REVISION_ID);
      printf("Revision ID: %d, ",val1);

      val1 = read_byte_data_at(VL53L0X_REG_IDENTIFICATION_MODEL_ID);
      printf("Device ID:  %d \n",val1);

      val1 = read_byte_data_at(VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD);
      printf("PRE_RANGE_CONFIG_VCSEL_PERIOD: %d \n",val1);
      printf(" decode:   %d \n",VL53L0X_decode_vcsel_period(val1));

      val1 = read_byte_data_at(VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD);
      printf("FINAL_RANGE_CONFIG_VCSEL_PERIOD: %d \n",val1);
      printf(" decode:   %d \n",VL53L0X_decode_vcsel_period(val1));

   //Init Start
      write_byte_data_at(VL53L0X_REG_SYSRANGE_START, 0x01);

      uint8_t val = 0;
      int cnt = 0;
      while (cnt < 100) { // 1 second waiting time max
          HAL_Delay(10);
        val = read_byte_data_at(VL53L0X_REG_RESULT_RANGE_STATUS);
        if (val & 0x01) break;
        cnt++;
      }
      if (val & 0x01) printf("Ready!! \n"); else printf("Not Ready!!");

      read_block_data_at(0x14, 12);
      uint16_t acnt = convuint16(buf[7], buf[6]);
      uint16_t scnt = convuint16(buf[9], buf[8]);
      uint16_t dist = convuint16(buf[11], buf[10]);
      uint8_t DeviceRangeStatusInternal = ((buf[0] & 0x78) >> 3);

      //printf("ambient count: %d, signal count: %d, distance: %d, status: %d  \n",
      //        acnt,scnt,dist,DeviceRangeStatusInternal);
   printf("RES: %d mm  \n",dist);

}

uint8_t VL53L0X_Address_Test(void){

     uint8_t tmp[2];
     HAL_I2C_Mem_Read(&hi2c1, VL53L0X_Address, 0xC1, I2C_MEMADD_SIZE_8BIT, tmp, 1, 100);
   
     if(tmp[0]==0xAA){
         printf("VL53L0X is Found! \n");
         return true;
     }
     else{
         printf("VL53L0X is NOT Found! ERROR! \n");
         return false;
     }

}


実際にVl53L0X_Testを実行して距離を計測してみました。



vl53.png



最初、内部メモリ内のデータに異常があったようで
SPAD初期化に失敗するという状況でした。
最低限の初期化のみを実行すると正常そうな値を返すようになりました。

STのサイトからダウンロードしたライブラリやAPIはあまりにも
膨大で複雑な処理をしているため、
遊びの距離センサとして使うには少し敷居が高いかもしれません。




posted by Crescent at 00:00| Comment(0) | TrackBack(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする

2016年12月13日

赤外線グリッドセンサMLX90621

今回は赤外線グリッドセンサMLX90621を試食してみたので、
ご紹介します。

IMG_4085.JPG

赤外線グリッドセンサは安価なサーモカメラという感じです。
非接触で物体の温度の分布を取得することができます。


Digikey等で日本国内で購入できる
赤外線グリッドセンサとして下記があります。
MLX90621 解像度16x4 Digikey MELEXIS製 5千円程度
検出角で3種類有

D6T44L06 解像度4x4 Digikey オムロン製 7千円程度
8x1の解像度も有

がありますが、日本では個人で購入できないようです。



※参考
ガチなサーモカメラモジュール
FLIR LEPTON 秋月電子通商は80x60で高解像度
ただ、価格も10倍、5万円弱・・・



環境はこれまで同様、
・STM32F303K8
 +SW4STM32(System Workbench for STM32)
 +STM32CubeMX(F3_1.6.0)
です。



赤外線グリッドセンサMLX90621のデータ資料を見ると、
I2Cの通信に少し癖があることが分かりました。

一般的な通信としては
デバイスアドレス1byte+レジスタ1byte+デバイスアドレス1byte+データXXbyte
という流れです。

一方、
赤外線グリッドセンサMLX90621は一部の通信では
デバイスアドレス1byte+レジスタ4byte+デバイスアドレス1byte+データXXbyte
という感じでレジスタが4byteです。

STM32のHALライブラリではI2Cの関数として
HAL_I2C_Mem_Read
HAL_I2C_Mem_Write
が用意されており、簡単に通信可能ですが
レジスタ長が1byteもしくは2byteです。
4byteには対応していません。

そのため、HALライブラリのI2Cを一部、変更して
レジスタ長が3byteと4byteに対応させました。
※MLX90621自体は3byteは未使用

HAL_I2C_Mem_Read2
I2C_RequestMemoryRead2
stm32f3xx_hal_i2c.c に作成。

#define I2C_MEMADD_SIZE_24BIT           (0x00000003U)
#define I2C_MEMADD_SIZE_32BIT           (0x00000004U)
stm32f3xx_hal_i2c.hに追加しました。


追加した関数の詳細やMLX90621の処理の詳細は
STM32F303_i2c_MLX90621.zipを参考にどうぞ。
パスはブログ名です。


実際にハンダごてを観察してみた結果を
UartでPCへ出力してエクセルの条件書式カラースケールで
色分けしてみました。


temp.png

中心付近が200度程度になっていることが分かります。
物体によって放射率が異なるため、
補正しないと温度として正しく読めませんが、
温度の分布を得るには十分だと思いました。


温度補正の他に画素補間技術等で
更に高分解能にしてみるのも面白いと思います。


I2Cの通信に少し癖がありましたが、
ライブラリ関数を少し手直しするだけで動作できました。

最近、秋月から発売されたシリアルカメラと組み合わせて
応用ができそうです。





posted by Crescent at 00:00| Comment(0) | TrackBack(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする

2016年12月08日

math関数使用時のエラー対処

今回はSTM32でのmath関数使用時のエラー対処について紹介します。

以前にご紹介したDSP処理の前設定2でも同じようなエラーがでましたが、
以前はDSPを使用した関数でした。
今回はDSP関数は使用せず、math関数使用時のエラー対処方法です。



環境はこれまで同様、
・STM32F303K8
 +SW4STM32(System Workbench for STM32)
 +STM32CubeMX(F3_1.6.0)
です。


main.c関数中でpowなど使う分には問題ありませんでしたが、
読み込んだヘッダやドライバ系にpow関数を使うと
下記のようなエラーが発生してコンパイルできませんでした。


w_pow.c:(.text.pow+0x): undefined reference to `__errno'
collect2.exe: error: ld returned 1 exit status
make: *** [STM32F.elf] Error 1


Eclipseのプロジェクトから
「C/C++ Build」→「Settings」→「ToolSettings」→「MCU GCC Linker」
「Libraries」に下記のように
m
を追加します。


ffff.png


上記のようなエラーに遭遇するパターンがいくつかあるため、
今回はmの追加で回避できました。

posted by Crescent at 00:00| Comment(0) | TrackBack(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする

2016年12月03日

GPIOを介したSDカード読み書き


今回はSTM32でのGPIOでSDカードの読み書きについて紹介します。
特にSTM32F303K8等ではSPIが1つしかなく、SDIOもないため、
CubeMXで自動生成されず、
SDカードの読み書きに苦労するところです。

ChanさんのFatFSモジュールを使用して
STM32のGPIOによるSDカード読み書きを紹介します。

読み書きの速度に期待はできないものの、
空きのGPIOで自由に使用可能なため、
汎用性は非常に高いです。

環境はこれまで同様、
・STM32F303K8
 +SW4STM32(System Workbench for STM32)
 +STM32CubeMX(F3_1.6.0)
です。


CubeMXでSDカードで使用するGPIOを定義します。
最低限はCS,CLK、MOSI、MISOの4つです。
MISOのみInput、他はOutputで定義します。
プルアップ及びハイスピード設定を有効にします。

今回は
CS:PA11(D10)
CLK:PB5(D11)
MOSI:PB4(D12)
MISO:PB3(D13)
で定義しました。

※Chanさんのモジュールを使用するため、
  CubeMX自体のFatFSはチェックをいれません。


下の方にある「サンプルプロジェクト」をダウンロードします。

ffsampleフォルダ内のgenericフォルダのコードを使用します。
Workspace内のIncとSrcにそれぞれ下記のファイルを入れます。
diskio.h、ff.c、ff.h、ffconf.h、interger.h、sdmm.c


STM32ですぐ使えるように設定変更します
◆ffconf.h
 //RTC無効化
 #define _FS_NORTC    1
 //LFN無効化
 #define    _USE_LFN    0

◆sdmm.c

#define DO_INIT()                             
#define DO            HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)

#define DI_INIT()                              
#define DI_H()        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET)
#define DI_L()        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET)

#define CK_INIT()                              
#define CK_H()        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)
#define CK_L()        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET)

#define CS_INIT()                          
#define CS_H()        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET)
#define CS_L()        HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET)



dly_us (UINT n)関数内のPINB;をコメントアウト

select (void)関数が名前が重複するため、
適当な他の名前に置き換え、sdmm.c内のselectを置き換えた名前に2か所変更。

#include <avr/io.h> をコメントアウトして#include "stm32f3xx_hal.h" に変更。


あとは、main.c内で
#include "ff.h"をインクルード

FATFS FatFs;      
FIL Fil;           
を変数定義

while(1)の中で下記を実行。


     int bw;
           if(f_mount(&FatFs, "", 1)==FR_OK)printf("Mount OK!! \n");
           else {
               printf("Mount Fail!! \n");
               while(1);
           }
                  
           if (f_open(&Fil, "newfile.txt", FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {  

                   f_write(&Fil, "It works!!!!!!!\r\n", 16, &bw);   
                   f_close(&Fil);                               

                   if(bw==16)printf("Write OK!! \n");
                   while(1);

            }
      else{
                   printf("Open Fail!! \n");
                   while(1);
            }
これでGPIOを使って書き込みができます。
GPIOの書き込みは思った以上に簡単にできました。



posted by Crescent at 00:00| Comment(1) | TrackBack(0) | 電子工作 | このブログの読者になる | 更新情報をチェックする