Device crashes - NV Storage fails after deep sleep and ADC sampling combination

I have been able to replicate a problem with NV storage on 2 different imp002 devices. In order to persist data through deepsleep, I’m using the approach shown in the API docs. Everything works fine i.e. variables are persisted through deepsleep, until you include ADC sampling. The goal was to collect samples on say 20 second deep sleep intervals and then upload all samples to the Agent once a minute (example values only to illustrate the problem - time can vary).
What I find is that the NV table gets trashed when the ADC, or more accurately the sampler object is run to collect samples. The log output shows.

2014-03-20 09:42:12 UTC-4: [Device] sleeping until 1395322952000
2014-03-20 09:42:12 UTC-4: [Status] Device disconnected; 208 bytes sent, 0 received, 208 total
2014-03-20 09:42:36 UTC-4: [Status] Device booting; 4.75% program storage used
2014-03-20 09:42:36 UTC-4: [Device] Crash Test Started
2014-03-20 09:42:36 UTC-4: [Device] Agent Buffer Size:1000 pulseBuffersRequired: 7
2014-03-20 09:42:40 UTC-4: [Device] -------------NV Table trashed--------------
2014-03-20 09:42:40 UTC-4: [Device] ERROR: the index ‘lastUploadToAgentTime’ does not exist
2014-03-20 09:42:40 UTC-4: [Device] ERROR: at completeDataAcquisitionCycle:49
2014-03-20 09:42:40 UTC-4: [Device] ERROR: from samplesReady:40
2014-03-20 09:42:45 UTC-4: [Status] Device disconnected; 203 bytes sent, 0 received, 203 total
2014-03-20 09:42:46 UTC-4: [Status] Device booting; 4.75% program storage used
2014-03-20 09:42:46 UTC-4: [Device] Crash Test Started
2014-03-20 09:42:46 UTC-4: [Device] Agent Buffer Size:1000 pulseBuffersRequired: 7
2014-03-20 09:42:46 UTC-4: [Device] -----------------Initializing NV----------------
2014-03-20 09:42:51 UTC-4: [Device] sleeping until 1395322990000
2014-03-20 09:42:51 UTC-4: [Status] Device disconnected; 208 bytes sent, 0 received, 208 total
2014-03-20 09:43:14 UTC-4: [Status] Device booting; 4.75% program storage used
2014-03-20 09:43:14 UTC-4: [Device] Crash Test Started
2014-03-20 09:43:14 UTC-4: [Device] Agent Buffer Size:1000 pulseBuffersRequired: 7
2014-03-20 09:43:19 UTC-4: [Device] -------------NV Table trashed--------------
2014-03-20 09:43:19 UTC-4: [Device] ERROR: the index ‘lastUploadToAgentTime’ does not exist
2014-03-20 09:43:19 UTC-4: [Device] ERROR: at completeDataAcquisitionCycle:49
2014-03-20 09:43:19 UTC-4: [Device] ERROR: from samplesReady:40

I was able to reduce the code to this minimal piece to reproduce the error:
`server.log(“Crash Test Started”);

// ADC Sampling rate in Hz. Choose multiples of 10 because the interval
// between samples is calculated as 1000 / SAMPLING_FREQUENCY = Interval ms
const SAMPLING_RATE = 100;

// Two small buffers for holding the ADC data. ADC is free running
// converting at the specified SAMPLING_RATE.
const BUFF_SIZE = 128;
buffer1 <- blob(BUFF_SIZE);
buffer2 <- blob(BUFF_SIZE);

pulseAcqDuration <- 5; // How long to aquire data
pulseBuffersProcessed <- 0; // Running total of number of buffers that have been processed

pulseBuffersRequired <- ((pulseAcqDuration) / (BUFF_SIZE/2.0/SAMPLING_RATE)).tointeger();
agentSize <- ( (pulseAcqDuration) / (BUFF_SIZE/2.0/SAMPLING_RATE) * BUFF_SIZE).tointeger();
server.log(“Agent Buffer Size:” + agentSize + " pulseBuffersRequired: " + pulseBuffersRequired );
bufferAgent <- blob( agentSize );

// Analog data in on pin 1
adcPin <- hardware.pin1;

//------------------------------------------------------------------------
function samplesReady(buffer, length)
{
if (length > 0) {
if(++pulseBuffersProcessed >= pulseBuffersRequired )
{
hardware.sampler.stop();
pulseBuffersProcessed = 0;
//agent.send(“log”, bufferAgent );
// Clear the Agent buffer for the next collection
//bufferAgent.flush();

  if (!("nv" in getroottable() && "lastUploadToAgentTime" in nv)) {
    
    server.log("-------------NV Table trashed--------------")  
  }
  completeDataAcquisitionCycle();
}

}
}

//--------------------------------------------------------------------------------------------------------
function completeDataAcquisitionCycle()
{
// On the specfied interval, send the data to the agent
if( time() - nv.lastUploadToAgentTime >= ( ( nv.uploadMultiple * nv.collectionInterval ) -2 )) {
nv.lastUploadToAgentTime = time;
// sendQueuedData( );
}

// Tell the server we’ll be online shortly
server.expectonlinein( nv.collectionInterval );
// go to deep sleep for x seconds
imp.onidle(function() { imp.deepsleepfor(nv.collectionInterval); });

}

//------------------------------------------------------------------------
function initialize()
{
if (!(“nv” in getroottable() && “queues” in nv)) {
server.log("-----------------Initializing NV----------------");

// queues do not exist so add all queues. This will happen at power up
// since NV storage does not persist through power cycle
nv <- { queues = { batteryQueue = [], temperatureQueue = [], rssiQueue = [], lightQueue = [] }, 
        lastUploadToAgentTime = 0,
        uploadMultiple     = 3,    // nv.uploadMultiple * nv.collectionInterval = uploadInterval or how often to upload colelcted data to server in seconds
        collectionInterval = 20,   // How often to acquire and timestamp data
        serverNotConnected = 0,
        acquisitionEnabled = true
};

}

adcPin.configure(ANALOG_IN);
imp.setpowersave(true);
// Start Sampling
hardware.sampler.reset();
hardware.sampler.configure(adcPin, SAMPLING_RATE, [buffer1, buffer2], samplesReady);
hardware.sampler.start();
}

//------------------------------------------------------------------------
// Start things off.
//------------------------------------------------------------------------
initialize();

`

When the program initializes from power up, the NV table is created and the program runs correctly. ADC Sampler runs to completion and NV table is intact. After deepsleep, the NV table appears to be valid during initialization, but at the end of the ADC acquisition cycle, it is corrupted. I have tried bigger sampling buffers (1024), reduced sampling frequency to 50Hz but nothing affects the crash condition.

Can anyone see anything in the code that might cause this? Or is this an imp bug?

nv.lastUploadToAgentTime = time;

“time” is a function and cannot be kept in the NV table. So it’s not there when the imp restarts. You probably meant:

nv.lastUploadToAgentTime = time();

Peter

Thanks Peter! That was it exactly. Works now :">
I’m going to blame my failing eyesight. I must have looked at that line 10000 times