簡體   English   中英

全局變量在下一個循環之前不更新

[英]Global variable doesn't update prior to next loop

我正在嘗試在 C++ 中為我的 ESP32 構建轉速計。 當我取消注釋Serial.printf("outside rev: %d \n", rev); 在條件之外它可以工作,但是當我評論它時,我得到的值比它們應該的值大幾個數量級(沒有 700 轉,有 7 轉)。 我最好的猜測是 print 語句正在減慢loop()的速度,剛好足以讓incrementRevolutions()在下一個循環之前將全局變量passedMagnet從 true 切換為 false。 這是有道理的,因為延遲更新 passMagnet 將允許newRevCount++; 被觸發多次。 但鑒於競態條件的時間敏感性,這顯然是我無法使用打印語句或逐步調試來調試的。

bool passedMagnet = true;
int incrementRevolutions(int runningRevCount, bool passingMagnet)
{
//    Serial.printf("passedMagnet: %d ,  passingMagnet %d , runningRevCount: %d \n", passedMagnet, passingMagnet, runningRevCount);
    int newRevCount = runningRevCount;
    if (passedMagnet && passingMagnet)
    { //Started a new pass of the magnet
        passedMagnet = false;
        newRevCount++;
    }
    else if (!passedMagnet && !passingMagnet)
    { //The new pass of the magnet is complete
        passedMagnet = true;
    }
    return newRevCount;
}

unsigned long elapsedTime = 0;
unsigned long intervalTime = 0;
int rev = 0;
void loop()
{
    intervalTime = millis() - elapsedTime;
    rev = incrementRevolutions(rev, digitalRead(digitalPin));

//    Serial.printf("outside rev: %d \n", rev);
    if (intervalTime > 1000)
    {
        Serial.printf("rev: %d \n", rev);
        rev = 0;
        elapsedTime = millis();
    }
}

這是 Arduino 或 C++ 編程的已知問題嗎? 我應該怎么做才能修復它?

我認為測試是罪魁禍首。 我不得不重命名並移動一些東西以可視化邏輯,對此感到抱歉。

bool magStateOld = false;  // initialize to digitalRead(digitalPin) in setup()

int incrementRevolutions(int runningRevCount, bool magState)
{
    int newRevCount = runningRevCount;

    // detect positive edge.
    if (magState && !magStateOld)      // <- was eq. to if (magState && magStateOld)
                                       // the large counts came from here.  
    { 
        newRevCount++;
    }
    magStateOld = magState; // record last state unconditionally

    return newRevCount;
}

你也可以寫成...

int incrementRevolutions(int n, bool magState)
{
    n += (magState && !magStateOld);
    magStateOld = magState;
    return n;
}

但是做你想做的最經濟(和最快)的方法是:

bool magStateOld;

inline bool positiveEdge(bool state, bool& oldState)
{
    bool result = (state && !oldState);
    oldState = state;
    return result;
}  

void setup()
{
  // ...

  magStateOld = digitalRead(digitalPin);
}

void loop()
{
    // ...

    rev += (int)positiveEdge(digitalRead(digitalPin), magStateOld);

    // ...
}

它是可重用的,並且節省了堆棧空間和不必要的分配。

如果您無法從傳感器獲得干凈的轉換(正邊緣和負邊緣的噪聲,則需要使用計時器對信號進行一點去抖動。

例子:

constexpr byte debounce_delay = 50; // ms, you may want to play with
                                    // this value, smaller is better.
                                    // but must be high enough to 
                                    // avoid issues on expected
                                    // RPM range. 
                                    // 50 ms is on the high side.
    
byte debounce_timestamp;            // byte is large enough for delays 
                                    // up to 255ms. 

// ...

void loop()
{
    // ...

    byte now = (byte)millis();

    if (now - debounce_timestamp >= debounce_delay)
    {
        debounce_timestamp = now;
        rev += (int)positiveEdge(digitalRead(digitalPin), magStateOld);
    }

    // ...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM