elapsedMicros strangeness?

Status
Not open for further replies.

paynterf

Well-known member
Hi,

I'm using a Teensy 3.5 to sample an incoming 520Hz (~2ms/cycle) square-wave signal. I want to sample the waveform 20 times/cycle, so I set the timing delay to 95.7uSec (empirically derived number). Here is the code:

Code:
#include <ADC.h>
ADC *adc = new ADC(); // adc object;


const int OUTPUT_PIN = 32; //lower left pin
const int IRDET1_PIN = A0; //aka pin 14
const float USEC_PER_SAMPLE = 95.7; //value that most nearly zeroes beat-note
const int SENSOR_PIN = A0;
int sample_count = 0; //this counts from 0 to 1279
elapsedMicros sinceLastOutput;

void setup()
{
	Serial.begin(115200);
	pinMode(OUTPUT_PIN, OUTPUT);
	pinMode(IRDET1_PIN, INPUT);
	digitalWrite(OUTPUT_PIN, LOW);

	//decreases conversion time from ~15 to ~5uSec
	adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED);
	adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED);
	adc->setResolution(12);
	adc->setAveraging(1);
}

void loop()
{
	//this runs every 95.7uSec
	if (sinceLastOutput > USEC_PER_SAMPLE)
	{
		sinceLastOutput = 0;
		//sinceLastOutput -= USEC_PER_SAMPLE;

		//start of timing pulse
		digitalWrite(OUTPUT_PIN, HIGH);

		//	Step1: Collect a 1/4 cycle group of samples and sum them into a single value
		// this section executes each USEC_PER_SAMPLE period
		int samp = adc->analogRead(SENSOR_PIN);
		Serial.print(sample_count); Serial.print("\t"); Serial.println(samp);
		sample_count++; //checked in step 6 to see if data capture is complete

		digitalWrite(OUTPUT_PIN, LOW);
	}//if (sinceLastOutput > 95.7)
}//loop

The problem I'm having is that I get two completely different results depending on whether I use the 'sinceLastOutput = 0' or sinceLastOutput -= USEC_PER_SAMPLE versions of the elapsedMicros variable adjustment technique, as shown in the following Excel sample plots. In each plot, the first 100 or so samples are shown. These plots should be almost identical, but in fact are off by a factor of about 5:1 - something that I can't explain. This is perfectly repeatable, and is driving me nuts.

SinceLastOutput1.jpg
SinceLastOutputZero.jpg



Any ideas what I'm doing wrong here?

TIA,

Frank
 
If i comment out the print's in the loop() and use an analyzer to look at OUTPUT_PIN, the analyzer looks about the same for either setting of sinceLastOuput. Low for about 90.7us, and high for 7.2 us. HOWEVER, as you noted, with the print's active and the monitor open, the =0 setting, shows 81.7us low and 19.5us high, BUT for -= setting, 5 us low, high 17.8. Closing the monitor, usually makes the -= setting work even with print's enabled. So there is effect from the print's?? I tried different optimization levels with no effect. (T3.2@96mhz 1.8.3/1.37)

inconclusive
 
Maybe the printing is just too fast and there's an overflow of the USB-Buffers ?
(just a blind guess)
You could try to print every 10th loop only - does this help ?
 
Last edited:
If i comment out the print's in the loop() and use an analyzer to look at OUTPUT_PIN, the analyzer looks about the same for either setting of sinceLastOuput. Low for about 90.7us, and high for 7.2 us. HOWEVER, as you noted, with the print's active and the monitor open, the =0 setting, shows 81.7us low and 19.5us high, BUT for -= setting, 5 us low, high 17.8. Closing the monitor, usually makes the -= setting work even with print's enabled. So there is effect from the print's?? I tried different optimization levels with no effect. (T3.2@96mhz 1.8.3/1.37)

inconclusive

Moreover, If I close and then re-open the serial port, I get the '=0' behavior even with the '-= USEC_PER_SAMPLE' setup, as shown below
SinceLastOutputMinusEqualAfterCloseOpen.jpg
 
How long are you actually measuring?

Initially, you will have a fair amount of time accumulated in 'sinceLastOutput' (all the startup and serial initialization delay). So your initial loops using '-=' won't have the proper delay, until 'sinceLastOutput' reaches 0.

Add a 'sinceLastOutput = 0;' at the end of setup().
 
How long are you actually measuring?

Initially, you will have a fair amount of time accumulated in 'sinceLastOutput' (all the startup and serial initialization delay). So your initial loops using '-=' won't have the proper delay, until 'sinceLastOutput' reaches 0.

Add a 'sinceLastOutput = 0;' at the end of setup().

tni,

You nailed it! After adding the line you suggested to the setup() block, both versions (=0 and -= Tdelay) produce exactly the same results, as shown below
SinceLastOutputZeroInSetup.jpg

Thanks all for the prompt and helpful replies - esp tni. I guess I'm going to have to start monitoring this forum now, as I need to help someone else now to reduce my karma deficit :)

Frank
 
Status
Not open for further replies.
Back
Top