Author Topic: RFDuino and ADS1115 fast sampling  (Read 1214 times)

ya

  • RFduino Jr. Member
  • **
  • Posts: 20
  • Karma: +0/-0
    • View Profile
RFDuino and ADS1115 fast sampling
« on: August 30, 2016, 04:34:39 PM »
Hi,

I am working with RFDuino and sampling using ADS1115.
I found this post for fast sampling with the chip: https://forums.adafruit.com/viewtopic.php?f=25&t=43931
I made the changes to the library described in the post: delay for 1 ms and rate for 0xE0.
The changes improved the sampling rate from 27 sps to 34 sps (differential read => 68 sps per channel).
Similar setup with Arduino and 2 differential reads and some more code (not relevant for rate improvement) gives 130 sps (520 sps per channel).
The ADS1115 chip is rated for 860 sps. So, Arduino is close (kind of) giving the fact that I use some additional code there.
But RFDuino is nowhere near the specified rate.
I timed RFDuino by sending data to iPad via BLE. But I found that sending data itself is not an issue - without ads1115.readADC_Differential_0_1() and with RFduino_ULPDelay(1) I could get 901 sps which is close to 1 point per ms.
But with ads1115.readADC_Differential_0_1() rate drops to 34 sps.

Here is RFDuino code - modified "Temperature.ino" example - I use it with iPhone app from RF Digital:
Code: [Select]
#include <RFduinoBLE.h>
#include <Wire.h>
#include <Adafruit_ADS1015.h>

Adafruit_ADS1115 ads1115;

int Preading;
int i = 0;
bool flag;
float temp = 50;

void setup() {
  //start ADC
  ads1115.begin();
  //initialize serial communication for debugging
  override_uart_limit = true;
  Serial.begin( 115200 );
 
  // this is the data we want to appear in the advertisement
  // (if the deviceName and advertisementData are too long to fix into the 31 byte
  // ble advertisement packet, then the advertisementData is truncated first down to
  // a single byte, then it will truncate the deviceName)
  RFduinoBLE.advertisementData = "temp";

  // start the BLE stack
  RFduinoBLE.begin();
}

void RFduinoBLE_onConnect() {
  flag = true;
  Serial.println("Sending");
  // first send is not possible until the iPhone completes service/characteristic discovery
}

void RFduinoBLE_onDisconnect()
{
  flag = false;
  Serial.println("Disconnected");
  Serial.println(i);
  i = 0;
}

void loop() {
 

  if (flag)
  {
    // sample once per second
    //RFduino_ULPDelay( 1 );

    //get measurement
    measure();
    // send the sample to the iPhone
    RFduinoBLE.sendFloat(ADS1115_CONVERSIONDELAY);
  }
}

void measure()
{
    ads1115.readADC_Differential_0_1();
    i++;
}

What can be the problem with RFDuino?
My target is to get sampling close to what I see with Arduino - is this possible with RFDuino? Or there is some hardware limitation.
Thanks
« Last Edit: August 30, 2016, 04:38:06 PM by ya »

tolson

  • Global Moderator
  • *****
  • Posts: 838
  • Karma: +19/-0
    • View Profile
    • Thomas Olson Consulting
Re: RFDuino and ADS1115 fast sampling
« Reply #1 on: August 31, 2016, 10:43:48 AM »
I don't see how your example sketch shows anything about determining the samples per seconds rate the ADC is doing.
You are sending the constant ADS1115_CONVERSIONDELAY.
How about put a start=millis() before your call to measure() and a end=millis() after the send command. Subtract the two to
get the time it took to do the measurment and the transmission, and print that out.

Also note that you should comment out the Wire.begin() in the Adafruit library and put it specifically in your sketches setup().

tolson

  • Global Moderator
  • *****
  • Posts: 838
  • Karma: +19/-0
    • View Profile
    • Thomas Olson Consulting
Re: RFDuino and ADS1115 fast sampling
« Reply #2 on: August 31, 2016, 01:22:37 PM »
FYI, if  you read the library source code, it doesn't matter what the SPS setting is as the configuration uses the single shot mode. The SPS settings is just the speed that the chip itself can continuously take measurements and updates it's output register when it is in the continous mode. However, the library doesn't actually use that mode, so is non-sequitor. If you were to use that mode then the data would be updated at whatever SPS rate was configured. In continous mode the rate at which you grab that data is dependant on how fast the sketch can get around to reading that register.

The library is only doing single shot mode which means you have to wait for the output register to have valid data. There are two ways to do this. Either poll the conversion complete flag (ideal), or just do a static delay for longer that the longest possible time it might take to do the conversion. The library is doing the latter and defaults to 8ms for the ADS1115 and 1ms for the ADS1015. As your reference article indicated you could change this to 1ms by modifying the library.  How fast you can get around to doing a single shot request depends on what else is going on in your sketch.

If you want to get the most out of your ADC you might want to change the library to not use a static DELAY and instead actually poll the conversion complete flag. Then you will be playing with power. Or, you can change the library configuration so that the ADC is in continous conversion mode so that whenever you do ask for data, it will be the last valid conversion and your not waiting around for it.

Data single shot at 1ms an sending to BLE...

Quote
Tmeas= 1923us, SPS= 520, adc= 7967
Tmeas= 1586us, SPS= 630, adc= 7968
Tmeas= 2320us, SPS= 431, adc= 7968
Tmeas= 1983us, SPS= 504, adc= 7968
Tmeas= 1648us, SPS= 606, adc= 7968
Tmeas= 2319us, SPS= 431, adc= 7968
Tmeas= 2044us, SPS= 489, adc= 7968
Tmeas= 1740us, SPS= 574, adc= 7968
Tmeas= 2411us, SPS= 414, adc= 7968
Tmeas= 2106us, SPS= 474, adc= 7968
Tmeas= 1801us, SPS= 555, adc= 7968
Tmeas= 2411us, SPS= 414, adc= 7968
Tmeas= 1800us, SPS= 555, adc= 7968
Tmeas= 2502us, SPS= 399, adc= 7968
« Last Edit: August 31, 2016, 01:35:43 PM by tolson »

ya

  • RFduino Jr. Member
  • **
  • Posts: 20
  • Karma: +0/-0
    • View Profile
Re: RFDuino and ADS1115 fast sampling
« Reply #3 on: August 31, 2016, 02:52:43 PM »
Thank you for the response.
I actually just timed the program with stopwatch.

I added timer to the code (see below).
The output I am getting:

Code: [Select]
Sending
1739 us;   SPS: 575.00
2258 us;   SPS: 442.00
2228 us;   SPS: 448.00
2228 us;   SPS: 448.00
2227 us;   SPS: 449.00
2259 us;   SPS: 442.00
2258 us;   SPS: 442.00
2228 us;   SPS: 448.00
2258 us;   SPS: 442.00
2228 us;   SPS: 448.00
2258 us;   SPS: 442.00
2228 us;   SPS: 448.00
2258 us;   SPS: 442.00
2228 us;   SPS: 448.00
2227 us;   SPS: 449.00
2259 us;   SPS: 442.00
2228 us;   SPS: 448.00
2228 us;   SPS: 448.00
2198 us;   SPS: 454.00
3021 us;   SPS: 331.00
2350 us;   SPS: 425.00
2258 us;   SPS: 442.00
2228 us;   SPS: 448.00
2258 us;   SPS: 442.00
2228 us;   SPS: 448.00
2228 us;   SPS: 448.00
2258 us;   SPS: 442.00
2228 us;   SPS: 448.00
2350 us;   SPS: 425.00
20446 us;   SPS: 48.00
28992 us;   SPS: 34.00
29358 us;   SPS: 34.00
29083 us;   SPS: 34.00
29724 us;   SPS: 33.00
28870 us;   SPS: 34.00
29419 us;   SPS: 33.00
28961 us;   SPS: 34.00
29449 us;   SPS: 33.00
28992 us;   SPS: 34.00
29663 us;   SPS: 33.00
28778 us;   SPS: 34.00
29663 us;   SPS: 33.00
28991 us;   SPS: 34.00
29328 us;   SPS: 34.00
28991 us;   SPS: 34.00
29480 us;   SPS: 33.00
29022 us;   SPS: 34.00
29785 us;   SPS: 33.00
29358 us;   SPS: 34.00
28808 us;   SPS: 34.00
29266 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29266 us;   SPS: 34.00
29236 us;   SPS: 34.00
29266 us;   SPS: 34.00
29267 us;   SPS: 34.00
29205 us;   SPS: 34.00
29236 us;   SPS: 34.00
29235 us;   SPS: 34.00
29267 us;   SPS: 34.00
29267 us;   SPS: 34.00
29266 us;   SPS: 34.00
29206 us;   SPS: 34.00
29266 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29266 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29266 us;   SPS: 34.00
29236 us;   SPS: 34.00
29266 us;   SPS: 34.00
29236 us;   SPS: 34.00
29235 us;   SPS: 34.00
29266 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29267 us;   SPS: 34.00
29235 us;   SPS: 34.00
29236 us;   SPS: 34.00
29266 us;   SPS: 34.00
29297 us;   SPS: 34.00
29297 us;   SPS: 34.00
29113 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29235 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00
29236 us;   SPS: 34.00

As you see - at the beginning I am getting good sampling rates. But after 29th data point the sampling rate goes down to 34 sps.
What can be the problem?

Here is the updated script with timer (micros() instead of millis()):
Code: [Select]
#include <RFduinoBLE.h>
#include <Wire.h>
#include <Adafruit_ADS1015.h>

Adafruit_ADS1115 ads1115;

int i = 0;
int t, t1, t2;
float sps;
bool flag;
float temp = 50;

void setup() {
  //start ADC
  ads1115.begin();
  Wire.begin();
  //initialize serial communication for debugging
  override_uart_limit = true;
  Serial.begin( 115200 );
 
  // this is the data we want to appear in the advertisement
  // (if the deviceName and advertisementData are too long to fix into the 31 byte
  // ble advertisement packet, then the advertisementData is truncated first down to
  // a single byte, then it will truncate the deviceName)
  RFduinoBLE.advertisementData = "temp";

  // start the BLE stack
  RFduinoBLE.begin();
}

void RFduinoBLE_onConnect() {
  flag = true;
  Serial.println("Sending");
  // first send is not possible until the iPhone completes service/characteristic discovery
}

void RFduinoBLE_onDisconnect()
{
  flag = false;
  Serial.println("Disconnected");
  Serial.println(i);
  i = 0;
}

void loop() {
 

  if (flag)
  {
    // sample once per second
    //RFduino_ULPDelay( 1 );

    //set timer
    t1 = micros();
    //get measurement
    measure();
    // send the sample to the iPhone
    RFduinoBLE.sendFloat(float(t));
    //timer
    t2 = micros();
    t = t2-t1;
    sps = 1000000/t;
    Serial.print(t);
    Serial.print(" us;   SPS: ");
    Serial.println(sps);
  }
}

void measure()
{
   
    ads1115.readADC_Differential_0_1();
   
    i++;
}