ユーザ用ツール

サイト用ツール


arduino_adc_improvement

文書の過去の版を表示しています。


ArduinoのanalogRead高速化

本ページでは、analogReadの処理時間を見かけ上、高速化するためのテクニックを紹介します。

たとえば、以下のようなコードがあります。analogReadをコールすると、おおよそ100us、変換時間のためウェイトが入ります。

	if( (millis() - gPreviousL8) >= 200)
	{
		//Reset task
		gPreviousL8 = millis();
		
		//LED Control
		taskLED();
		
		/* Sensor check */
		aEdc = analogRead(A1);
		
		/* OV check */
		if( aEdc > gThreshold_OV )
		{
			aErrNo = 2;
		}
		/* LV check */
		if( aEdc < gThreshold_LV )
		{
			aErrNo = 1;
			
		}
		/* エラー処理 */
		if( aErrNo > 0)
		{
			if( DSCore.IsPower() == 1)
			{
				PowerOffByErr(aErrNo);
			}
			
		}
	}

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).  this also sets ADLAR (left-adjust result)
    // 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, ADSC));
    
    // 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;
			
		}
		/* エラー処理 */
		if( aErrNo > 0)
		{
			if( DSCore.IsPower() == 1)
			{
				PowerOffByErr(aErrNo);
			}
			
		}
	}
arduino_adc_improvement.1522453312.txt.gz · 最終更新: 2018/03/31 08:41 by yaasan

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki