Weird time of day related phenomenon

I have the weirdest problem that I can’t figure out.

The setup

An Imp001 on an April board, running the device code below.

The agent code just outputs the data on Xively

A Maxbotix MB7060 Outdoor ultrasonic sensor, housed in a waterproof (even submergible) container, which measures the distance from the sensor to the surface of my water tank.

Pin 1: open
Pin 2: open
Pin 3: analog out connected to pin 1 of the Imp (imp001)
Pin 4: RX connected to pin 5 of the Imp, held low, but pulsed high to initiate a reading
Pin 5: not used
V+ : connected to Vcc over a BSS138 N-channel MOSFet, of which the gate is connected to pin 2 of the Imp
Gnd : connected to Gnd

The flow of the program
The Imp awakens from a previous sleep
The Imp turns on power to the MB7060 by setting pin 2 high
The Imp waits for a few moments to let the internal calibration of the MB7060 run
The Imp initiates a read by pulsing pin 5 (pin 4 of the MB7060) high for a few millisecs
The Imp reads the resulting analog voltage on pin 1, makes some calculations and outputs the result on a Xively stream through the agent.
The Imp turns off power
The Imp goes to sleep for “polling time”

The weird part

Every night, approximately around the same hour (very early morning), the calculated level of the watertank “drops” by about 1500 liters, only to return to the normal level again the same day, every day (very early afternoon). Needless to say that the waterlevel does NOT change that drastically.

This picture taken from Xively demonstrates the problem (the picture is a composition of data taken from Xively over several days and manually “stitched” together:

So, what am I doing wrong? Anyone any ideas that I can try?

====================================
The following code is running on the Imp:

`//Configure Pins
//Pin 1 analog in to measure ultrasonic transducer voltage
hardware.pin1.configure(ANALOG_IN);
//Pin 2 digital out to power the ultrasonic transducer
hardware.pin2.configure(DIGITAL_OUT) ;
//Pin 3 activates a single pulse
hardware.pin5.configure(DIGITAL_OUT);

// define variables
//Report measurements every xxx seconds, sleep in the meantime

local pollingtime =600 ;
local voltage = hardware.voltage();
//define sensorheight from mounting point to tank edge in cm ;
local SensorHeight = 47;
//Define volume variable
local Volume = 0.0;
//Define measured distance to surface
local Measurement_in_cm = 0.0;
//Define scaling factor (Vcc/1024)
local scalingfactor=0;



//Define functions

function checkVolume_and_voltage()
    {
        //Read voltage to measure health and to calculate the scaling factor
        //The scaling factor will change as the battery empties
        voltage = hardware.voltage();
        //Record it on a Xively channel
        agent.send("Voltage", voltage);
        scalingfactor=voltage/1024.0;

        //Read the distance. The distance returned is a 16-bit ranging the Vcc voltage
        local DistanceReading = hardware.pin1.read();
        local DistanceVoltage = DistanceReading*voltage/65536;
        Measurement_in_cm=DistanceVoltage/scalingfactor;

        server.log(format("Voltage %1.8f \\t Scalingfactor %1.8f \\t DistanceReading %5.0f \\t DistanceVoltage %.8f \\t Distance %5.5f",voltage, scalingfactor, DistanceReading, DistanceVoltage, Measurement_in_cm));
        //50 liter per cm water
        Volume = 10000.0 - (Measurement_in_cm - SensorHeight)*50.0 ;

        //Correct for totally empty or totally full container
        if (Volume <= 0.0)
            Volume = 0.0;
        else
            Volume = Volume ;

        if (Volume >= 10000.0)
            Volume = 10000.0;
        else
            Volume = Volume ;
            
        //Record it on a Xively channel
        agent.send("Level", Volume);
        //server.log(Volume);

    }

//Begin executing program and loop forever

//Set the sensor to single puls reading
hardware.pin5.write(0);


imp.onidle(function() {
  //Turn transducer on with a high on pin 2 (connected to transducer V+)
  //Wait 0.25 secs to stabilize
  hardware.pin2.write(1) ;
  imp.sleep(1);
  
  //Send a read command of 10ms by pulsing pin 5 to high
  hardware.pin5.write(1);
  imp.sleep(0.01);
  hardware.pin5.write(0);
  
  //wait for the last reading to stabilize for another 100 ms
  imp.sleep(0.1);
  
  //Read the values
  checkVolume_and_voltage();
  
  //Now turn the transducer off again to save power
  hardware.pin2.write(0) ;

  //Sleep for the remaining time
  server.sleepfor(pollingtime);
});
`

One thing I don’t really like very much is the power gating for the sensor

  1. the sensor appears to peak at 100mA draw, and your NFET Rds(on) is not great.
  2. Generally, you don’t switch high side of supply with an NFET.

I’d recommend you change your sensor power gate to a PFET with a pullup, so that you drive the imp pin LOW to turn the sensor on. You’ll get less voltage drop across the FET that way.

…but if you’re getting readings at all, then it obviously works a bit. Have you tried taking several readings and averaging them just in case you’re getting some interference on the line? How long is the wire from the sensor to the imp?

Oh, other thought is that maybe your imp has a bad pin 1; try moving the sampling to another pin. Way back we had a bad batch of imps that would misbehave with certain sockets and essentially pin 1 would become disconnected.

Thx for the tips, Hugo.

I was indeed thinking in the line of your last remark. This is indeed probably one of the earliest imp’s, so possibly I do have indeed one of those bad ones. I didn’t know about the bad pin 1, but I couldn’t imagine any other reason why this would work for a long time, and then suddenly read a totally different level for the same voltage.

Is only pin 1 affected? If so, I can just switch to another one and retest.

I had the NFET (it’s actually part of one of the sparkfun level converters, “misused” for this purpose) lying around, hence that solution. I’ll get myself a PFET in the upcoming days.

The wire is about 6 ft, but is shielded. It runs the power to the sensor as well as ground and the control signal and returns the analog read line.

Yep, only pin 1 is affected (it’s due to pressure on pin 9, which is adjacent to pin 1 on the SD socket, bending the PCB upwards).

As the sensor output is buffered, putting maybe 10nF on the imp side of the sensor might be good - though your readings don’t make it look like noise as it’s a clean drop for a period. It’s nothing like the sun hitting the sensor, is it?

No, it’s pitch black in there. But what you say about pressure makes sense. It may be temperature related as it gets colder in the early morning. The PCB bends, thereby causing false readings. As the sun gets up, it’s being warmed up and around noon, it’s warm enough to “snap” back (or vice versa, whatever). That sounds like a very plausible explanation why it would be time of day related.

First night with the DAC reading on pin 7, and indeed, no sudden “water loss”. The readings are of course not all the same, but the large “jump” is gone.

Thx Hugo.

Oops ADC reading, of course