开/关组合开关C++ arduino代码

问题描述 投票:0回答:1

所以我正在开发一个新项目,其中有 5 个开/关引导开关和一个普通按钮。我想让它在液晶显示屏上显示 5 位数字代码,您需要按正确的顺序打开开关(例如 1,3,4,2,5),然后按下按钮,如果这是正确的,将会发生一些事情,但如果是错误的,液晶显示屏会告诉您,您需要重试。所以你打开1号开关,它会一直亮着,直到你按下按钮,如果你只打开4个开关,就会说密码错误。当您按下按钮时,您需要关闭所有开关才能重试。

我试图为此编写一个程序,但我们已经为此绞尽脑汁三天了。我是一名初级程序员。我认为比我聪明的人可能可以在 15 分钟内写出它,所以我想知道是否有人可以帮助我。

Tnx

c++ arduino combinations
1个回答
0
投票

我已经有一段时间没有对arduinos进行编程了。当我这样做时,我只使用 C 编写了一些非常小的项目,而不是 C++(当时我不知道),所以我不确定是否有对我使用的算法的支持。如果没有,您可能必须自己为您的用例实现它们。您必须自己完成任何特定于硬件的部分,例如配置输入/输出引脚并将变量映射到它们等等。

我在我的 PC 上想出了一个解决方案,在 Windows 上使用纯 C++。作为开关的输入,我只使用了 Visual Studio 中的监视窗口,并使用正在运行的调试器覆盖了这些值。这意味着我没有任何反跳(正如 Gabriel Staples 在您的问题评论中提到的那样),这对您来说很重要。您可以使用一些计时器并忽略输入的更改,例如更改后的下一个 50 毫秒(说实话,我不知道这是否是一个现实的方法或持续时间)。

我也不知道你如何与液晶屏通信,因此我只是在代码中使用

std::cout
来模拟写入。

我的代码可能无法在所有情况下工作或完全按照您的预期工作,因此只需将其用作指导/灵感,但请不要完全依赖它。

#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>

constexpr int unspecifiedItem{ -1 };
constexpr std::size_t numberOfSwitches{ 5 };
constexpr std::array<int, numberOfSwitches> correctPasscodePattern{ 0, 2, 3, 1, 4 };    // 0 - 4, because of 0 indexed array DI_switches
enum class Step {
    WaitForSubmission, HandleSubmission, WaitForReset
};

// map them somehow to the hardware (DI for digital input from the hardware, either true or false)
std::array<bool, numberOfSwitches> DI_switches;
bool DI_submitPasscode;

Step step{ Step::WaitForSubmission };
std::array<bool, numberOfSwitches> previousSwichesStates{};
std::array<int, numberOfSwitches> enteredPattern{};

void setup() {
    // set wanted pins for input
    // map DI's to wanted pins

    // initialize the entered pattern to some "invalid" pattern
    std::fill(enteredPattern.begin(), enteredPattern.end(), unspecifiedItem);
}

void loop() {
    switch (step)
    {
    case Step::WaitForSubmission:
    {
        if (DI_submitPasscode) {
            step = Step::HandleSubmission;
        }

        // search for the first difference between the current DI's and the one from the previous check
        const auto mismatchResult = std::mismatch(DI_switches.begin(), DI_switches.end(), previousSwichesStates.begin(), previousSwichesStates.end());

        if (mismatchResult.first == DI_switches.end()) {
            // both arrays were the same, therefore the user didnt change any switches since the last check
            break;
        }
        // changedSwitch has the index of the first difference in the arrays
        // decide if you want to check if multiple differences occured since last check
        // (if loop() gets executed 100 times a second, you would need to change two switches in 10ms)
        const std::ptrdiff_t changedSwitch = std::distance(DI_switches.begin(), mismatchResult.first);

        // seach for the first item in enteredPattern with value -1
        auto firstUnspecifiedItem = std::find(enteredPattern.begin(), enteredPattern.end(), unspecifiedItem);
        if (firstUnspecifiedItem == enteredPattern.end()) {
            // enteredPattern is already full, maybe go to Step::HandleSubmisssion or print error
            break;
        }

        *firstUnspecifiedItem = static_cast<int>(changedSwitch);
        break;
    }
    case Step::HandleSubmission:
        // if not all switches are on, or if the switches were entered in the wrong order, 
        // the user should keep entering (but first reset all switches)
        if (!std::all_of(DI_switches.begin(), DI_switches.end(), std::identity{})
            || enteredPattern != correctPasscodePattern) {
            std::cout << "Wrong password!" << std::endl;
            step = Step::WaitForReset;
            break;
        }

        // you could have an additional step for what to do when the user enters the correct password
        std::cout << "Correct password!" << std::endl;
        break;
    case Step::WaitForReset:
        // if all switches are off again, reset the entered pattern and get input again
        if (std::none_of(DI_switches.begin(), DI_switches.end(), std::identity{})) {
            std::fill(enteredPattern.begin(), enteredPattern.end(), unspecifiedItem);
            step = Step::WaitForSubmission;
        }
        break;
    default:
        break;
    }

    previousSwichesStates = DI_switches;
}

int main() {

    setup();
    while (true) {
        loop();
    }

    return 0;
}

为了将来,请记住,SO 不是免费的代码编写服务,您应该发布一个“最小的、可重现的示例”作为问题的一部分,以便人们知道您已经做了什么以及哪里出了问题。我主要这样做,因为我只是想亲眼看看我将如何实现这样的事情。

我是一名初级程序员。

我不知道你对C++了解多少,比如stl算法或指针/迭代器。代码中的大多数术语应该是不言自明的,注释应该有助于遵循我的思维过程,但是如果您遇到不理解的内容,请随时在 cppreference.com 上查找或发表评论。

© www.soinside.com 2019 - 2024. All rights reserved.