This is taking place on a Duemilanove with an ATMega328P.
My sketch polls a MaxSonar sensor to determine whether someone is standing in front of my aquarium and then adjusts the tank lights accordingly. Distance measurement is by way of pulse width detection (147 microseconds to the inch).
I'm playing around with the sketch and the hardware to eliminate spurious measurements. I've got a working solution...but only when the Arduino's USB port is plugged into the serial port of my laptop. When it's not plugged in, the sketch detects the presence of an observer and ramps the lights up, but it never detects the observer's departure so as to turn the lights down.
The effect of plugging in the USB connection is reproducible. Merely rebooting the Arduino, without the USB being connected, doesn't solve the problem.
Here's the portion of the code that interfaces to the MaxSonar. The entire sketch is pretty large (it compiles to around 20KB) so posting it probably wouldn't be too useful.
The header file:
// interface for sonar observation
#define MICROSEC_PER_INCH 147.0
#define SONAR_READINGS 5
#define SENSE_WINDOW_MICROSEC 50000
typedef void (* DetectionCallback) ( ObserverDetection* );
ObserverDetection( byte pin );
int detect( const time_t t );
unsigned long _pulseWidths[SONAR_READINGS];
unsigned long _sortedWidths[SONAR_READINGS];
The method definition file:
// implementation of sonar observation interface
ObserverDetection::ObserverDetection( byte pin )
_pin = pin;
freqSec = 5;
_lastTime = 0; // force reading on first detect
_lastDist = -1;
int ObserverDetection::detect( const time_t t )
if( (t - _lastTime) < freqSec ) return _lastDist;
for( byte idx = 0; idx < SONAR_READINGS; idx++ )
_pulseWidths[idx] = pulseIn(_pin, HIGH, SENSE_WINDOW_MICROSEC);
_lastDist = (int) ((float) _sortedWidths[ SONAR_READINGS / 2 ] / MICROSEC_PER_INCH);
if( _lastDist <= 0 ) _lastDist = -1;
for( byte i = 0; i < SONAR_READINGS; i++ )
_sortedWidths[i] = _pulseWidths[i];
for( byte i=0; i< SONAR_READINGS- 1; i++ )
byte m = i;
for( byte j=i+1; j< SONAR_READINGS; j++ )
if (_sortedWidths[j] < _sortedWidths[m]) m = j;
if (m != i)
unsigned long t = _sortedWidths[m];
_sortedWidths[m] = _sortedWidths[i];
_sortedWidths[i] = t;
FYI, the basic algorithm is:
- wait 5 seconds between observations (this is adjustable)
- take 5 sonar readings (each one with a timeout window of 50000 microseconds)
- sort the readings by distance
- select the 3rd reading (median) as the observation
Elsewhere in the sketch the observed median distance value is used to determine whether the system is or is not under observation.
My question is this: are there side effects of the Arduino USB port being connected to a destination which alter the way the board works? Even to the extent of "just" inserting some timing delays in the looping?