Millis() seems to reset for some reason

I have been playing around with the spark for creating a simple energy meter. I created something that will trigger on a pulse(1 pulse per watt-hour), sample the current time, and store this in flash. Then when I connect with TCP(once a day or so), i retrieve the array of data, to display it as a graph.
but I currently seem to run into a small issue regarding millis(). the code posted below provides an output that leaves me to think that millis() is resetting and seems to be affected by the tcpserver.

    // Define the pins we're going to call pinMode on
int sensor = D0;

unsigned long pulsearray[100];
unsigned int pulsearrayindex = 0;
unsigned int storearrayindex = 0;
unsigned int flashindex = 0;
unsigned int printlist = 0;
unsigned int timst = 0;
bool printthelist = false;

TCPServer server = TCPServer(23);
TCPClient client;


void blink();
int SparkFlash_read(int address);
int SparkFlash_write(int address, uint16_t value);

// This routine runs only once upon reset
void setup() {
  // It's important you do this here, inside the setup() function rather than outside it or in the loop function.
  server.begin();// start listening for clients
  pinMode(sensor, INPUT_PULLUP);
  attachInterrupt(sensor, blink, FALLING);
}


// This routine gets called repeatedly, like once every 5-15 milliseconds.
// Spark firmware interleaves background CPU activity associated with WiFi + Cloud activity with your code. 
// Make sure none of your code delays or blocks for too long (like more than 5 seconds), or weird things can happen.
void loop() 
{
    if(storearrayindex != pulsearrayindex)
    {
        SparkFlash_write(flashindex, (pulsearray[storearrayindex] >> 16) & 0x0000ffff);
        SparkFlash_write(flashindex + 2, pulsearray[storearrayindex] & 0x0000ffff);
        
        flashindex += 4;
        if(flashindex > 0x1FFFFF)
        {
            flashindex = 0;
        }
                          
        storearrayindex++;
        if(storearrayindex > 99)
        {
            storearrayindex = 0;
        }
    }
    
    if (client.connected()) 
    {
        if (client.available()) 
        {
            if(client.read() == 'g')
            {
                server.println("list");
                printthelist = true;
                printlist = 0;
            }
        }
        if(printthelist == true)
        {
            if(flashindex != printlist)
            {
                timst = SparkFlash_read(printlist);
                timst <<= 16;
                timst |= SparkFlash_read(printlist + 2);
                
                server.print(timst);
                //debug
                server.print(",");
                server.print(pulsearrayindex);
                server.print(",");
                server.print(storearrayindex);
                server.print(",");
                server.print(flashindex);
                server.print(",");
                server.print(pulsearray[pulsearrayindex]);
                // end debug
                server.print(",");                
                server.println(printlist);
                
                printlist += 4;
                if(printlist > 0x1FFFFF)
                {
                    printlist = 0;
                }
            }
            else
            {
                printthelist = false;
                client.flush();
            }
        }
    } 
    else
    {
    // if no client is yet connected, check for a new connection
        client = server.available();
    }
}

// This is a circular buffer of 100 items to store when a pulse happened
void blink()
{
    pulsearray[pulsearrayindex] = millis();
    pulsearrayindex++;
    if(pulsearrayindex > 99)
    {
        pulsearrayindex = 0;
    }
}

int SparkFlash_read(int address)
{
  if (address & 1)
    return -1; // error, can only access half words

  uint8_t values[2];
  sFLASH_ReadBuffer(values, 0x80000 + address, 2);
  return (values[0] << 8) | values[1];
}

int SparkFlash_write(int address, uint16_t value)
{
  if (address & 1)
    return -1; // error, can only access half words

  uint8_t values[2] = {
    (uint8_t)((value >> 8) & 0xff),
    (uint8_t)(value & 0xff)
  };
  sFLASH_WriteBuffer(values, 0x80000 + address, 2);
  return 2; // or anything else signifying it worked
}

so this currently creates the following output:

g
list
0,50,50,200,0,0
0,50,50,200,0,4
0,50,50,200,0,8
0,50,50,200,0,12
0,50,50,200,0,16
0,50,50,200,0,20
0,50,50,200,0,24
0,50,50,200,0,28
0,50,50,200,0,32
0,50,50,200,0,36
0,50,50,200,0,40
0,50,50,200,0,44
0,50,50,200,0,48
0,50,50,200,0,52
0,50,50,200,0,56
0,50,50,200,0,60
0,50,50,200,0,64
0,50,50,200,0,68
0,50,50,200,0,72
0,50,50,200,0,76
0,50,50,200,0,80
0,50,50,200,0,84
0,50,50,200,0,88
0,50,50,200,0,92
4096,50,50,200,0,96
0,50,50,200,0,100
0,50,50,200,0,104
0,50,50,200,0,108
0,50,50,200,0,112
0,50,50,200,0,116
0,50,50,200,0,120
18432,50,50,200,0,124
256,50,50,200,0,128
4,50,50,200,0,132
0,50,50,200,0,136
1,50,50,200,0,140
0,50,50,200,0,144
4096,50,50,200,0,148
65792,50,50,200,0,152
256,50,50,200,0,156
36,50,50,200,0,160
5140,50,50,200,0,164
1,50,50,200,0,168
0,50,50,200,0,172
10272,50,50,200,0,176
32,50,50,200,0,180
0,50,50,200,0,184
17,50,50,200,0,188
66560,50,50,200,0,192
1,50,50,200,0,196

any idea why most of the timestamps seem to be 0 or something small?(with an occasional power of 2 multiple??)

Thanks in advance

PS: feel free to reuse/improve on posted code above :wink:

Could you just output the millis() itself to Serial and see the data?

Maybe the flash_write is not working correctly since there’s some discussion of it not being 100% reliable at this moment for users.

It’s working great for OTA firmware download, factory reset etc as the core is managing all the stuff.

When we use the flash_write, the SPI of the CC3000 and external flash is on the same line and might be the problem for now

You can also download the flash memory portion via dfu-util and take a look at the data to see if anything is actually being written to the address :smile:

Hi @robindev

Kenneth is right on about flash being somewhat experimental right now. Based on another user’s experience with writing flash, I wrote a test program that writes 256 byte blocks and reads them back, which worked great with each of the calls to sFLASH_… surrounded by delay(20); sFLASH_…; delay(20); My theory is that this give the core time to handle the CC3000 and could still fail, but it does improve things.

Maybe in addition to what Kenneth suggested, you could use Spark.publish() to send the events out in the interrupt handler (blink). The advantage is they would get automatically timestamped and you could compare to the data you fetch over TCP.

@robindev @kennethlimcp @bko, The cc3000 and the serial Flash are on the same SPI bus. I think this is a SPI, DMA arbitration issues. I really need to have some time to dig into it, but I am just swamped at the moment.

I hope you have some free time soon! :smiley:

Always impressed by how you guys perform the fixes really. My best experience is only with the PIC like years back during my microcontroller class and hobby-ing time. STM32 is like a big jump for me. haha! :stuck_out_tongue:

This may or may not help:

SparkFlash_write(flashindex,  (uint16_t)((pulsearray[storearrayindex] >> 16) & 0xffff));
SparkFlash_write(flashindex + 2, (uint16_t)(pulsearray[storearrayindex] & 0xffff));

If you notice, you have a lot of perfectly round numbers for timestamps… 4096, 256, 0, 18482, 4, 65792… all are just one bit high, or two bits high. To answer your question, millis() does not just randomly reset like you think it may be doing. It’s likely just a saving, recalling, type casting issue.

Also, I question if you are truly getting “1 pulse per watt-hour”. What generates the pulse? If it’s a mechanical switch, I guarantee your interrupt routine is being slammed with repeated calls. You can look at my pinewood derby code here and see how I prevented that from being an issue:

1 Like

@kennethlimcp

I will try the serial suggestion and the dfu-util, but I think its stored like it was retrieved, as the data in the volatile pulsearray is already 0.(there is a little bug there in the debug code, but I already fixed that, and saw the same result)

@bko,

Thanks, I will try your suggestion. But can you use a spark.publish in an ISR? I would expect this would cause some issues regarding reentrance if this function takes up too much time. Or does the publish function only adds things to a list to be pushed out?

@BDub,

I actually had the uint_16t typecast before, but removed it because I also did not see them in the write flash routine offered by the spark team.

I agree that the 4096, 256 etc. seems to be a saving/recalling issue. I will investigate a bit further in the coming days.

The hardware generating the pulse is a photodiode, so contact-bounce should not be an issue. There is an ever so slightly chance that the breadboard contacts is causing some interrupt triggering(it being the equivalent to a fricking antenna…) but I highly doubt that.

In any case, thanks for the response! will keep you posted.

Update: Fixed another debug-code bug, and yes… it is the flash store routine, not the millis routine… Perhaps an endian-ess problem? will try some more things…

@robindev How about this…just try a simple test. write sequence of 0…100 to the flash in the top of the loop. The read and display it in the loop. Does it work?

1 Like