2017-03-14 6 views
0

NodeMCUボードを使用してコンデンサの放電時間を測定しようとしています。以下の完全なスケッチを参照してください。このコードはうまく動作しますが、ESP.getCycleCount()関数とタイミングの割り込みを使うことで、より良い時間スケールになるように改善したいと考えています。私はこのようなもので上記の機能を置き換える、capPos端子の立ち下がりエッジに耳を傾け、割り込みベースの機能のいくつかの形式に書き直したいArduino/ESP8266割り込みを使用してサンプルを取る

startTime = micros(); 
while (digitalRead(capPos) == HIGH) { 
    delayMicroseconds (1); 
} 
endTime = micros(); 

whileループ:

関心の一部はこれです
startTime = micros(); 
attachInterrupt(digitalPinToInterrupt(capPos), dischargeInterrupt, FALLING); 
} 


void dischargeInterrupt() { 

endTime = micros(); 
detachInterrupt(digitalPinToInterrupt(capPos)); 

その後、元のコードが続きます。

私が持っている問題は、必要な100サンプルをどのように取るかです。 startTimeを実行した後に割り込みを設定すると、このルーチンは終了し、100回の反復のうちの次の処理を行います。代わりに、それは待たなければなりません:インタラプトが来るように、その後、元のスケッチに従って、残りのルーチンが終了するようにします。むしろ割り込みの新機能であるから、どこから始めたらいいのか分かりません。

だから何を行う必要があります: - loop()呼び出しgetEC()

  • getEC()は100のサンプル取ります

    • が担当キャップを、放電を測定するために、割り込み設定、放電用のピンを設定時間。

    • 割り込みが来て、時間が経過したことを計測します。ネガティブキャップサイクルが実行され、1回のサンプリングラウンドが完了する。 LOWにピンドロップで瞬時に反応し、時間をはるかに高い解像度を使用します。

この変更の主な目的は、タイミングをより正確にすることです。現在のマイクロ秒の解像度は仕事をしますが、それは深刻な制限です。ここで

私の完全な、働く、スケッチ:

だから、
// capacitor based TDS measurement 

// pin D5 C+ - 330 ohm resistor----------|------------|  
//          |   | 
//          cap  EC probe or 
//          |   resistor (for simulation) 
// pin D6 C- ----------------------------|   | 
//             | 
// pin A0 EC -----------------------------------------| 

#include <Average.h> 

int capPos = D5; //C+ 
int capNeg = D6; //C- 
int EC = D7;  //EC 

float CAP = 47; // capacity in nF 
#define calibration 150 // a calibration factor to link time with EC. 

void setup() { 
    Serial.begin(9600); 
} 

void loop() { 
    float EC = getEC(); // get the EC as mS/cm. 
    Serial.println (", EC: " + String(EC) + " mS/cm"); 
    delay(100); 
} 

float getEC() { 

    int samples = 100;    // number of EC samples to take and average. 
    unsigned long startTime;  // the time stamp (in microseconds) the measurement starts. 
    unsigned long endTime;   // the time stamp (in microseconds) the measurement is finished. 
    unsigned int dischargeTime; // the time it took for the capacitor to discharge. 
    Average<unsigned int> discharge(samples); // Take measurements on both the positive and negative cycles. 
    unsigned int chargeDelay = 500;   // The time (in microseconds) given to the cap to fully charge/discharge - about 10x RC is a good value. 

    int startLevel; // analog level of the pin. 
    int endLevel; 
    pinMode(A0, INPUT); 

    for(int i=0; i<samples; i++) { // take <samples> measurements of the EC. 

    // Stage 1: fully charge capacitor for positive cycle. 
    // C+ high, C- low, EC disconnected. 
    pinMode (EC, INPUT); 
    pinMode (capPos,OUTPUT); 
    digitalWrite (capPos, HIGH); 
    pinMode (capNeg, OUTPUT); 
    digitalWrite (capNeg, LOW); 
    delayMicroseconds(chargeDelay); 

    // Stage 2: positive side discharge; measure time it takes. 
    // C+ disconnected, C- low, EC low. 
    pinMode (capPos,INPUT); //set C+ to input to keep voltage from grounding a discharging thru this output pin 
    pinMode (EC, OUTPUT); 
    digitalWrite (EC, LOW); 

    // Measure time until capPos goes LOW. Can't use pulseIn() here as the pin will be high already. 
    startTime = micros(); 
    while (digitalRead(capPos) == HIGH) { 
     delayMicroseconds (1); 
    } 
    endTime = micros(); 

    // handle potential overflow of micros() just as we measure, this happens every 70 minutes. 
    if (endTime < startTime) dischargeTime = 4294967295 - startTime + endTime; 
    else dischargeTime = endTime - startTime; 
    discharge.push(dischargeTime); 

    // Stage 3: fully charge capacitor for negative cycle. C+ low, C- high, EC disconnected. 
    pinMode (EC, INPUT); 
    pinMode (capPos,OUTPUT); 
    digitalWrite (capPos, LOW); 
    pinMode (capNeg, OUTPUT); 
    digitalWrite (capNeg, HIGH); 
    delayMicroseconds(chargeDelay); 

    // Stage 4: negative side charge; don't measure as we just want to balance it the directions. 
    // C+ disconnected, C- low, EC low. 
    pinMode (capPos,INPUT); //set C+ to input to keep voltage from grounding a discharging thru this output pin 
    pinMode (EC, OUTPUT); 
    digitalWrite (EC, HIGH); 
    delayMicroseconds(dischargeTime); 

    } 
    float dischargeAverage = discharge.mean(); 
    Serial.print("Discharge time: "); 
    Serial.print(dischargeAverage); 

    // Calculate EC from the discharge time. 

    return dischargeAverage; 
} 
+0

これのどれかがあなたにマイクロ秒よりも正確なタイミング情報を与える方法を私は見ていません... – dandavis

答えて

0

、これは自分自身に答えました。

時間分解能:プロセッササイクルをカウントするESP.getCycleCount()を使用すると、より正確な時間を得ることができます.80MHzのNodeMCUボードでは、サイクルあたり12.5ns、またはマイクロ秒あたり80サイクルです。私は最初の部分でそれを言及すべきだった。

割り込み:これは私が誤解したものです。今私はmain関数がタイムアウトに達するまで(1ミリ秒に設定され、通常の予想時間は1〜100マイクロ秒の範囲にある)、グローバル変数が割り込み関数によって設定されるまで待つことによって解決します。今は12.5ナノ秒の解像度で測定しています!

このスケッチから欠落しているものの1つは、タイミングに対処するためのプログラム時間の修正です:ECピンの値を落としてカウントを開始するまでの時間と、割り込みを受け取るのにかかる時間カウントを停止する。そのオーバヘッドが100サイクルと言えば、それは1.25マイクロ秒となり、測定時間内に収まります。

//コンデンサベースのTDS測定

// pin D5 C+ - 330 ohm resistor----------|------------|  
//          |   | 
//          cap  EC probe or 
//          |   resistor (for simulation) 
// pin D6 C- ----------------------------|   | 
//             | 
// pin A0 EC -----------------------------------------| 

#include <Average.h> 

int capPos = D5; //C+ 
int capNeg = D6; //C- 
int EC = D7;  //EC 
unsigned long startCycle; 
unsigned long endCycle; 
#define CYCLETIME 12.5 // the time it takes in nanoseconds to complete one CPU cycle (12.5 ns on a 80 MHz processor) 

float CAP = 47; // capacity in nF 
#define calibration 150 // a calibration factor to link time with EC. 

void setup() { 
    Serial.begin(9600); 
} 

void loop() { 
    float EC = getEC(); // get the EC as mS/cm. 
    Serial.println (", EC: " + String(EC) + " mS/cm"); 
    delay(500); 
} 

float getEC() { 

    int samples = 100;    // number of EC samples to take and average. 
    unsigned long startTime;  // the time stamp (in microseconds) the measurement starts. 
    unsigned long endTime;   // the time stamp (in microseconds) the measurement is finished. 
    unsigned int dischargeTime; // the time it took for the capacitor to discharge. 
    Average<unsigned int> discharge(samples); // The sampling results. 
    unsigned int chargeDelay = 500;   // The time (in microseconds) given to the cap to fully charge/discharge - about 10x RC is a good value. 
    unsigned int timeout = 1; // discharge timeout in milliseconds - if not triggered within this time, the EC probe is probably not there. 

    int startLevel; // analog level of the pin. 
    int endLevel; 
    pinMode(A0, INPUT); 

    for(int i=0; i<samples; i++) { // take <samples> measurements of the EC. 

    // Stage 1: fully charge capacitor for positive cycle. 
    // C+ high, C- low, EC disconnected. 
    pinMode (EC, INPUT); 
    pinMode (capPos,OUTPUT); 
    digitalWrite (capPos, HIGH); 
    pinMode (capNeg, OUTPUT); 
    digitalWrite (capNeg, LOW); 
    delayMicroseconds(chargeDelay); 

    // Stage 2: positive side discharge; measure time it takes. 
    // C+ disconnected, C- low, EC low. 
    startCycle = ESP.getCycleCount(); 
    pinMode (capPos,INPUT); //set C+ to input to keep voltage from grounding a discharging thru this output pin 
    pinMode (EC, OUTPUT); 
    digitalWrite (EC, LOW); 

    // Use cycle counts and an interrupt to get a much more precise time measurement, especially for high-EC situations. 
    endCycle = 0; 
    startTime = millis(); 
    attachInterrupt(digitalPinToInterrupt(capPos), capDischarged, FALLING); 
    while (endCycle == 0) { 
     if (millis() > (startTime + timeout)) break; 
    } 
    detachInterrupt(digitalPinToInterrupt(capPos)); 
    if (endCycle == 0) dischargeTime = 0; 
    else { 

     // Handle potential overflow of micros() just as we measure, this happens about every 54 seconds 
     // on a 80-MHz board. 
     if (endCycle < startCycle) dischargeTime = (4294967295 - startCycle + endCycle) * CYCLETIME; 
     else dischargeTime = (endCycle - startCycle) * CYCLETIME; 
     discharge.push(dischargeTime); 
    } 

    // Stage 3: fully charge capacitor for negative cycle. C+ low, C- high, EC disconnected. 
    pinMode (EC, INPUT); 
    pinMode (capPos,OUTPUT); 
    digitalWrite (capPos, LOW); 
    pinMode (capNeg, OUTPUT); 
    digitalWrite (capNeg, HIGH); 
    delayMicroseconds(chargeDelay); 

    // Stage 4: negative side charge; don't measure as we just want to balance it the directions. 
    // C+ disconnected, C- high, EC high. 
    pinMode (capPos,INPUT); //set C+ to input to keep voltage from grounding a discharging thru this output pin 
    pinMode (EC, OUTPUT); 
    digitalWrite (EC, HIGH); 
    delayMicroseconds(dischargeTime/1000); 

    } 
    float dischargeAverage = discharge.mean(); 
    Serial.print("Discharge time: "); 
    Serial.print(dischargeAverage); 

    // Calculate EC from the discharge time. 

    return dischargeAverage; 
} 

// Upon interrupt: register the cycle count of when the cap has discharged. 
void capDischarged() { 
    endCycle = ESP.getCycleCount(); 
    detachInterrupt(digitalPinToInterrupt(capPos)); 
} 
関連する問題