Perangkat penglihatan malam berdasarkan modul pencitraan termal Flir Lepton 3

Sebelumnya, saya menulis artikel tentang menghubungkan set-top box pencitraan termal ke smartphone Flir One Gen 2. Sudah waktunya untuk menghapus modul lepton dari set-top box ini dan menghubungkannya langsung ke mikrokontroler dengan merakit perangkat night-vision dengan resolusi 160x120 piksel.

Untuk membangun perangkat pencitraan termal penglihatan malam Anda sendiri, Anda perlu:

1) Papan dengan mikrokontroler. Saya mengambil papan dari seorang teman China dengan mikrokontroler STM32F407VGT6. Kontroler yang baik: frekuensi 168 MHz dan RAM 192 KB.



2) Tampilan. Saya mengambil layar dengan resolusi 320x240. Tampilan seperti itu datang dengan berbagai pengontrol. Saya mendapatkannya dengan controller hx8347d.



3) Papan untuk menghubungkan lepton 3 pada SPI dan I2C.



4) Lepton itu sendiri 3. Unsur yang paling sulit dan mahal. Untuk mendapatkannya, saya membeli imager termal Flir One Gen 2 yang rusak di ebay dan mengeluarkan lepton darinya. Itu terlihat dalam pembesaran seperti ini:



Anda dapat mengecualikan item 3 dari daftar ini, kecuali, tentu saja, Anda berhasil mengambil buaian untuk lepton dari imager termal yang tidak berfungsi dan Anda dapat melepaskannya (dan kontaknya, dengan cara, akan dari bawah). Sayangnya, jarak antara kedua kaki di lepton cukup kecil, jadi opsi ini tidak diserahkan kepada saya.

Untuk mengumpulkan semua ini, Anda hanya perlu mensolder semuanya sebagai berikut:



Anda juga perlu menghubungkan daya. Untuk menyalakan papan lepton saya menggunakan 5 V, untuk papan STM32 3.3 V. Untuk mendapatkan 5 V dari baterai, saya menggunakan konverter TEL3-0511 (tegangan input dari 4,5 ke 9 V), dan sudah menurunkan 5 V ini pada LP2950CZ-3.3 biasa (omong-omong , memanas hingga 70 derajat. Di sini, Anda juga perlu menggunakan konverter DC / DC, tapi saya belum membelinya). Ngomong-ngomong, Lepton 3 makan. Ketika diberdayakan dari 6 V, konsumsi saat ini dari seluruh perangkat adalah sekitar 250 mA. Ketika lepton ingin mengklik rana untuk kalibrasi, arus naik ke 500 mA.

Semuanya disatukan terlihat seperti ini:





Untuk bekerja dengan lepton, Anda memerlukan sebuah program. Saya menggunakan CubeMX dan Keil 5. Dalam hal ini, semua binding perangkat lunak disederhanakan menjadi tidak mungkin.

Komunikasi dengan lepton dilakukan pada SPI. Saya belum pernah menggunakan I2C, karena tidak ada kebutuhan khusus untuk itu. Menurut I2C, Anda dapat mengontrol status lepton, mode operasinya, mengaktifkan / menonaktifkan mode kalibrasi otomatis, dan sebagainya. Tetapi untuk perangkat penglihatan malam, ini tidak terlalu perlu.

Untuk mendekripsi data, saya menulis modul:

Modul
leptoncontrol.h
#ifndef LEPTON_CONTROL_H #define LEPTON_CONTROL_H #include <stdbool.h> #include <stdio.h> //   ( ) #define LEPTON_ORIGINAL_IMAGE_WIDTH 160 #define LEPTON_ORIGINAL_IMAGE_HEIGHT 120 //  VoSPI #define VOSPI_FRAME_HEIGHT 60 //  VoSPI #define VOSPI_FRAME_WIDTH 80 //  VoSPI   (164  RAW14  244  RGB) #define VOSPI_PACKAGE_SIZE 164 //   VoSPI   #define VOSPI_PACKAGE_LINE_SIZE 160 //  VOSPI   #define VOSPI_SEGMENT_LINE_AMOUNT 60 void LEPTONCONTROL_Init(void);// void LEPTONCONTROL_CalculateCRC(unsigned short *crc,unsigned char byte);// crc bool LEPTONCONTROL_PushVoSPI(unsigned char data[VOSPI_PACKAGE_SIZE],bool *first_line);//    VoSPI    unsigned short *LEPTONCONTROL_GetRAW14Ptr(void);//      #endif 

leptoncontrol.c

 #include "leptoncontrol.h" #include "stm32f4xx_hal.h" static unsigned short RAW14Image[LEPTON_ORIGINAL_IMAGE_HEIGHT*LEPTON_ORIGINAL_IMAGE_WIDTH];//  static unsigned short CRCTable[256];//   CRC16 //     #define RESYNC_TIMEOUT_MS 19 //:   #define NO_SEGMENT -1 //:   #define ERROR_PACKAGE -2 //---------------------------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------------------------- void LEPTONCONTROL_Init(void) { //    CRC unsigned short code; for(long n=0;n<256;n++) { code=((unsigned short)n)<<8; for(unsigned char m=0;m<8;m++) { if(code&(1<<15)) code=(code<<1)^0x1021; else code=code<<1; } CRCTable[n]=code; } } //---------------------------------------------------------------------------------------------------- // crc //---------------------------------------------------------------------------------------------------- void LEPTONCONTROL_CalculateCRC(unsigned short *crc,unsigned char byte) { *crc=CRCTable[(((*crc)>>8)^byte++)&0xFF]^((*crc)<<8); } //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- long LEPTONCONTROL_ReadSegment(unsigned short *raw14_ptr,unsigned char data[VOSPI_PACKAGE_SIZE],bool *first_line) { static long current_package=-1; static long segment=-1; long n; *first_line=false; if ((data[0]&0x0F)==0x0F) return(NO_SEGMENT);//  unsigned short crc=data[2]; crc<<=8; crc|=data[3]; // CRC unsigned short crc16=0; LEPTONCONTROL_CalculateCRC(&crc16,data[0]&0x0F); LEPTONCONTROL_CalculateCRC(&crc16,data[1]); LEPTONCONTROL_CalculateCRC(&crc16,0); LEPTONCONTROL_CalculateCRC(&crc16,0); for(n=4;n<VOSPI_PACKAGE_SIZE;n++) LEPTONCONTROL_CalculateCRC(&crc16,data[n]); if (crc16!=crc) return(ERROR_PACKAGE);// CRC //   unsigned short package=data[0]&0x0F; package<<=8; package|=data[1]; if (package==0) { *first_line=true; current_package=0; } if (package==20) { unsigned char ttt=(data[0]&0x70)>>4;//     20  segment=ttt; } if (current_package<0) return(NO_SEGMENT); if (current_package!=package) { current_package=-1; return(ERROR_PACKAGE); } unsigned short *raw_ptr=raw14_ptr+current_package*VOSPI_PACKAGE_LINE_SIZE/2; for(n=0;n<VOSPI_PACKAGE_LINE_SIZE/2;n++,raw_ptr++) { //    big-endian: ,  unsigned short value=data[n*sizeof(short)+4]; value<<=8; value|=data[n*sizeof(short)+5]; *raw_ptr=value; } current_package++; if (current_package!=VOSPI_FRAME_HEIGHT) return(NO_SEGMENT); current_package=-1; return(segment); } //---------------------------------------------------------------------------------------------------- //    VoSPI    //---------------------------------------------------------------------------------------------------- bool LEPTONCONTROL_PushVoSPI(unsigned char data[VOSPI_PACKAGE_SIZE],bool *first_line) { *first_line=false; static long waitable_segment=1; long segment=LEPTONCONTROL_ReadSegment(RAW14Image+(waitable_segment-1)*VOSPI_FRAME_WIDTH*VOSPI_SEGMENT_LINE_AMOUNT,data,first_line); if (segment==ERROR_PACKAGE) HAL_Delay(RESYNC_TIMEOUT_MS); if (segment==ERROR_PACKAGE || segment==0) waitable_segment=1; if (segment==ERROR_PACKAGE || segment==NO_SEGMENT || segment==0) return(false); if (segment!=waitable_segment) { waitable_segment=1; if (segment!=1) return(false); } waitable_segment++; if (waitable_segment!=5) return(false); waitable_segment=1; return(true); } //---------------------------------------------------------------------------------------------------- //      //---------------------------------------------------------------------------------------------------- unsigned short *LEPTONCONTROL_GetRAW14Ptr(void) { return(RAW14Image); } 


Semua pekerjaan dengan modul ini terdiri dari pengiriman data sederhana yang diperoleh SPI.

Bekerja dengan modul
 while(1) { //   while(1) { HAL_SPI_Receive(&hspi1,buffer,VOSPI_PACKAGE_SIZE,0x1000); bool first_line=false; unsigned char *buffer_ptr=buffer; LEPTONCONTROL_PushVoSPI(buffer_ptr,&first_line); if (first_line==true) break; } //    lepton3 unsigned char *buffer_ptr=buffer; HAL_SPI_Receive(&hspi1,buffer_ptr,VOSPI_PACKAGE_SIZE*SPI_READ_VOSPI_AMOUNT,0x1000); buffer_ptr=buffer; for(long n=0;n<SPI_READ_VOSPI_AMOUNT;n++,buffer_ptr+=VOSPI_PACKAGE_SIZE) { bool first_line=false; bool res=LEPTONCONTROL_PushVoSPI(buffer_ptr,&first_line); if (res==true) CreateImage();//     } } 


Setelah merakit bingkai, pembacaan sensor dinormalisasi, dikurangi menjadi kisaran [0..255] dan ditampilkan pada layar dalam bentuk nuansa abu-abu. Namun, tidak ada yang mencegah menggunakan palet apa pun untuk mewarnai gambar.

Untuk menampilkan gambar pada tampilan, saya menggunakan modul FSMC yang dibangun pada pengontrol ini dalam mode bus data 8-bit.

Program lengkap dapat diunduh di sini .

Video kerja (sayangnya, saya memotret pada kamera lama dengan kualitas yang sesuai - Saya tidak memiliki kamera video sekarang).


Ngomong-ngomong, Anda dapat menghubungkan imager termal Flir One Gen 2 ke papan debug STM32F407Discovery langsung melalui USB. Namun, koneksi tidak stabil - imager termal sering hilang.


Program untuk koneksi semacam itu ada di sini . Mungkin seseorang akan mengerti apa itu dan bagaimana membuat koneksi stabil.

Juga, modul lepton 3 ini dengan mudah dan mudah terhubung ke Raspberry Pi.


Dalam hal ini, saya harus memodifikasi program dari repositori , membuat versi saya berfungsi dengan lepton 3.

Source: https://habr.com/ru/post/id413021/


All Articles