Hi,
I use Arduino Nano BLE 33/Sense (as Bluetooth Periperal) to sample a full rectified sine voltage wave and real-time send it through bluetooth, then bluetooth central (Such as: pad) can show the waveform realtime. In this project,I find an important issue.
To get high ADC sampling rate, I can’t use AnalogRead() which is too slow for my project. Instead, I code based on the sketch which Klaus_K provided in the post [Increase the ADC sample rate]. Thanks to Klaus_K!
However, I find a critial issue:
When I don’t connect Bluetooth, nRF52840 ADC works fine,I can achieve high accuracy based on the ADC sampling data. I plot it by using a Python script based on the data which a PC computer receive from Serial port of Arduino Nano BLE 33/Sense. Refer to Fig 1, it is a standard full-rectified sine wave (x axis: sample numbers; y axis: ADC value read by Arduino Nano BLE 33/Sense). Great! But when I connect Bluetooth, the wavform received from Bluetooth Central is distorted. It can not be achieve any accuracy for later computation at all. I dig into the code line by line. Eventually, I find if I just use BLE.begin(), the nRF52840 ADC sampling is interrupted, refer to Fig 2. Notice: the actual input waveform to Arduino Nano BLE A0 is good, refer to Fig 3, just the internal ADC sampling seems to be interrupted.
My questions are:
- is there any configuration wrong in the sketch for this application? (If I am lucky, I hope Klaus_K can be aware of this blog and help to review the codes configuration for ADC.)
- Is there any thing wrong (or conflict) with ArduinoBLE library and mbed library when both libraries are used?
- Is Arduino Nano BLE 33/Sense support ADC sampling and real-time Bluetooth commuincation? (I had been stopped by this issue for a couple of weeks. I am thinking If this issue can’t be solved, I have to use two Arduino Nano BLE boards: one Arduino Nano BLE 33/Sense as ADC, the other one for Bluetooth communication for this project, but certainly, this is not a beautiful design. I really want to make both ADC sampling and Bluetooth in one Arduino Nano BLE 33/Sense )
I really appreciate if anyone can help me out in this issue.
I provide code below. You can just comment/uncomment “if(BLE.begin()) { Serial.println( "Bluetooth initialized successfully!");}” to deplicate this issue.
To duplicate this issue, I proivde minimum code below. Again, I make a little change based on Klaus_K’s code. For the hardware connection, I use a circuit to convert a sine wave(the project require a input frequency: 30 ~ 300Hz, amplitude: +/-2.5V) to fully recified waveform, then input to A0 of Arduino Nano BLE 33. You can duplicate Fig 1 and Fig2 by using 30Hz Sine waveform. I also attach a 100Hz Sine waveform waveform. It seems ADC is interrupted by some action with higher priority, refer to Fig 4. I try to increase ADC priority: by change NVIC_setPriority(SAADC_IRQn, 1UL) to NVIC_setPriority(SAADC_IRQn, 0UL), however it doesn’t help. It seems Bluetotooth has higher priority, forecly disable any other interrupt(?). Notice; please do not use DC voltage to A0 to duplicate this issue, you won’t find this issue since DC voltage still can be plotted to a straight line even the ADC is interuppted.
OK. Any help, I really appreciate!!!
/*
This experimental code shows how to control the nRF52840 SAADC using a Timer and PPI.
The SAADC uses EasyDMA to copy each sample into a variable in memory.
The ADC samples pin A0.
Note:
- the maximum sampling rate is 200kSamples/s
- only one sample per second it printed
- this code has not been tested with a debugger, some samples might be lost due to mbedOS (needs further testing)
- this code will likely not work when using analogRead() on other pins
The circuit:
- Arduino Nano 33 BLE/ BLE Sense board.
This example code is in the public domain.
*/
// make some change on the original experimental codes to demonstrate the ADC interrupted issue by Bluetooth,2022/01/17 9:55AM
#include "mbed.h"
#include <ArduinoBLE.h>
#define SAMPLES_PER_SECOND 20000
#define PPI_CHANNEL (7)
#define ADC_BUFFER_SIZE 1
volatile nrf_saadc_value_t adcBuffer[ADC_BUFFER_SIZE];
volatile bool adcFlag = false;
volatile uint32_t sampleCounter = 0;
void setup()
{
Serial.begin( 115200 );
while ( !Serial );
Serial.println( "Arduino Nano 33 BLE (mbedOS) example: Timer -> PPI -> SAADC" );
if(BLE.begin())
{
Serial.println( "Bluetooth initialized successfully!");
}
initADC();
initTimer4();
initPPI();
}
void loop()
{
static uint32_t previousMillis = 0;
if ( adcFlag )
{
adcFlag = false;
// if ( sampleCounter >= SAMPLES_PER_SECOND )
if ( sampleCounter >= 1 )
{
// uint32_t sampleCount = sampleCounter;
// uint32_t currentMillis = millis();
// uint32_t runTime = currentMillis - previousMillis;
// Serial.print( "Samples: " );
// Serial.print( sampleCount );
// Serial.print( " run time: " );
// Serial.print( runTime );
// Serial.print( " ms A0: " );
Serial.println( adcBuffer[0] );
// previousMillis = currentMillis;
sampleCounter = 0;
}
}
}
extern "C" void SAADC_IRQHandler_v( void )
{
if ( NRF_SAADC->EVENTS_END != 0 )
{
NRF_SAADC->EVENTS_END = 0;
adcFlag = true;
sampleCounter++;
}
}
void initADC()
{
nrf_saadc_disable();
NRF_SAADC->RESOLUTION = NRF_SAADC_RESOLUTION_12BIT;
// P0.04 - AIN2 -> Pin A0
NRF_SAADC->CH[2].CONFIG = ( SAADC_CH_CONFIG_GAIN_Gain1_4 << SAADC_CH_CONFIG_GAIN_Pos ) |
( SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos ) |
( SAADC_CH_CONFIG_REFSEL_VDD1_4 << SAADC_CH_CONFIG_REFSEL_Pos ) |
( SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos ) |
( SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos ) |
( SAADC_CH_CONFIG_TACQ_3us << SAADC_CH_CONFIG_TACQ_Pos );
NRF_SAADC->CH[2].PSELP = SAADC_CH_PSELP_PSELP_AnalogInput2 << SAADC_CH_PSELP_PSELP_Pos;
NRF_SAADC->CH[2].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;
NRF_SAADC->RESULT.MAXCNT = ADC_BUFFER_SIZE;
NRF_SAADC->RESULT.PTR = ( uint32_t )&adcBuffer;
NRF_SAADC->EVENTS_END = 0;
nrf_saadc_int_enable( NRF_SAADC_INT_END );
NVIC_SetPriority( SAADC_IRQn, 1UL );
NVIC_EnableIRQ( SAADC_IRQn );
nrf_saadc_enable();
NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
while ( NRF_SAADC->EVENTS_CALIBRATEDONE == 0 );
NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
while ( NRF_SAADC->STATUS == ( SAADC_STATUS_STATUS_Busy << SAADC_STATUS_STATUS_Pos ) );
}
void initTimer4()
{
NRF_TIMER4->MODE = TIMER_MODE_MODE_Timer;
NRF_TIMER4->BITMODE = TIMER_BITMODE_BITMODE_16Bit;
NRF_TIMER4->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
NRF_TIMER4->PRESCALER = 0;
NRF_TIMER4->CC[0] = 16000000 / SAMPLES_PER_SECOND; // Needs prescaler set to 0 (1:1) 16MHz clock
NRF_TIMER4->TASKS_START = 1;
}
void initPPI()
{
NRF_PPI->CH[PPI_CHANNEL].EEP = ( uint32_t )&NRF_TIMER4->EVENTS_COMPARE[0];
NRF_PPI->CH[PPI_CHANNEL].TEP = ( uint32_t )&NRF_SAADC->TASKS_START;
NRF_PPI->FORK[PPI_CHANNEL].TEP = ( uint32_t )&NRF_SAADC->TASKS_SAMPLE;
NRF_PPI->CHENSET = ( 1UL << PPI_CHANNEL );
}
Fig 1. Singal Generator: 30Hz,+/-2.5V Sine waveform, after full rectified circuit, 60Hz full rectified sine wave to A0. Comment BLE.begin() in codes.
Fig 2. Singal Generator: 30Hz,+/-2.5V Sine waveform, after full rectified circuit, 60Hz full rectified sine wave to A0. Uncomment BLE.begin() in codes.
Fig 3. the actual waveform catched by oscilloscope. Blue waveform: 30Hz,+/-2.5V Sine waveform. Green waveform: 60Hz full rectified sine wave to Arduino A0
Fig 4.Singal Generator: 100Hz,+/-2.5V Sine waveform, after full rectified circuit, 200Hz full rectified sine wave to A0. Uncomment BLE.begin() in codes. The inerrupt seems periodic.



