我没有长时间编程,我只想通过Arduino UNO电路板扩展电子工程。
我已经开始了一个基于Grathio的Steve Hoefer的Secret Knock Detecting Door Lock的新项目,我想实施以下内容:
(http://grathio.com/2009/11/secret_knock_detecting_door_lock/) (http://grathio.com/assets/secret_knock_detector.pde)
如果全局值等于0且有效爆震模式为真,则使用毫秒闪烁黄色LED 4次而不是延迟,以便它仍然可以“监听”。
如果在6秒内没有听到另一个有效的爆震模式,它将超时并将全局重置为0,以便它可以确认初始的真实模式并闪烁黄色LED。
如果在6秒内听到另一个有效的爆震模式,则递增一个计数器。
如果计数器等于1,则等待另一个有效的爆震模式,如果在6秒内为真,则再次递增计数器,不要闪烁黄色LED。
否则,超时并重置所有值。
依此类推,直到计数器大于或等于4触发主LED阵列。
一旦获得4次成功敲门,我希望它能触发我建造的主LED阵列。
该项目的灵感来自乘客飞机上使用的测试面板。我已经看过很多了,并认为这是一个开始学习时机的好地方。
有一些问题,因为我不想每次都重置millis()并且我在敲击检测脚本中使用按钮而不是布尔值,所以我不会迷失在代码中。
我知道这不会在50秒后响应并且这是初学者的错误,但证明了如果我按下按钮我会得到什么。在第一个digitalRead HIGH或true布尔值之后,下面的代码也没有超时(我正在努力解决这个问题)。
int inPin = 2; // input pin switch
int outPin = 3; // output pin LED
long currentTime = 0; // counter
long nextTime = 0; // counter
long lastTime = 0; // counter
int patternCounter = 0; // build up
int globalValue = 0; // lock out
int breakIn = 0; // waste of time?
void setup()
{
pinMode(inPin, INPUT);
pinMode(outPin, OUTPUT);
Serial.begin(9600);
Serial.println("GO");
}
void loop(){
// boolean true, switch just for testing
if (digitalRead(inPin)==HIGH&&globalValue==0&&breakIn==0) {
Serial.println("CLEARED 1st");
delay (500); // flood protection
globalValue++;
breakIn++;
if (globalValue>0&&breakIn>0){
currentTime = millis(); // start a 'new' counter and 'listen'
if (currentTime<6000) { // less than
if (digitalRead(inPin)==HIGH) { // and true
Serial.println("CLEARED 2nd"); // cleared the stage
delay (500); // flood protection
patternCounter++;
} // if counter less
} // if true or high
if (currentTime>6000) {
Serial.println("TIMEOUT waiting 2nd"); // timed out
globalValue = 0;
patternCounter = 0;
breakIn = 0;
} // if more than
} // global master
}
// 3rd attempt
if (globalValue==1&&patternCounter==1){ // third round
nextTime = millis(); // start a 'new' counter and 'listen'
if (nextTime<6000) { // less than
if (digitalRead(inPin)==HIGH) { // and true
Serial.println("CLEARED 3rd");
delay (500); // flood protection
patternCounter++;
} // if counter less
} // if true or high
if (nextTime>6000) {
Serial.println("TIMEOUT waiting 3rd"); // timed out
globalValue = 0;
patternCounter = 0;
} // if more than
} // global master
// 4th attempt and latch
if (globalValue==1&&patternCounter==2){ // last round
lastTime = millis(); // start a 'new' counter and 'listen'
if (lastTime<6000) { // less than
if (digitalRead(inPin)==HIGH) { // and true
digitalWrite(outPin, HIGH); // LED on
Serial.println("CLEARED 4th ARRAY"); // cleared the stage
delay(500); // flood protection
} // true or high
} // counter
if (lastTime>6000) {
Serial.println("TIMEOUT waiting 4th"); // timed out
globalValue = 0;
patternCounter = 0;
} // if more than
} // global and alarm
} // loop end
这是当前的草图,我理解我使用的计数器几乎没有意义。
非常感谢任何帮助!
答案 0 :(得分:0)
这需要大量工作,所以我可能无法理解你的问题,但下面的代码有点突出:
currentTime = millis(); // start a 'new' counter and 'listen'
if (currentTime<6000) { // less than
.....
}
你明白没有&#34;重置&#34;是millis()
可能的,这只是一个函数,它返回自程序启动以来的毫秒数?只要程序运行,它就会继续增加(直到它翻滚但这是一个单独的问题)。所以在上面的代码&#39; currentTime&#39;只会是&lt; 6000非常,非常短暂(6秒)然后再也没有(除了翻转条件,毫秒重置)。
因此,millis()
用于跟踪时间的典型方式是将setup
中的当前值存储到变量中,并将超时期限值添加到其中:
// timeoutAmount is defined at head of program. Let's say it is 6000 (6 seconds)
nextUpdate = millis() + timeoutAmount;
然后在loop
你可以做检查:
if (millis() >= nextUpdate){
nextUpdate = millis() + timeoutAmount; // set up the next timeout period
// do whatever you want to do
}
使用delay()
时也要小心 - 它很容易用于流量控制,但对于任何有多个事情的程序,都会导致混乱和难以解决的问题。
哦 - 有更复杂的方法可以使用芯片上的内置定时器来触发中断,但最好先把事情挂起来。
答案 1 :(得分:0)
在玩完你的帮助后,我想出了以下草图。
草图几乎可以完成我想要的一切......
当按下第1,第2(inCount = 1)或第3(inCount = 2)按钮后超时(T / O)时,我希望它能够恢复到开始而不必再次按下它循环triggerFlash两次。
或者在超时内实施另一个'等待和聆听'将其移动到第二个(inCount = 1)e.t.c.但我认为这可能会导致问题。
我知道闪光灯内有延迟,但会改为毫米(),我只是试图获得基本功能和理解。
const int switchPin = 2; //输入引脚的编号
const int BswitchPin = 4; //输入引脚的编号
const int outPin = 3;
const int thePin = 5;
long startTime; // the value returned from millis when the switch is pressed
long escapeTime; // the value returned from millis when in time out
long duration; // variable to store the duration
int inCount = 0;
int dupe = 0;
void setup()
{
pinMode(switchPin, INPUT);
pinMode(outPin, OUTPUT);
pinMode(thePin, OUTPUT);
digitalWrite(switchPin, HIGH); // turn on pull-up resistor
Serial.begin(9600);
Serial.println("Go");
digitalWrite(outPin, HIGH);
}
void loop()
{
if(inCount==0&&digitalRead(switchPin) == LOW)
{
// here if the switch is pressed
startTime = millis();
while(inCount==0&&digitalRead(switchPin) == LOW)
; // wait while the switch is still pressed
long duration = millis() - startTime;
if (duration<4000) {
Serial.println("1");
triggerFlash();
inCount++;
}
} // master 1
if (inCount>0&&inCount<4&&digitalRead(switchPin) == LOW)
{
// here if the switch is pressed
startTime = millis();
while(inCount>0&&inCount<4&&digitalRead(switchPin) == LOW)
; // wait while the switch is still pressed
long duration = millis() - startTime;
delay(500); // flood protection
if (duration>4000) { // script an escape here - formerly if (while will loop the condition)
Serial.println("T/O");
triggerFlash();
inCount = 0;
}
if (duration<4000) {
dupe = inCount + 1;
Serial.println(dupe);
inCount++;
}
}
if (inCount>=4) {
digitalWrite(thePin, HIGH);
}
} // loop
void triggerFlash() {
int i = 0;
for (i=0; i < 8; i++){
digitalWrite(outPin, LOW);
delay(100);
digitalWrite(outPin, HIGH);
delay(100);
}
}
非常感谢任何想法! (用改进的计数编辑)
答案 2 :(得分:0)
上面的代码实际上是错误的。一段时间后,请小心使用millis()。它只是长型。因此,如果millis + timeout接近max(long)并且millis()将翻转并从零开始计数,则即使实际发生超时,millis()&gt; = nextupdate也将为false。
正确的方法是:
unsigned long start = millis();
unsigned long timeout = MY_TIMEOUT_HERE;
...
//check if timeout occured
unisgned long now = millis();
unsigned long elapsed = now - start;
if(elapsed > timeout)
//do whatever you need to do when timeout occurs