Arduino MAX30100 程式庫讀取資料的小臭蟲


もし你有使用 Arduino MAX30100 程式庫 撰寫 Arduino 程式, 可能會遇に一個の小問題, 若是沒有速的讀取資料, 就可能會導致後續不再夠讀取新的資料.の loop() のように:

void loop()
{
    uint16_t ir, red;

    sensor.update();

    while (sensor.getRawValues(&ir, &red)) {
        Serial.print(ir);
        Serial.print('\t');
        Serial.println(red);
    }
}


因為是不間斷的讀取資料, 所以正常運作, 不斷顯示讀到的原始資料:

Initializing MAX30100..SUCCESS
2105    1025
2114    1031
2128    1040
2142    1062
2171    1067
...


但是如果因為進行其他事務導致耽擱了時間我們以加入delay(500)為例:

void loop()
{
    uint16_t ir, red;

    sensor.update();

    while (sensor.getRawValues(&ir, &red)) {
        Serial.print(ir);
        Serial.print('\t');
        Serial.println(red);
    }
    Serial.println("=======");
    delay(500);
}


你看到的輸出結果就可能會是這樣:

Initializing MAX30100..SUCCESS
35  36
=======
=======
=======
=======
=======
=======
...


你會は、ループ ゾーンの面を認識し、後來都沒有發生的影響を与えました.原因は程式庫從 MAX30100 模組讀取資料的 MAX30100_RawData 是這樣寫的:

void MAX30100::readFifoData()
{
    uint8_t buffer[MAX30100_FIFO_DEPTH * 4];
    uint8_t toRead;

    toRead = (readRegister(MAX30100_REG_FIFO_WRITE_POINTER) - readRegister(MAX30100_REG_FIFO_READ_POINTER)) & (MAX30100_FIFO_DEPTH - 1);

    if (toRead)
    {
        burstRead(MAX30100_REG_FIFO_DATA, buffer, 4 * toRead);

        for (uint8_t i = 0; i < toRead; ++i)
        {
            // Warning: the values are always left-aligned
            readoutsBuffer.push({.ir = (uint16_t)((buffer[i * 4] << 8) | buffer[i * 4 + 1]),
                                 .red = (uint16_t)((buffer[i * 4 + 2] << 8) | buffer[i * 4 + 3])});
        }
    }
}


MAX30100 使用一個總共 16 筆資料的環狀居住列, 並透過 FIFO_WR_PTR 暫存器紀錄下一筆資料要寫入的位置編號, 編號為0~15;FIFO_RD_PTR 暫定存器則は第一筆予定讀取資料の位置編. , 並置されて OVF_COUNTER (オーバーフロー カウンター) 一時的に存在する器記錄は丟棄却された資料筆數, 最多為 15.

toRead = (readRegister(MAX30100_REG_FIFO_WRITE_POINTER) - readRegister(MAX30100_REG_FIFO_READ_POINTER)) & (MAX30100_FIFO_DEPTH - 1);


また、入所位置が調査対象の位置との差距離であるが、並置は考慮された居列已滿であり、また差距離も 0 であるという状況です.得到待讀取資料為 0 筆的結論, 使得後面真正讀取資料的 if 內的程式根本不會執行.滿, 將 toRead 設為 16 即可:

if(readRegister(MAX30100_REG_FIFO_OVERFLOW_COUNTER) == 0)
  toRead = (readRegister(MAX30100_REG_FIFO_WRITE_POINTER) - readRegister(MAX30100_REG_FIFO_READ_POINTER)) & (MAX30100_FIFO_DEPTH-1);
else
  toRead = 16;


修正過後、同樣的程式就可以上正確な結果了:

Initializing MAX30100..SUCCESS
=======
8649    2722
8646    2725
8639    2731
8615    2718
8601    2716
8582    2702
8570    2703
8570    2698
8579    2701
8591    2709
8594    2707
8602    2712
8585    2716
8568    2714
8526    2711
8491    2700
=======
8437    2672
8422    2664
8426    2667
8431    2667
.....