arduino_adc_improvement
差分
このページの2つのバージョン間の差分を表示します。
| 次のリビジョン | 前のリビジョン | ||
| arduino_adc_improvement [2018/03/31 08:38] – 作成 yaasan | arduino_adc_improvement [2018/03/31 08:42] (現在) – yaasan | ||
|---|---|---|---|
| 行 2: | 行 2: | ||
| 本ページでは、analogReadの処理時間を見かけ上、高速化するためのテクニックを紹介します。 | 本ページでは、analogReadの処理時間を見かけ上、高速化するためのテクニックを紹介します。 | ||
| + | |||
| + | たとえば、以下のようなコードがあります。analogReadをコールすると、おおよそ100us、変換時間のためウェイトが入ります。 | ||
| < | < | ||
| - | if( (millis() - gPreviousL8) >= 200) | + | if( (millis() - gPreviousL8) >= 200) |
| + | { | ||
| + | //Reset task | ||
| + | gPreviousL8 = millis(); | ||
| + | |||
| + | //LED Control | ||
| + | taskLED(); | ||
| + | |||
| + | /* Sensor check */ | ||
| + | aEdc = analogRead(A1); | ||
| + | |||
| + | /* OV check */ | ||
| + | if( aEdc > gThreshold_OV | ||
| { | { | ||
| - | //Reset task | + | aErrNo = 2; |
| - | gPreviousL8 = millis(); | + | } |
| + | /* LV check */ | ||
| + | if( aEdc < gThreshold_LV | ||
| + | { | ||
| + | aErrNo = 1; | ||
| - | //LED Control | + | } |
| - | taskLED(); | + | /* エラー処理 */ |
| + | if( aErrNo > 0) | ||
| + | { | ||
| + | if( DSCore.IsPower() == 1) | ||
| + | { | ||
| + | PowerOffByErr(aErrNo); | ||
| + | } | ||
| - | /* Sensor check */ | + | } |
| - | aEdc = __analogRead__(A1); | + | } |
| + | </ | ||
| + | |||
| + | ADCは、通常、変換開始→変換完了までは自由にCPUを動かすことが出来ます。ただし、ArduinoのanalogRead関数は、whileで強制ウェイトを掛けています。 | ||
| + | |||
| + | そこで、analogRead関数を以下のように分割することで、ウェイト中に他の処理をして見かけ上の高速化を行うことが出来るようになります。 | ||
| + | |||
| + | < | ||
| + | void analogRead_trigger(uint8_t pin) | ||
| + | { | ||
| + | |||
| + | if (pin >= 14) pin -= 14; // allow for channel or pin numbers | ||
| + | |||
| + | // set the analog reference (high two bits of ADMUX) and select the | ||
| + | // channel (low 4 bits). | ||
| + | // to 0 (the default). | ||
| + | ADMUX = (analog_reference << 6) | (pin & 0x07); | ||
| + | |||
| + | // start the conversion | ||
| + | sbi(ADCSRA, ADSC); | ||
| + | } | ||
| + | |||
| + | |||
| + | int analogRead_get() | ||
| + | { | ||
| + | uint8_t low, high; | ||
| + | |||
| + | // ADSC is cleared when the conversion finishes | ||
| + | while (bit_is_set(ADCSRA, | ||
| + | |||
| + | // we have to read ADCL first; doing so locks both ADCL | ||
| + | // and ADCH until ADCH is read. reading ADCL second would | ||
| + | // cause the results of each conversion to be discarded, | ||
| + | // as ADCL and ADCH would be locked when it completed. | ||
| + | low = ADCL; | ||
| + | high = ADCH; | ||
| + | |||
| + | // combine the two bytes | ||
| + | return (high << 8) | low; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 上記の分割した関数を使って直した、コードが以下の通りです。 | ||
| + | |||
| + | < | ||
| + | if( (millis() - gPreviousL8) >= 200) | ||
| + | { | ||
| + | //Reset task | ||
| + | gPreviousL8 = millis(); | ||
| + | |||
| + | /* Sensor check */ | ||
| + | analogRead_trigger(A1); | ||
| + | |||
| + | //LED Control | ||
| + | taskLED(); | ||
| + | |||
| + | /* Sensor check */ | ||
| + | aEdc = analogRead_get(); | ||
| + | |||
| + | /* OV check */ | ||
| + | if( aEdc > gThreshold_OV ) | ||
| + | { | ||
| + | aErrNo = 2; | ||
| + | } | ||
| + | /* LV check */ | ||
| + | if( aEdc < gThreshold_LV ) | ||
| + | { | ||
| + | aErrNo = 1; | ||
| - | /* OV check */ | + | } |
| - | if( aEdc > gThreshold_OV | + | /* エラー処理 |
| + | if( aErrNo | ||
| + | { | ||
| + | if( DSCore.IsPower() == 1) | ||
| { | { | ||
| - | aErrNo = 2; | + | PowerOffByErr(aErrNo); |
| - | } | + | |
| - | /* LV check */ | + | |
| - | if( aEdc < gThreshold_LV ) | + | |
| - | { | + | |
| - | aErrNo = 1; | + | |
| - | + | ||
| - | } | + | |
| - | /* エラー処理 */ | + | |
| - | if( aErrNo > 0) | + | |
| - | { | + | |
| - | if( DSCore.IsPower() == 1) | + | |
| - | { | + | |
| - | PowerOffByErr(aErrNo); | + | |
| - | } | + | |
| - | + | ||
| } | } | ||
| + | |||
| } | } | ||
| + | } | ||
| </ | </ | ||
| - | |||
arduino_adc_improvement.1522453090.txt.gz · 最終更新: 2018/03/31 08:38 by yaasan