使用ATMEGA328P在LCD矩阵上显示文本

发布于 2025-01-27 19:46:32 字数 2512 浏览 3 评论 0原文

背景和目标

我正在使用超声波传感器(HC-SR04)和ATMEGA328P(Arduino)和三个级联的Max7219 LCD矩阵之间的SPI通信进行简单的AVR C项目。系统的目的是使用超声传感器检测和测量距离,并同时在LCD矩阵上显示适当的消息。

有效的是,

我可以执行两个组件的主要功能 分别 。我可以使用HC-SR04检测并测量距离,并且可以在LCD矩阵上显示文本并滚动文本。 HC-SR04反复测量每5ms的距离。

问题问题

当我想同时执行两个功能 时,问题就会上升。发生的事情是,文本消息是在LCD矩阵上反复显示的,但没有完整。我了解这是因为我使用超声传感器反复测量距离。我的猜测会中断,但是我不确定如何解决这个问题。

是否有一种方法可以在LCD上完全显示“ 最后测量的距离”,而仍在测量距离?

代码(主要部分):

// GLOBALS
volatile unsigned short echo_time;
volatile unsigned short distance;

// Text to display to LCD
char text[25] = "DEFAULT";

// Fire sensor
void fire_sensor()
{
    // Fire the trigger pin
    PORTD |= (1 << TRIG_PIN);
    
    // Wait for 10 microseconds in reference to the data sheet
    _delay_us(10);
    
    // Toggle the trigger pin to turn off
    PORTD &= ~(1 << TRIG_PIN);
}

// Measure distance
void measure_distance()
{   
    // Wait until echo pin is low and timer counter has changed
    while (echo_time == 0);
    
    // Calculate the distance in centimeters
    distance = echo_time/58;
    
    if (distance <= 60)
    {   
        strcpy(text,"VEHICLE DETECTED");
        PORTB = 0b00000001; // Turn DEBUG LED ON
        
    }
    else
    {
        strcpy(text,"DETECTED NOTHING");
        PORTB = 0b00000000; // Turn DEBUG LED OFF
    }
}

// *************************** MAIN *************************** //

int main(void)
{
    // Enable interrupts
    sei();
    
    // Initialise components
    EchoSetup();
    SPISetup();
    
    InitMatrix();
    InitBuffer();
    ClearMatrix();
    
    // Get length of text
    size_t length = strlen(text);
    
    /* Replace with your application code */
    while (1) 
    {
        fire_sensor();
        measure_distance();
        _delay_ms(5);
        
        // Display to LCD matrix character by character
        for (uint16_t i = 0; i < length; i++)
        {
            PushCharacter(text[i] - 32);
            PushBuffer(0x00);                       // Add empty column after character for letter spacing
        }
        
    }
}

// *************************** INTERRUPTS *************************** //

ISR(INT0_vect)
{
    // ECHO is high (signal has come back) stop counter
    if(PIND &(1 << PIND3)){
        
        // Reset the counter
        TCNT1 = 0;
    }
    else
    {
        // ECHO pin is low and the counter starts
        echo_time = TCNT1;
    }
}

Background and objective

I am working on a simple AVR C project with an ultrasonic sensor (HC-SR04) and SPI communication between the ATmega328P (Arduino) and three cascaded MAX7219 LCD matrix. The objective of the system is to detect and measure the distance using the ultrasonic sensor and display an appropriate message on the LCD matrix simultaneously.

What's working

I can perform the main functionality of both components separately. I can detect and measure distance with the HC-SR04 and I can display the text on the LCD matrix and scroll the text as well. The HC-SR04 repeatedly measures the distance roughly every 5ms.

Problem

The problem rises when I want to perform both functionalities simultaneously. What happens is that the text message is displayed repeatedly on the LCD matrix but not in full. I understand this is because I repeatedly measure the distance using the ultrasonic sensor. My guess would be interrupts, however I am not sure how to tackle this issue.

Is there a way of displaying the "last measured distance" fully on the LCD whilst still measuring distance?

The code (main parts):

// GLOBALS
volatile unsigned short echo_time;
volatile unsigned short distance;

// Text to display to LCD
char text[25] = "DEFAULT";

// Fire sensor
void fire_sensor()
{
    // Fire the trigger pin
    PORTD |= (1 << TRIG_PIN);
    
    // Wait for 10 microseconds in reference to the data sheet
    _delay_us(10);
    
    // Toggle the trigger pin to turn off
    PORTD &= ~(1 << TRIG_PIN);
}

// Measure distance
void measure_distance()
{   
    // Wait until echo pin is low and timer counter has changed
    while (echo_time == 0);
    
    // Calculate the distance in centimeters
    distance = echo_time/58;
    
    if (distance <= 60)
    {   
        strcpy(text,"VEHICLE DETECTED");
        PORTB = 0b00000001; // Turn DEBUG LED ON
        
    }
    else
    {
        strcpy(text,"DETECTED NOTHING");
        PORTB = 0b00000000; // Turn DEBUG LED OFF
    }
}

// *************************** MAIN *************************** //

int main(void)
{
    // Enable interrupts
    sei();
    
    // Initialise components
    EchoSetup();
    SPISetup();
    
    InitMatrix();
    InitBuffer();
    ClearMatrix();
    
    // Get length of text
    size_t length = strlen(text);
    
    /* Replace with your application code */
    while (1) 
    {
        fire_sensor();
        measure_distance();
        _delay_ms(5);
        
        // Display to LCD matrix character by character
        for (uint16_t i = 0; i < length; i++)
        {
            PushCharacter(text[i] - 32);
            PushBuffer(0x00);                       // Add empty column after character for letter spacing
        }
        
    }
}

// *************************** INTERRUPTS *************************** //

ISR(INT0_vect)
{
    // ECHO is high (signal has come back) stop counter
    if(PIND &(1 << PIND3)){
        
        // Reset the counter
        TCNT1 = 0;
    }
    else
    {
        // ECHO pin is low and the counter starts
        echo_time = TCNT1;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

温柔少女心 2025-02-03 19:46:32

我建议将MEATH_DISTANCE()非阻滞。

// Measure distance 
// (returns true if distance was process and text was updated)
bool process_distance()
{   
    if (echo_time == 0)
        return false;
    
    // Calculate the distance in centimeters
    distance = echo_time/58;
    
    if (distance <= 60)
    {   
        strcpy(text,"VEHICLE DETECTED");
        PORTB = 0b00000001; // Turn DEBUG LED ON
        
    }
    else
    {
        strcpy(text,"DETECTED NOTHING");
        PORTB = 0b00000000; // Turn DEBUG LED OFF
    }

    echo_time = 0;  // reset echo time
    return true;
}

在您的时循环中,您不再等待结果准备就绪,而是反复检查它是否已准备就绪并显示结果。

while (1) 
{
    bool refreshDisplay = false;
    fire_sensor();
    refreshDisplay = process_distance();
    _delay_ms(5);  // Why this delay?
    
    // Only refresh if necessary
    if (refreshDisplay)
        // Display to LCD matrix character by character
        for (uint16_t i = 0; i < length; i++)
        {
            PushCharacter(text[i] - 32);
            PushBuffer(0x00);                       // Add empty column after character for letter spacing
        }
    }
}

这仍然不是“干净的代码”,因为某些职责在功能之间松散耦合。但是改进这样的代码具有经验。

I would suggest to make measure_distance() non-blocking.

// Measure distance 
// (returns true if distance was process and text was updated)
bool process_distance()
{   
    if (echo_time == 0)
        return false;
    
    // Calculate the distance in centimeters
    distance = echo_time/58;
    
    if (distance <= 60)
    {   
        strcpy(text,"VEHICLE DETECTED");
        PORTB = 0b00000001; // Turn DEBUG LED ON
        
    }
    else
    {
        strcpy(text,"DETECTED NOTHING");
        PORTB = 0b00000000; // Turn DEBUG LED OFF
    }

    echo_time = 0;  // reset echo time
    return true;
}

In your while loop, you no longer wait for the result to be ready but repeatedly check if it "was" ready and display the result.

while (1) 
{
    bool refreshDisplay = false;
    fire_sensor();
    refreshDisplay = process_distance();
    _delay_ms(5);  // Why this delay?
    
    // Only refresh if necessary
    if (refreshDisplay)
        // Display to LCD matrix character by character
        for (uint16_t i = 0; i < length; i++)
        {
            PushCharacter(text[i] - 32);
            PushBuffer(0x00);                       // Add empty column after character for letter spacing
        }
    }
}

This is still not "clean code" because some responsibilities are loosely coupled between functions. But improving code like this comes with experience.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文