打破 While 循环 C++

Breaking a While loop C++

我有一个简短的问题,我认为更有经验的固件开发人员能够帮助我解决这个问题。所以我使用这段代码的主要目标是:

  1. 运行 一个循环(检测)将 "listen" 发生某事,然后在达到该阈值后增加变量(在本例中为 voltscount)。一旦在指定时间内两次达到 voltscount,采样循环内的第一个 while 循环将更仔细地监听(通过 FFT)。

  2. 当检测循环中的阈值在特定时间段内(本例中为 3 秒)未达到时,我想跳出 while 循环(停止使用 FFT 侦听) .

数字 1 已实现,但我在数字 2 上遇到了问题。代码似乎保留在采样内的第一个 while 循环中(串行 window 一直显示 FFT 值而不是 0,1或 2 -voltscount 值)在该电压阈值保持低于 4.8 的 3 秒之后。

我没有包括我的无效设置和所有爵士乐,让我知道是否需要回答我的问题。

void loop(){
  detect();
  sampling();

}
void detect(){
   unsigned long startMillis= millis();  // Start of sample window

   unsigned int peakToPeak = 0;   // peak-to-peak level

   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;

   // collect data for 50 mS
   while (millis() - startMillis < sampleWindow)
   {
      sample = analogRead(0);
      if (sample < 1024)  // toss out spurious readings
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save just the min levels
         }
      }
   }
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   volts = (peakToPeak * 5.0) / 1024;  // convert to volts
 Serial.println(voltscount);
}

void sampling(){
unsigned long currentMillis = millis();

if(volts >=4.8){
  voltscount++;

  previousMillis = millis();
}
while(voltscount >= 2){
    /////SAMPLING
    for(int i=0; i<samples; i++)
    {
        microseconds = micros();    /* Overflows after around 70 minutes! */
        vReal[i] = analogRead(0);
        vImag[i] = 0;
        while(micros() < (microseconds + sampling_period_us)){
        }
    }
  double x;
  double v;
  FFT.MajorPeak(vReal, samples, samplingFrequency, &x, &v);
  Serial.print(x, 0);
  Serial.print(", ");
  Serial.println(v, 0);
  delay(10); /* Repeat after delay */ 
/* 
// 3 tests for smoke detector chirps and code to light up the LEDs

    if (x > 4000 and x < 4900 and v > 80) {
        digitalWrite(blueLEDpin, HIGH);
        digitalWrite(uvLEDpin, HIGH);
        delay(blueLEDdelay);
        digitalWrite(blueLEDpin, LOW);
        delay(uvLEDdelay);
        digitalWrite(uvLEDpin, LOW);
    }

    if (x > 1700 and x < 1800 and v > 40) {
        digitalWrite(blueLEDpin, HIGH);
        digitalWrite(uvLEDpin, HIGH);
        delay(blueLEDdelay);
        digitalWrite(blueLEDpin, LOW);
        delay(uvLEDdelay);
        digitalWrite(uvLEDpin, LOW);
    }
*/
    if (v > 1400) {
        digitalWrite(blueLEDpin, HIGH);
        digitalWrite(uvLEDpin, HIGH);
        delay(blueLEDdelay);
        digitalWrite(blueLEDpin, LOW);
        delay(uvLEDdelay);
        digitalWrite(uvLEDpin, LOW);
    }
  if (currentMillis - previousMillis > 3000){
  voltscount = 0;
  break;
  }

 }

}


假设voltscount为1的状态。你输入sampling()。您首先将当前磨坊设置为当前时间。假设它是 1000(假设是因为我不知道那个函数 returns 是什么)。然后,由于您的 volts 大于 4.8,您将 voltscount 递增到 2。然后将 previousMillis 设置为 1500 之类的值,因为第二次调用了 millis()。然后你进入第一个 while 循环,在它的末尾,你检查是否 currentMillis - previousMillis > 3000。但这绝不是真的,因为 previouslMillis 的价值大于 currentMillis。我想您可以做的是在检查差异是否大于 3000 之前阅读 currentmillis

if (millis() - previousMillis > 3000){
  voltscount = 0;
  break;
}

在Arduino编程中,大多数初学者的while循环都是错误的。 特别是,如果您觉得有必要以某种方式打破它们。 Arduino环境提供了一个loop()函数原型,请您正确使用。

通常,任何 while() {...} 都可以替换为 if() {...},在下一个循环中再次调用 运行。有时,您需要更多的状态变量,但重要的变化是遵循 loop() 不应该花费明显时间到 运行 并且不应该通过在循环中一个接一个地列出它们来描述顺序动作的范例( ). 基本的 BlinkWithoutDelay 示例适用于所有地方,而不仅仅是闪烁。重要的部分不仅是调用 millis(),而是将草图的状态保存在适当的变量中(比如那些 previousmillis