Spark analog sample rate? (SOLVED)

Hi I just got my spark core kit - seems very good kit. I am a software person so not as familiar with the lights-and-wire part of things. Anyway I have a project in mind (basically a car RPM meter) and I want to check that the analog input sample rate will be high enough.

I read somewhere that the loop() is called a maximum of 200 times per second - but I need to sample at around 500 times per second to catch all the revs. It seems to be related to a 6ms delay between loop calls (I have not tested that - just comments from other users on this community)

I saw that the the Arduino can read at 10000 per second (http://arduino.cc/en/Reference/analogRead) so now I am confused if it will be possible?

Am I confusing loop() execution with analogRead rate?

Thanks for any (real world) experience in this area

the loop() is running in the Khz frequency and there shouldn’t be any issues with what you want to sample. :slight_smile:

Hi Kenneth - thanks for reply. I have now run a very simple test and got some slow results. I setup a simple counter in the loop and just got its count after 60 seconds. I tried three times and got an average of 12118 loops in 60 seconds. So that is 202 per second. I did not do a very precise measurement - just used my watch but it shows the general result.

My core has wifi enabled and online but my connection is not that fast.

My code is below - you can see it is really simple. Theer is a read on analog just so the loop is doing something real.

Am I missing something obvious? This is clearly not in the kHz range.

 int counter = 0;

void setup()
{
  // counter export value
  Spark.variable("counter", &counter, INT);
  
     //Register our Spark function here
   Spark.function("reset", resetCounter);

  //dummy read
  pinMode(A7, INPUT);


}

void loop() {

  int reading = 0;
//increment counter
counter = counter + 1;


//do a read
reading = analogRead(A7);

}

int resetCounter(String command) {
    
    counter = 0;
    return 1; //success
    
}

I was looking at this new commit comments:

I don’t have a core with me right now but try this on Serial?

 uint32_t counter = 0;

void setup()
{
   pinMode(A7, INPUT);
   Serial.begin(115200);
   while(!Serial.available()) Spark.process();  //Press any button to continue
}

unsigned long last_millis = millis();

void loop() {
  if(millis() - last_millis >= 60000){
     Serial.println(counter);
     last_millis = millis();
     counter = 0;
}
  else{
     counter++;
  }
}

Hi Kenneth. I think you are assuming I understand more about the core than I do :wink:
Anyway - here is what I think you want me to try:

  1. Connect to core via a Serial device (using USB?)
  2. run your code which is comparing timing marks and output counter every minute

I will come back to you as soon as possible but will probably be a couple of days

The link you send to github does seem to imply a fast loop rate = 69 kHz or 234 kHz depending on mode (whatever mode means …)

Thanks for help.

1 Like

@dave1, @kennethlimcpd, the speed of the loop() will be affected by whether the Core is connected to the cloud or not. Typically, with the cloud connected, the background task will require up to 5ms to run, thus slowing down loop() to about 200Hz on average. With the cloud connection disabled, the loop() will run much faster, primarily being affected by the servicing of WiFi interrupts and such. It is fair to say that loop() timing is variable and not “reliable”.

You may be better served by having timer interrupt driven sampling of the ADC though your top speed will be limited by the actual ADC sampling rate. Using DMA may also be possible where queued data could be serviced in loop() while data is gathered in the background. :smile:

Hi Peekay123
Thanks for confirming . I am not intending to use the loop() rate as my timer because it will not be “reliable” as it is no doubt doing many magical things underneath. My real concern was that the sample rate was going to be high enough to catch my signal. I expect my signal to be around 500 Hz so 200Hz would have been no good - but 60kHz would be fine.

I guess I will need to disable the cloud connection … or try and understand your second point about DMA…

Kenneth , Peekay123 - thanks for your help on this

Hi @dave1

I am not sure why you need a analog input for an RPM counter–usually a digital input would work fine since the sensor is a reed-switch or hall effect device and a magnet typically. 10000 rpm is only 166.6 Hz and 30000 rpm is 500 Hz so there is still quite a bit of room to move there. If you do have a digital input, there are lots of ways to use interrupts or an external counter to your advantage too.

And of course, if you can turn the cloud off, the loop speed goes way up, faster than a typical Arduino Uno.

1 Like

hi @bk0
I am just experimenting at the moment and digital may work. I am looking at RPM for old cars which do not have electronic ignition (juts points/breakers). They connect 4 times per revolution of distributor (which normally runs at half engine speed) - so effectively the signal is twice as fast as the actual RPM. I am hoping to measure the on/off duration as well as the actual RPM so I will need a sample rate 10 times (guess) the signal to make sure I get the general shape.

Anyway - first step is to be to get the signal… then see where to go from there.

Just hoping I do not accidentally put the high-tension part of the ignition circuit through my core (I am sure 10000 volts or more would not be good for it… :wink: Also 30000 RPM for my engine would result in many bits flying about …

Hi to all who helped me - thanks for inputs.

Just to finalise on this one in case it helps others - I found that I can easily achieve 25kHz loop rate if Spark.disconnect() is called.

In summary - with full online (ie default behavior) I got 202Hz. With Spark.disconnect() I got 25.7kHz loop rate

I am posting my test code in case it helps anyone

int counter = 0;

int onlineFlag = 1; 
int led2 = D7; // This one is the built-in tiny one to the right of the USB jack
unsigned long start_millis = 0;

void setup()
{



  // counter export value
  Spark.variable("counter", &counter, INT);
  
     //Register Spark function to reset counter
   Spark.function("reset", resetCounter);

  //dummy read
  pinMode(A7, INPUT);

pinMode(led2, OUTPUT);

    //init
    start_millis = millis();


}

void loop() {
    int reading = 0;
    
    unsigned long currTime = millis();

    unsigned long diffTime = currTime - start_millis;

    //check if been running for 60s
    if(diffTime >= 60000){
     
     //finished run
     digitalWrite(led2, LOW);   // Turn OFF the LED pins
     
         //reconnect
        if ( onlineFlag == 0) {
            Spark.connect();  
            Spark.process();
            onlineFlag = 1;
        } else {
         //already online - so nothing to do
        }
         
     } else {
         
         //test running logic
         
         //turn on LED
         digitalWrite(led2, HIGH); 
         
         

         //disconnect from spark.io - note that the main LED goes green (breathing)
         if (onlineFlag == 1) {
             Spark.disconnect();
             onlineFlag = 0;
         } else {
             //already diconnected
         }//endif


          

        //increment counter
        counter = counter + 1;


        //do a read (dummy read - I have nothing connected)
        reading = analogRead(A7);



         
     }//endif

}//endloop



//called by spark function - to reset to do another run
int resetCounter(String command) {
    
    start_millis = millis();
    counter = 0;
    return 1; //success
    
}
3 Likes