06-08-2023 01:31 AM
ILX511はTCD1304に比べて画素幅が8μmから14μmに大きくなって画素数が3648から2048に少なくなっています。
TCD1304を使った記事は https://forums.ni.com/t5/北東北-LabVIEWユーザー会/分光器のラインセンサー-TCD1304-をESP32で制御して分光データをLabVIEW-Communityで受け取... です。
センサー変更で感度を幾らかでも上げたいというマツラボさんの希望でILX511を試してみることにしました。
分光器への取り付け基板です。74HC04を介していますのでESP32からの信号は反転させています。データを受け取るLabVIEWプログラムは基本的にTCD1304用と同じですので、ESP32のプログラムがこの記事での新しい部分です。今回はArduino IDE 1.8.19を使用して、500msec間隔で動作させています。
//Koji Ohashi MaDA Lab@Morioka 230507
//ILX511_Esp32230507
//Software: Arduino IDE 1.8.19
//Software: Arduino core for the ESP32 2.0.6
//パルス生成:Special thanks to
//https://www.mgo-tec.com/blog-entry-ledc-pwm-arduino-esp32.html/2
//https://logikara.blog/pwm/
//割り込み処理:Special thanks to
//https://lang-ship.com/blog/work/esp32-freertos-l04-interrupt/
//for SONY ILX511
//バッファ用反転ICが入るのでプログラムのIOは反転
//CLK IO5
//ROG IO18
//Trig_RO IO26 //internal use
//VOUT IO27(Analog In) Trig_ROがFallのタイミングで読む
//ROG
#define ROG_PIN 18
#define ROG_WIDTH 100 //100μsec
#define ROG_INTRVAL_MS 500 //500msec(reading:210msec, sending:180msec)
//CLK
#define CLK_PIN 5 //GPIO #36~#39 は設定不可
#define LEDC_CHANNEL_CLK 0 //CHANNEL_0 (CHANNEL_0とCHANNEL_1は周波数とタイマービットを同一値)
#define LEDC_TIMER_BIT_CLK 6 //6bit--64(0-63)
#define LEDC_BASE_FREQ_CLK 10000.0 //AnalogReadに時間がかかって13kHzが上限
#define DUTY_CLK 32//50% 0x20 = 32
//TrigRO
#define GPIO_PIN_TrigRO 26 //GPIO #36~#39 は設定不可
#define LEDC_CHANNEL_TrigRO 1 //CHANNEL_1 (CHANNEL_0とCHANNEL_1は周波数とタイマービットを同一値)
#define LEDC_TIMER_BIT_TrigRO 6 //6bit--64(0-63)
#define LEDC_BASE_FREQ_TrigRO 10000.0 //AnalogReadに時間がかかって13kHzが上限
#define DUTY_TrigRO 32//50% 0x20 = 32
#define PIXELS 2086
#define ReadRO_PIN 27
int16_t pixelArray[PIXELS];
volatile int read_count=0;
volatile int16_t sensorValue=0;
volatile boolean risingEdge=false;
byte HEADER[]={0x00,0x00,0xFF,0xFF};
byte SendBytes[2];
//割り込み関数***************
//ARDUINO_ISR_ATTRに変更になった
void ARDUINO_ISR_ATTR readRO(){
sensorValue = analogRead(ReadRO_PIN);
pixelArray[read_count]=sensorValue;
read_count++;
}
void ARDUINO_ISR_ATTR risingCLK(){
risingEdge=true;
}
//割り込み関数***************
void setup() {
Serial.begin(230400);
pinMode(ROG_PIN,OUTPUT);
pinMode(CLK_PIN,OUTPUT);
pinMode(ReadRO_PIN,ANALOG);
//CLK 必要な時だけ出力する
ledcSetup(LEDC_CHANNEL_CLK, LEDC_BASE_FREQ_CLK, LEDC_TIMER_BIT_CLK);
//TrigRO 割り込みに使用するため常に出力する
ledcSetup(LEDC_CHANNEL_TrigRO, LEDC_BASE_FREQ_TrigRO, LEDC_TIMER_BIT_TrigRO);
ledcAttachPin(GPIO_PIN_TrigRO, LEDC_CHANNEL_TrigRO);
ledcWrite(LEDC_CHANNEL_TrigRO, DUTY_TrigRO);
}
void loop() {
unsigned long startCLK = millis();
digitalWrite(CLK_PIN,LOW);
delayMicroseconds(50); //10kHzの周期の1/2
digitalWrite(CLK_PIN,HIGH);
delayMicroseconds(50); //10kHzの周期の1/2
digitalWrite(ROG_PIN,HIGH);
digitalWrite(CLK_PIN,LOW);
delayMicroseconds(ROG_WIDTH);//100μSec
digitalWrite(ROG_PIN,LOW);
// CLKに使うパルスがHIGHになるまで待つ
risingEdge=false;
attachInterrupt(GPIO_PIN_TrigRO, risingCLK, RISING); //割り込み開始
while(risingEdge==false){ //wait rising edge
}
digitalWrite(CLK_PIN,HIGH); //CLKをHIGHにする
detachInterrupt(GPIO_PIN_TrigRO);//割り込み解除
ledcAttachPin(CLK_PIN, LEDC_CHANNEL_CLK);//CLKパルスを出力
ledcWrite(LEDC_CHANNEL_CLK, DUTY_CLK);//CLKパルスを出力
read_count=0;
attachInterrupt(GPIO_PIN_TrigRO, readRO, FALLING);
//Reading CCD data
while(read_count < PIXELS){
//全てのPIXELを読み込むまで待つ
}
detachInterrupt(GPIO_PIN_TrigRO);
ledcDetachPin(CLK_PIN); //CLKパルスを停止
digitalWrite(CLK_PIN,HIGH); //CLKをHIGHにする
//Serial.println(read_count);
//Serial.println(millis()-startCLK);
writeArrayData();
//Serial.println(millis()-startCLK);
while((millis()-startCLK) < ROG_INTRVAL_MS){
//wait ROG Interval
}
//Serial.println(millis()-startCLK);
}
void writeArrayData(){
Serial.write(HEADER,4);
for(int i=0;i<PIXELS;i++){
sensorValue = pixelArray[i];
SendBytes[0] = byte(sensorValue);
SendBytes[1] = byte(sensorValue >> 8);
Serial.write(SendBytes,2);
}
}
ROG信号(オレンジ)とCLK信号(青)のオシロスコープ画面(左)
ROG信号(オレンジ)とVout(青)のオシロスコープ画面(右)
ILX511の方が扱いやすいような印象を持ちました。
時間を作って、ラズパイPico互換ボードとMicroPythonで動かしてみたいなと思っています。
プログラム一式を添付しました。LabVIEWはCommunity 2023で作ってしまったのでお手数ですがLabVIEW Community 2023をお使いください。