Những mẫu thiết kế nào tôi có thể sử dụng để xử lý cập nhật và hiển thị của người dùng?


7

Tôi đã sử dụng đủ các sản phẩm với bộ vi điều khiển nhúng và giao diện người dùng không phản hồi để biết rằng nó có thể tạo hoặc phá vỡ một sản phẩm. Ngay cả một chút chậm trễ hoặc độ trễ giữa các lần nhấn nút và cập nhật màn hình, hoặc các lần nhấn nút bị bỏ qua hoặc tính hai lần, có thể cực kỳ bực bội.

Những mẫu thiết kế nào có thể được sử dụng để đối phó với đầu vào của người dùng (từ các nút) và cập nhật màn hình mà không gây ra các vấn đề này?

Tôi hiện đang sử dụng loại mẫu sau (điều này được đơn giản hóa đến mức tối thiểu):

#include <Bounce.h>

#define GREEN_LED       6 // Pin for green LED

#define BUTTON_PIN      15 // Pin for button - uses external pull down so active high

#define DISPLAY_REFRESH_INT 100 // How many MS between display updates

Bounce button = Bounce(BUTTON_PIN, 5);

// To signal between the button read and the display update
bool ledState = false;

// Used to keep track of last display update
long displayUpdate = 0;

void setup()
{
    pinMode(GREEN_LED, OUTPUT);
    pinMode(BUTTON_PIN, INPUT);
}

void loop()
{
    // Read the button status
    if (button.update())
    {
        if (button.risingEdge())
        {
            ledState = !ledState;
        }
    }

    // Update the display periodically
    if (millis() - displayUpdate > DISPLAY_REFRESH_INT)
    {
        displayUpdate = millis();

        digitalWrite(GREEN_LED, ledState);
    }

}

tùy chọn khác là gì ở đó? Có bao giờ đáng sử dụng các ngắt thay đổi pin để đọc các nút (nếu chúng ta không xem xét thời lượng pin!).

Câu trả lời:


6

Câu trả lời phụ thuộc vào chính xác ý nghĩa của bản phác thảo để đáp ứng với sự tương tác của người dùng.

Ngắt bên ngoài
Nếu sự tương tác phụ thuộc vào phản ứng rất chính xác với cạnh tăng hoặc giảm của một sự kiện đầu vào (như trong ví dụ của bạn), thì có thể là một ngắt bên ngoài .

Điều này đặc biệt quan trọng nếu sự kiện đầu vào có thể ngắn hơn thời lượng của một cuộc gọi đến loop(). Nếu điều đó xảy ra, các nỗ lực liên tục để thăm dò ý kiến ​​đầu vào có thể hoàn toàn bỏ lỡ sự thay đổi trạng thái. Mặc dù khá hiếm khi một sự kiện đầu vào của người dùng lại ngắn như vậy, trừ khi loop()khá chậm để thực thi.

Phần cứng bên ngoài để nhận trợ giúp, mặc dù, bằng cách có một đầu vào chốt cho đến khi nó được đọc và thiết lập lại bởi vi điều khiển.

Cải thiện tần suất bỏ phiếu
Ngắt bên ngoài thường không thể thực hiện được (ví dụ: vì chip chỉ hỗ trợ số lượng hạn chế) hoặc đơn giản là chúng quá mức / không cần thiết cho một ứng dụng nhất định.

Trong những trường hợp đó, vẫn có thể cải thiện độ chính xác về thời gian khi sử dụng bỏ phiếu. Một tùy chọn là tách tất cả các phần khác nhau của vòng lặp chính thành các chức năng riêng biệt. Trên mỗi lần lặp lại liên tiếp của loop()nó, nó sẽ gọi hàm tiếp theo, và sau đó ngắt vòng thành đầu tiên. Ở giữa mỗi chức năng đó, nó có thể thăm dò nút. Đây là một ví dụ đơn giản:

unsigned int g_section = 0;

void setup() { }

void pollButton()
{
    //...
}

void runSection0()
{
    //...
}

void runSection1()
{
    //...
}

void runSection2()
{
    //...
}

void loop()
{
    // Poll the button on every pass:
    pollButton();

    // Execute the next section of the main code:
    switch (g_section)
    {
    case 0: runSection0(); break;
    case 1: runSection1(); break;
    case 2: runSection2(); break;
    }

    // On the next iteration, run the next section:
    if (++g_section > 2) g_section = 0;
}

Một vấn đề quan trọng với cách tiếp cận này là rất khó để làm cho mỗi runSectionX()chức năng đó có cùng thời gian thực hiện. Điều đó có thể dẫn đến việc nút được bỏ phiếu không nhất quán từ lần lặp này đến lần lặp tiếp theo. Nếu nó đủ nhanh, thì đó không phải là vấn đề quá lớn.

Không may cập
nhật màn hình Cập nhật màn hình hiển thị thường khá chậm, so với nhiều thao tác khác. Điều đó có nghĩa là bạn cần phải khá cẩn thận nơi bạn làm điều đó. Bên trong một Dịch vụ ngắt thường xuyên sẽ không phù hợp, vì điều đó có thể giới thiệu các vấn đề thời gian khác trong bản phác thảo của bạn.

Thực tế, bạn phải làm điều đó trong vòng lặp chính. Nếu bạn hoàn toàn phải chạy nó một cách nhanh chóng, thì nó có thể được bao gồm trong ví dụ bỏ phiếu nhanh hơn tôi đã đưa ra ở trên - tức là cập nhật màn hình trên mỗi lần lặp, giống như bỏ phiếu. Bạn phải cẩn thận để tránh cập nhật một phần mặc dù.


Đây là một câu trả lời tuyệt vời. Chính xác là loại câu trả lời mà trang web cần.
Cyberg Ribbon

2

Để kiểm soát chương trình, tôi đã tạo một cái gì đó của khung xử lý menu cho một trong các dự án của mình và chia sẻ nguồn trên Github . Lưu ý rằng đây là cho chipKIT nhưng mã xử lý menu là chung chung. Sau khi xây dựng cấu trúc if-if-if và if khổng lồ thứ 3 hoặc thứ 4 của tôi, tôi quyết định phải có một cách tốt hơn. Tín dụng cho nguồn của các cấu trúc menu tĩnh.

Tôi chỉ sử dụng vòng lặp chính để kiểm tra nút.

Tôi muốn nói bước đầu tiên là có được một màn hình LCD. Nếu bạn dùng thử, bạn sẽ không bao giờ quay lại ... Tôi đặc biệt yêu thích Adaf nhung 1.8 "với cần điều khiển. Arduinos đủ chậm để tôi không thể nhớ lại việc quan tâm đến việc gỡ bỏ đầu vào của người dùng.


Tôi thích cách bạn đã làm điều đó - nó dễ hiểu, sạch sẽ và kích thước rất nhỏ. Tôi đã xem xét việc sử dụng một thư viện (MenuBackend) nhưng thật khó hiểu cho các lập trình viên mới (sử dụng các cuộc gọi lại) và không thể ngồi trong PROGMEM.
Cyberg Ribbon

Tôi thấy việc gỡ lỗi thường không bắt buộc, nhưng một số thiết bị chuyển mạch dường như ồn hơn nhiều so với các công tắc khác. Các công tắc xúc giác PCB được gắn thẳng đứng, cạnh có vẻ tệ nhất cho đến nay, có thể vì thay vì nhấn, người dùng thường tận dụng các chuyển tiếp này. Tranh luận dễ dàng đến mức tôi gần như luôn luôn làm điều đó ngay bây giờ.
Cyberg Ribbon

Xin lỗi cho tất cả các câu hỏi - tại sao một màn hình LCD? Tôi hiện đang làm việc với màn hình LCD 128x64 có rất nhiều lợi ích (chủ yếu là lớn về mặt vật lý). Cũng rẻ.
Cyberg Ribbon

1
@Cyberg Ribbon ah, không thấy bất kỳ đề cập đến màn hình. Thứ tôi thích là một chiếc khiên làm sẵn, đủ rẻ và bạn có thể làm mọi thứ với màu sắc. Đây là một báo cáo xây dựng của dự án gần đây nhất của tôi: forum.adafbean.com/ Từ
Chris K

1

Bạn có thể ngắt thay vì bỏ phiếu nếu bạn có thể hủy các nút trong phần cứng. Nếu không, bạn sẽ bị gián đoạn nhiều hơn so với việc nhấn nút và vẫn phải giải phóng chúng trong phần mềm.

Nhưng đối với câu hỏi chính, một bộ sưu tập các máy trạng thái có thể rất hữu ích, ít nhất là đối với ui và cung cấp cho bạn hầu hết các lợi ích của đa tác vụ mà không cần hạt nhân am / t. Thật không may, trong các thiết bị giới hạn RAM, không may, bởi vì

Kỹ thuật này có thể đặc biệt hữu ích trên các thiết bị nhỏ này nhưng đối với các giới hạn nghiêm trọng về RAM, khiến việc phân chia dữ liệu máy trạng thái của bạn giữa flash và RAM trở nên khó khăn.


0

Vì Chris K tôi cũng đã triển khai một thư viện menu tĩnh với nhiều tùy chọn đầu ra như Nối tiếp, LCD, TFT, v.v. Tôi đã bắt đầu nó để giúp đỡ trong một dự án bạn bè và tôi cũng đang chia sẻ nó với nguồn mở những người có vấn đề tương tự, hy vọng bạn có thể tìm thấy nó hữu ích.

https://github.com/neu-rah/ArduinoMothy

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.