我正在研究arduino,我在loop()中有两种模式,在while循环中是mode1,在while循环中是第二种模式,它们有条件可以满足,我在它们之间使用按钮来切换它们当前执行,更改标志以强制程序更改为第二模式,并且出于某种原因而不是打破当前循环(因为不再符合conditoins)以更改为另一个它只是没有响应
或自动更改>停止响应
#define modeSwitch 2
boolean manual;
boolean automatic;
String sOld;
boolean flagPrint = false;
volatile int modeSwitchValue;
String receivedData = "";
String invitation = "Welcome to Morse Code Encoder!\nPlease choose a mode: Write 'automatic' for an automatic mode or 'manual' or manual code.\n";
void setup() {
pinMode(modeSwitch, INPUT);
attachInterrupt(0, changeMode, RISING);
manual = false;
automatic = false;
volatile int modeSwitchValue = 5;
Serial.begin(9600);
Serial.println(invitation);
}
void loop() {
if (Serial.available() > 0) {
receivedData = Serial.readStringUntil('\n');
if (receivedData == "manual" ) {
manual = true;
automatic = false;
modeSwitchValue = 0;
}
if ( receivedData == "automatic") {
automatic = true;
manual = false;
modeSwitchValue = 1;
}
while ((manual == true) && (modeSwitchValue == 0) ) {
String s = "Manual mode:";
while (checkPrint(s) == true) {
Serial.println(s);
}
automatic = false;
}
while ((automatic == true) && (modeSwitchValue == 1)) {
String s = "Automatic mode:";
while (checkPrint(s) == true) {
Serial.println(s);
}
manual = false;
}
}
}
void changeMode() {
if ( modeSwitchValue == 0) {
modeSwitchValue = 1;
automatic = true;
manual = false;
}
if ( modeSwitchValue == 1) {
modeSwitchValue = 0;
manual = true;
automatic = false;
}
}
我删除了checkPrint()函数,因为它只能确保msgs被打印一次因此我认为这不是必不可少的
我认为在执行自动代码时,我按下按钮并中断,更改模式变量然后返回到发生中断的程序中的相同位置。然后软件注意到自动模式的循环条件不再满足,因此它会跳转到循环()并找到自满足条件后执行手动模式的循环。我错了吗?或者我错过了什么?
答案 0 :(得分:0)
你正在混淆任务" ="和比较" =="在你的changeMode()函数中。以下是该功能的更正版本。
fullText
您还应该意识到机械按钮可以有触点反弹。由于您使用中断来检测按钮状态的变化,因此可能会出现不稳定的行为。通常,最好轮询按钮状态并应用大约20ms的去抖时间延迟。
您还没有分享按钮的连线方式。由于您检测到上升沿,我认为按下按钮是为了在按下时将引脚拉高。如果您使用单刀单通按钮,则需要一个下拉电阻接地,否则中断引脚将浮动。
通过在输入引脚和地之间连接一个简单的按钮,可以避免所需的上拉或下拉电阻。然后将初始化代码更改为
var fullTextFunctions = [];
function setText(text, lang, full) {
setTimeout(function () { $('#loading').fadeOut('fast'); }, 300);
var mylang = '<?= $_SESSION['lang']; ?>';
if (mylang != 'en' && lang == 'en')
var AppendText = '<span class="db f09 grey mt10"><?= __('TEXT_ONLY_ENGLISH'); ?></span>';
console.log(lang);
if (full) {
$('#text').html('<?= __('EMPTY'); ?>');
setTimeout(function () { $('#text').fadeIn('fast'); }, 500);
} else if (text) {
// Full Text
fullTextFunctions.push(function fullText() {
console.log('yes');
setText(text, lang, 1);
})
text = text.length > length ? text.substring(0, length - 3) +
'... <a class="cp" onclick="fullTextFunctions[' + (fullTextFunctions.length - 1) + ']()"><?= __('MORE') ?></a>' : text;
$('#text').html(text).append(AppendText);
setTimeout(function () { $('#text').fadeIn('fast'); }, 500);
}
};
function releaseFullTextFunction(index) {
fullTextFunctions[index] = null;
}
然后,您将需要在下降沿触发中断。
我希望这会有所帮助。
答案 1 :(得分:0)
如果您确实要将ISR附加到按钮信号的RISING边缘,则应忽略多个触发器。至少2毫秒,但为什么不忽略所有不切实际的东西(例如100毫秒)
当你切换两个状态时,我会提出一个布尔变量istate
。
volatile bool istate; // the state maintained in the ISR changeMode
void changeMode() {
static unsigned long lastime;
if (millis() - lastime > 100) {
lastime = millis();
istate = ! istate;
}
}
如果需要,可以从主代码中的易失性ISR变量构建所有其他冗余内容(自动,手动)。
在我的解释中,名称buttonState
是错误的。并且变量不必要。
您知道数据类型枚举吗?
enum {MANUAL, AUTO} mode;
if (istate) mode = AUTO;
else mode = MANUAL;
可能对你的目的很好。