c - 用于自动制动系统的激光雷达传感器的速度测量

标签 c distance sensors atmega lidar

对于一个学校项目,我一直在研究一个系统,该系统会在出现危险时自动刹车。只是要求比仅使用 ping 传感器并检测固定距离更严格(安全)。我还将实现传入对象的速度。

在互联网上,我发现了这个很棒的 100Hz sample 激光雷达模块,它非常便宜。它使用带有 2 个 header 帧 (0x59) 的 UART,然后是一个 dataLowbyte 和一个 dataHighbyte。这是 datasheet for the module .

所以我开始在 atmega328P (Arduino) 上输入咖啡并输出代码(C 语言)。

正如您在此处看到的,我已经设置了读取传感器和处理数据的代码。问题是它会返回奇怪的读数。就像当我远离时当我靠近时的距离差异,即使我说不是。有没有人有使用这个模块的经验?或者我可能误读了数据表的某些内容。

//Includes
//============================================================================================//
#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>
//============================================================================================//


//Defines
//============================================================================================//
#define F_CPU 16000000                                          //CPU frequency
#define Baudrate 115200                                         //UART Baudrate
#define UBRR_VALUE (((F_CPU / (Baudrate * 8))) - 1)             //UART Baudrate set in Arduino
// #define SafetyRating 8
// #define sampleTime 0x65                                          //Time between 2 samples in 10^-4. This value comes from testing (its 1,01ms)
//============================================================================================//


//Enums
//============================================================================================//
enum {Safe, Warning, Danger}State;                              //Possible States
//============================================================================================//


//Global variables
//============================================================================================//
uint8_t distanceL;                                              //Distance (low value) data taken from the UART buffer coming from Lidar
uint8_t distanceH;                                              //Distance (high value) data taken from the UART buffer coming from Lidar
uint16_t Distance;                                              //Distance combined
uint8_t frameByteCount = 0;                                     //To count which byte in the frame is current
uint16_t Speed;                                                 //Speed variable
//volatile uint8_t DangerLevel;                                 //Danger indicator


//Function prototypes
//============================================================================================//
void calcSpeed(uint16_t Measurement);                       //Function to calculate the speed out of distance readings
void UART_Transmit(uint8_t data);                               //Funtion to send data via uart
//============================================================================================//


//Interrupts
//============================================================================================//
/*UART receive complete interrupt*/
ISR(USART_RX_vect)                                              //Data taken from the UART buffer
{
    uint8_t sample;                                             

    sample = UDR0;                                              //Read a sample from the receiver buffer

    if(frameByteCount == 3)                                     //If its the 4th byte of the frame
    {
        frameByteCount = 0;                                     //Reset the counter
        distanceH = sample;                                     //Read the distance data high byte
        Distance = (8 << distanceH);                            //Combine the data low and data high
        Distance |= distanceL;

        calcSpeed(Distance);                                //Send the data to laptop for debugging purposes

    }

    if(frameByteCount == 2)                                     //If its the 3rd byte in the frame read the distance data low byte
    {
        distanceL = sample;
        frameByteCount++;                                       //Increment the counter
    }

    if (sample == 0x59)                                         //If a sample is a header increment a counter
    {
        frameByteCount++;
    }
    else if (frameByteCount != 2 && frameByteCount != 3)        //If its not a header or distance data byte reset counter
    {
        frameByteCount = 0;
    }   
}
//============================================================================================//

//Timers and Counters
//============================================================================================//
/*Timer0 Counter, this decreases the danger level periodically so a really slow approach will not keep incrementing the danger level*/
ISR(TIMER0_OVF_vect)                
{
//  if (DangerLevel > 0)
//  {
//      DangerLevel--;
//  }
}
//============================================================================================//

//Main
//============================================================================================//
int main(void)
{
    DDRB    |=      0x02;                                       //For debugging purposes LED pin PB1 (pin 9) as output

    UBRR0H = (UBRR_VALUE >> 8);                                 //Setting the Baudrate register high value
    UBRR0L =  UBRR_VALUE;                                       //Setting the Baudrate register low value
    UCSR0A |= (1<<U2X0);                                        //Setting the data sample to double speed to make Baudrate error less
    UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00);                        //Initializing UART, setting frame to 8 data bits
    UCSR0B |= (1<<RXCIE0) | (1<<TXEN0) | (1<<RXEN0);            //Setting receiver interrupt enable, transmitter enable and receiver enable... Transmitter for debugging purposes

    TCCR0A = 0x00;                                              //Timer0 Setup
    TCCR0B |= 0x05;                                             //Timer0 clock prescaler to 1024
    TIMSK0 |= 0x01;                                             //Timer0 overflow interrupt enable

    sei();                                                      //Set interrupts

    State = Safe;                                               //Set state to safe

    while (1)
    {
        //checkState(DangerLevel);
    }
}
//============================================================================================//

//Functions
//============================================================================================//
/*Calculate the danger level out of distance readings*/
void calcSpeed(uint16_t Measurement)
{
    static uint8_t samplenumber = 0;                                //Sample tracker
    static uint16_t value0 = 0;                                         //First sample
    static uint16_t value1 = 0;                                         //Second sample


    switch(samplenumber)                                            //To store the measurements alternately
    {
        case 0:
            value0 = Measurement;                                   //Store first measurement
            samplenumber = 1;                                       //So next measurement goes to a different variable
        break;
        case 1:
            value1 = Measurement;                                   //Store 2nd measurement
            samplenumber = 0;                                       //So next measurement goes to a different variable
        break;
        default:
        break;
    }

    if (samplenumber == 0 && value1 < value0)                       //When value0 is first and value1 is second and the object is closing in
    {
        Speed = value0 - value1;
    }
    else if (samplenumber == 1 && value0 < value1)                  //When value1 is first and value0 is second and the object is closing in
    {
        Speed = value1 - value0;
    }
    else
    {
        Speed = 0;
    }
    UART_Transmit(Speed);       //I think sending an uint16_t over uint8_t uart is possible because 'Speed' is never greater than 255 when i'm testing it
}

/*Send data over UART when buffer is empty*/
void UART_Transmit(uint8_t data)
{
    /* Wait for empty transmit buffer */
    while ( !( UCSR0A & (1<<UDRE0)) )
    ;
    /* Put data into buffer, sends the data */
    UDR0 = data;
}
//============================================================================================//

最佳答案

我找到了!

Distance = (8 << distanceH);                            //Combine the data low and data high
Distance |= distanceL;

应该是:

Distance = (distanceH << 8);                            //Combine the data low and data high
Distance |= distanceL;

关于c - 用于自动制动系统的激光雷达传感器的速度测量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47438854/

相关文章:

c - 检查字符时使用哈希表或数组作为位图

c - 如何在删除第一个索引中的元素后通过向左移动元素来减小数组的大小?

python - Scipy python 中的最高距离

accelerometer - IMU MPU9250 数据表中的满量程范围表示什么,哪个更好用?

java - 使用磁力计的简单 compass - Android (Java)

Android - SensorManager getOrientation 的奇怪行为

c - fcntl F_GETLK 始终返回 F_UNLCK

C - 使用指针的数组总和

java - 八个随机整数的数组,其中每个整数与数组中的所有其他整数至少相差 15?

postgresql - 使用 PostgreSQL 查询计算行进距离