catalogue
2, CCS engineering code part code
prefaceI got a Luna Mini lidar of TOF some time ago. I always wanted to get it. I saw it just yesterday, so I spent a day writing a driving protocol. The little partners needed for the video game can refer to it.
1, TOFLuna lidarThis is the official instruction:
It can be seen that the radar is still very small, but it is a little expensive......
TF Luna has two working modes, one is serial communication mode and the other is I2C communication mode. The Protocol I write here is serial communication. Please supplement the I2C communication protocol when you have time. (digging + 1)
1. Working principle
Ranging principle
TF Luna is based on TOF (time of flight) principle. Specifically, the product periodically sends out near-infrared light modulation wave, which is reflected when it meets an object. The product obtains the flight time by measuring the round-trip phase difference of the modulation wave, and then calculates the relative distance between the product and the measured target. As shown in the figure, the measurement distance of 0.2m~8m is still far.
Data transmission analysis
It can be seen from the figure that in the 9-byte cm data format, the first and second bits are 0x59, that is, the signal start bit, the third and fourth bits are the lower 8 bits and the higher 8 bits of the distance data, the fifth and sixth bits are the lower 8 bits and the higher 8 bits of the signal strength data, and the seventh and eighth bits are the lower 8 bits and the higher 8 bits of the temperature data. The calculation formula is Temp / 8-256, After knowing the data format, we can start to write the protocol. Of course, we mainly write it according to the instruction manual.
2, CCS engineering code part codemain.c
/****************************************************/ // MSP432P401R // laser ranging // Bilibili: Balala 1 energy // CSDN: quiet · no envy // E-mail:[email protected] // Created on: October 31, 2021 /****************************************************/ #include "sys.h" /* Global variable declaration area */ /* extern variables ----------------------------------------------------------*/ /* Function call declaration area */ int main(void) { System_init(); while(1) { Get_Distance(); } }
tof.c
/****************************************************/ // MSP432P401R // laser ranging // Bilibili: Balala 1 energy // CSDN: quiet · no envy // E-mail:[email protected] // Created on: October 31, 2021 /****************************************************/ #include "tof.h" #include "usart.h" #include "oled.h" #include "delay.h" /************************************** Global variable*******************************************/ uint8_t Freq;//output frequency uint8_t I2C_slave_addr;//I2C slave address uint8_t Dist_min_High,Dist_min_Low,Dist_max_High,Dist_max_Low;//Distance limit variable uint32_t timeout; uint16_t Distance,Sign,Temp; Format_Type TOF_Format = Format_CM;//9 byte CM output mode Output_Type TOF_Output = Output_On;//Enable output Checksum_Type TOF_Checksum = Frame_Checksum_Off;//Turn off checksum Filter_Type TOF_Filter = Filter_bit;//Turn on Kalman filter and median filter Power_Type TOF_Power = Low_Power_Mode_OFF;//Exit ultra low power mode DEALIAS_Type TOF_Freq = Dobule_Freq_Mode;//Dual Mode CONFIG_Type TOF_Config;//Radar configuration /************************************** Instruction set*******************************************/ uint8_t LOW_POWER_MODE[5] = ;//Turn off and turn on super power consumption mode uint8_t SAVE_SETTINGS[4] = ;//When saving the current settings, the returned data is [0x5a, 0x05, 0X11, data, 0x6f]. If the data is 0, it will succeed, and if it is not 0, it will fail. uint8_t SOFT_RESET[4] = ;//System software reset uint8_t SAMPLE_FREQ[6] = ;//Set output frequency uint8_t SAMPLE_TRIG[4] = ;//Single trigger instruction uint8_t OUTPUT_FORMAT[5] = ;//Format output uint8_t BAUD_RATE[8] = ;//Set serial port baud rate 115200 uint8_t OUTPUT_EN[5] = ;//Output switch uint8_t FRAME_CHECKSUM[5] = ;//Checksum switch uint8_t I2C_SLAVE_ADDR[5] = ;//Modify I2C slave address range [0x08,0x77] uint8_t RESTORE_DEFAULT[4] = ;//Restore the factory settings. The returned data is [0x5a, 0x05, 0x10, data, 0x6f]. If the data is 0, it will succeed, and if it is not 0, it will fail. uint8_t READ_MANU_BIN[4] = ;//Read production barcode uint8_t LOW_CONSUMPTION[6] = ;//Low power mode uint8_t FILTER_BIT_MAP[5] = ;//Filter settings enable Kalman filtering and median filtering uint8_t DIST_LIMIT[9] = ;//Set distance limit uint8_t GET_CONFIG_PARA[5] = ;//Read the specified radar configuration /************************************** Serial baud rate*******************************************/ /* * 9600 [5A 08 06 80 25 00 00 00] * 19200 [5A 08 06 00 4B 00 00 00] * 38400 [5A 08 06 00 96 00 00 00] * 57600 [5A O8 06 00 E1 00 00 00] * 115200 [5A 08 06 00 C2 01 00 00] * 230400 [5A 08 06 00 84 03 00 00] * 460800 [5A 08 06 00 08 07 00 00] * 921600 [5A 08 06 00 10 OE 00 00] * */ void TOF_init(void) { Freq = 0x00;//Set the frequency to 0 Send_Data(SAMPLE_FREQ);//Set frequency Send_Data(SAMPLE_TRIG);//Single trigger instruction waitflag=1; rxcnt=0; } void Get_Distance(void) { Send_Data(SAMPLE_TRIG);//Single trigger instruction timeout=10000; while((rxflag==0)&&(timeout--)); //In case of active transmission, you only need to query the rxflag flag bit if(rxflag)//Received a set of valid data { Distance = rxbuf[Dist_H] * 256 + rxbuf[Dist_L]; Sign = rxbuf[Amp_H] * 256 + rxbuf[Amp_L]; Temp = rxbuf[Temp_H] * 256 + rxbuf[Temp_L]; Temp = Temp / 8 -256; rxflag = 0; rxcnt = 0; sprintf((char*)str,"Distance=%dCM ",Distance); OLED_ShowString(1,0,str,12); sprintf((char*)str,"Sign=%d ",Sign); OLED_ShowString(2,12,str,12); sprintf((char*)str,"Tempt=%d ",Temp); OLED_ShowString(2,24,str,12); OLED_Refresh(); } } void Send_Data(uint8_t *COM_DATA) { int i; for(i = 0;i < *(COM_DATA + 1);i++) { USART0PutChar(*(COM_DATA + i)); } } /****************************************************/ //(1) Enter ultra low power mode /*Enable the ultra-low power consumption mode through the instruction "ultra-low power consumption mode id_low_power_mode = ox58". After the instruction is issued, TF Luna stops the serial port output, but does not immediately enter the ultra-low power consumption mode, TF Luna will not enter the ultra-low power consumption mode until the instructions "save current settings id_settings = 0X11" and "system software reset ID_SOFT_RESET=Ox02" are sent successively. Since the configuration has been saved, it will directly enter this mode after power on again. */ /****************************************************/ void TOF_LOW_POWER_MODE_ON(Power_Type Power_Mode) { TOF_Power = Power_Mode; LOW_POWER_MODE[3] = TOF_Power; Send_Data(LOW_POWER_MODE); delay_us(1); Send_Data(SAVE_SETTINGS); delay_us(1); Send_Data(SOFT_RESET); } /****************************************************/ /*(2)Wake up ranging The user sends any byte of data to TF Luna through the serial port to wake up TF Luna for ranging. After ranging, the user sends the ranging result in the specified format through the serial port, and then enters the ultra-low power consumption mode again. Taking 115200 baud rate and 9-byte output format as an example, the wake-up time is about 8.5ms. */ /****************************************************/ void Wake_Up_Get_Distense(void) { uint8_t Wake = 1; USART0PutChar(Wake); } /****************************************************/ /*(3)Exit ultra low power mode Since the serial communication module of TF Luna is not enabled when it is in the ultra-low power consumption mode, it cannot directly exit this mode. TF Luna can only respond to serial instructions within a short time sequence when it is awakened. Therefore, the user needs to continuously send the "disable" command of "ultra low power mode ID_ULTRA_LOW_POWER_MODE=Ox58" until receiving the response from TF Luna. Then the user sends the "save current settings ID_SAVE_SETTINGS=0x11" command to ensure that the state is saved. */ /****************************************************/ void TOF_LOW_POWER_MODE_OFF(Power_Type Power_Mode) { int i; TOF_Power = Power_Mode; LOW_POWER_MODE[3] = TOF_Power; for(i = 0;i < 3;i++) { Send_Data(LOW_POWER_MODE); delay_us(1); } Send_Data(SAVE_SETTINGS); }
tof.h
/****************************************************/ // MSP432P401R // laser ranging // Bilibili: Balala 1 energy // CSDN: quiet · no envy // E-mail:[email protected] // Created on: October 31, 2021 /****************************************************/ #ifndef __TOF_H #define __TOF_H #include <driverlib.h> #define Dist_L 2 #define Dist_H 3 #define Amp_L 4 #define Amp_H 5 #define Temp_L 6 #define Temp_H 7 #define Check_sum 8 typedef enum { Output_On = 0x01,//Enable output Output_Off = 0x00,//Close output }Output_Type;//Output switch typedef enum { Frame_Checksum_On = 0x01,//Enable checksum Frame_Checksum_Off = 0x00,//Turn off checksum }Checksum_Type;//Checksum switch typedef enum { Format_CM = 0x01,//9 byte CM output Format_PIK = 0x02, //PIK output Format_MM = 0x06, //9 byte MM output Format_BIT = 0x07, //With 32bit timestamp Format_ID0 = 0x06, //IDO output Format_CM0 = 0x09, //8-byte CM output Format_ID = 0x0A, //Output with device ID }Format_Type;//Output format typedef enum { Filter_bit0 = 0x01,//Turn on Kalman filter Filter_bit1 = 0x02,//Turn on median filtering Filter_bit = 0x03,//Turn on Kalman filter and median filter }Filter_Type; typedef enum { Low_Power_Mode_ON = 0x01,//Enter ultra low power mode Low_Power_Mode_OFF = 0x00,//Exit ultra low power mode }Power_Type; typedef enum { Dobule_Freq_Mode = 0x01,//Dual Mode Single_Freq_Mode = 0x00,//Single frequency mode }DEALIAS_Type; typedef enum { ID_Output_Format = 0x05,//Output formatting ID_Output_EN = 0x07,//Output switch setting ID_Frame_Checksum_EN = 0x08,//Checksum switch settings ID_DEALIAS_EN = 0x29,//Single and dual frequency mode setting ID_DIST_LIMIT = 0x3A,//Distance limit setting ID_ON_OFF_MODE = 0x3B,//Switching value output mode setting }CONFIG_Type; extern uint16_t Distance, Sign, Temp; extern uint8_t Freq;//output frequency extern uint8_t I2C_slave_addr;//I2C slave address extern uint8_t Dist_min_High,Dist_min_Low,Dist_max_High,Dist_max_Low;//Distance limit variable extern uint32_t timeout; void TOF_init(void); void Get_Distance(void); void Send_Data(uint8_t *COM_DATA); void TOF_LOW_POWER_MODE_ON(Power_Type Power_Mode); void Wake_Up_Get_Distense(void); void TOF_LOW_POWER_MODE_OFF(Power_Type Power_Mode); #endif
usart.c
void uart_init(uint32_t baudRate) { #ifdef EUSCI_A_UART_7_BIT_LEN //Firmware library v3_40_01_02 //Default SMCLK 48MHz bit rate 115200 const eUSCI_UART_ConfigV1 uartConfig = { EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 26, // BRDIV = 26 0, // UCxBRF = 0 111, // UCxBRS = 111 EUSCI_A_UART_NO_PARITY, // No Parity EUSCI_A_UART_LSB_FIRST, // MSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling EUSCI_A_UART_8_BIT_LEN // 8 bit data length }; eusci_calcBaudDividers((eUSCI_UART_ConfigV1 *)&uartConfig, baudRate); //Configure baud rate #else //Firmware library v3_21_00_05 //Default SMCLK 48MHz bit rate 115200 const eUSCI_UART_Config uartConfig = { EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 26, // BRDIV = 26 0, // UCxBRF = 0 111, // UCxBRS = 111 EUSCI_A_UART_NO_PARITY, // No Parity EUSCI_A_UART_LSB_FIRST, // MSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling }; eusci_calcBaudDividers((eUSCI_UART_Config *)&uartConfig, baudRate); //Configure baud rate #endif MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION); //Initialize serial port MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig); //Open serial port MAP_UART_enableModule(EUSCI_A0_BASE); /*Enable serial port related interrupt*/ UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); /*Open serial port interrupt*/ Interrupt_enableInterrupt(INT_EUSCIA0); } void EUSCIA0_IRQHandler(void) { // uint8_t rev0; uint32_t status = UART_getEnabledInterruptStatus(EUSCI_A0_BASE);//Interrupt receive flag if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) //Description received data { // Rev0 = uart_receivedata (eusci_a0_base); / / (UART0 - > DR); read the received data if(rxflag == 0) { rxbuf[rxcnt++] = UART_receiveData(EUSCI_A0_BASE);//(UART0 - > DR); read the received data if(rxcnt >= 2) { if(waitflag == 1) { if((rxbuf[0] == TOF_RES_FLAG) && (rxbuf[1] == TOF_RES_FLAG))//The serial port receives TOF data twice, both of which are 0x59 { waitflag = 2; } } else { if(rxcnt == Check_sum)//The serial port receives the last bit of TOF data { rxflag = 1; waitflag = 1; } } } else if(rxcnt >= 9) { rxcnt = 0; } } else { rxempty = UART_receiveData(EUSCI_A0_BASE);//(UART0 - > DR); read the received data } } }3, Output result display
The first line shows the distance data in CM, which can also be set as M and MM. The second line shows the signal strength. If the signal strength is lower than 100, the data is unreliable, and if it is greater than 65536, it is seriously exposed. Finally, the third line shows the radar temperature in Celsius.
4, Source code link