所以我正在开发一个新项目,其中有 5 个开/关引导开关和一个普通按钮。我想让它在液晶显示屏上显示 5 位数字代码,您需要按正确的顺序打开开关(例如 1,3,4,2,5),然后按下按钮,如果这是正确的,将会发生一些事情,但如果是错误的,液晶显示屏会告诉您,您需要重试。所以你打开1号开关,它会一直亮着,直到你按下按钮,如果你只打开4个开关,就会说密码错误。当您按下按钮时,您需要关闭所有开关才能重试。
我试图为此编写一个程序,但我们已经为此绞尽脑汁三天了。我是一名初级程序员。我认为比我聪明的人可能可以在 15 分钟内写出它,所以我想知道是否有人可以帮助我。
Tnx
我已经有一段时间没有对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 上查找或发表评论。