Boron Low ADC Readings

Tags: #<Tag:0x00007fe222d42388>


That shouldn’t be required.
Have you tested with my code? I can’t make any of my Gen3 devices report anything but 4095 (occasionally 4094) with that code and a D2-A2 bridge :confused:


Yep I am using your code. I have 3 Borons doing the same thing. BUT I tested the same setup and code on an Argon and it works fine, 4095. Its hard for me to believe I have 3 bad Borons?


That is rather peculiar - maybe @marekparticle can take this one from here.

BTW, can you post a photo of your Boron setup?


Here is a picture of the setup. The USB cable is going to my MacBook Pro.


I see you have no antenna attached - if you have the cell module on you should not do that. These modules are not meant to be running without load on the output stage.


I actually did not know that. I do have SYSTEM_MODE(SEMI_AUTOMATIC); at the top of my code. Does this change things?


When the radio is not on (as in SEMI_AUTOMATIC) it shouldn’t matter.


I’m seeing similar results with a Boron LTE that was shipped recently.
All tests with Cellular Antenna Connected, USB powered, and Li-Po connected.

// Using 3V3 Pin Bridge
0000013954 [app] INFO: ADC: 4079
0000018955 [app] INFO: ADC: 4075
0000023955 [app] INFO: ADC: 4081
0000028956 [app] INFO: ADC: 4082
0000033957 [app] INFO: ADC: 4078
0000038957 [app] INFO: ADC: 4085
0000043958 [app] INFO: ADC: 4083
0000048958 [app] INFO: ADC: 4081
0000053959 [app] INFO: ADC: 4079
0000058959 [app] INFO: ADC: 4079
0000063960 [app] INFO: ADC: 4081
0000068961 [app] INFO: ADC: 4078

// Using D2 Pin Bridge
0000035008 [app] INFO: ADC: 4081
0000040009 [app] INFO: ADC: 4088
0000045009 [app] INFO: ADC: 4079
0000050010 [app] INFO: ADC: 4082
0000055010 [app] INFO: ADC: 4074
0000060011 [app] INFO: ADC: 4071
0000065012 [app] INFO: ADC: 4087
0000070012 [app] INFO: ADC: 4085
0000075013 [app] INFO: ADC: 4079
0000080013 [app] INFO: ADC: 4081
0000085014 [app] INFO: ADC: 4076


Huh? :flushed:

That’s something @marekparticle and @oddwires1 may want to chime in on - that seems rather wrong to me.


Hi @Particle9 - sorry to be getting to you so late, had a break for the holiday weekend (thanks for the ping, @ScruffR). I can’t reproduce this on my own device, so it looks like something must be up hardware-wise. Would you mind creating a support ticket ( and we can determine whether or not a replacement is in order?


@marekparticle, I’m reproducing this with “replacement” Boron’s that were recently shipped to me.
Note: This ADC error isn’t a concern for me personally, but I wanted you to be aware.
Do you have a Boron from a recent production run to try ?

I switched to A3 Pin, and disconnected the Li-Po during the test, no significant change:

// A3 to 3V3 Pin Bridge
0000014060 [app] INFO: ADC: 4088
0000019060 [app] INFO: ADC: 4079
0000024061 [app] INFO: ADC: 4088
0000029062 [app] INFO: ADC: 4079
0000034062 [app] INFO: ADC: 4077
// Disconnected the Li-Po, Boron was Re-Charging previously
0000039063 [app] INFO: ADC: 4075
0000044063 [app] INFO: ADC: 4078
0000049064 [app] INFO: ADC: 4088
0000054065 [app] INFO: ADC: 4082
0000059065 [app] INFO: ADC: 4074


@rickkas7 - should we expect any variance from 4095 when analogRead()ing a pin grabbing 3.3V from itself?


@marekparticle, the ADC reference is the 3.3v rail so measuring 3.3v on an analog pin should result in only a one bit error at most.


@peekay123, understood. But, I’m struck by the fact that this has occurred on more than one Boron. I… must be missing something.


@marekparticle, it is incredibly odd. It may be worth looking at the 3.3v rail to make sure it is clean. It might be worth testing with a known-clean external 3.3v source. You may also want to look at the boards for any manufacturing anomalies like excess flux, etc. My understanding is that all things being equal (DeviceOS, app), “older” Borons work fine but now these “new” ones. So software issues can most likely be eliminated.


@Rftop - can you PM me device IDs so I can check mfg date?


I tried this out on a Boron LTE running 1.4.2. I connected A2 to 3V3 and the values are not 4095.

0000012309 [app] INFO: ADC: 4090
0000019311 [app] INFO: ADC: 4087
0000026312 [app] INFO: ADC: 4092
0000033314 [app] INFO: ADC: 4094
0000040316 [app] INFO: ADC: 4087
0000047318 [app] INFO: ADC: 4091
0000054319 [app] INFO: ADC: 4093
0000061321 [app] INFO: ADC: 4092
0000068323 [app] INFO: ADC: 4094
0000075325 [app] INFO: ADC: 4089
0000082326 [app] INFO: ADC: 4095
0000089327 [app] INFO: ADC: 4087

This was also the case with the other ADC inputs, and also using D2 as an output.

By the way, using a GPIO as a voltage reference is not guaranteed to work with the nRF52, because the output voltage spec says VOH,SD can be from VDD-0.4 to VDD volts. In other words, GPIO HIGH may not be exactly VDD.

However, after forcing the calibration of the nRF52 SAADC, I got much better values. There were a few outliers, but they were generally close to 4095 and less frequent:

0000003070 [app] INFO: calibration complete
0000003072 [app] INFO: A2=4095
0000004074 [app] INFO: A2=4095
0000005076 [app] INFO: A2=4095
0000006077 [app] INFO: A2=4094
0000007079 [app] INFO: A2=4095
0000008080 [app] INFO: A2=4095
0000009082 [app] INFO: A2=4079
0000010084 [app] INFO: A2=4095
0000011085 [app] INFO: A2=4095
0000012087 [app] INFO: A2=4093
0000013088 [app] INFO: A2=4095
0000014090 [app] INFO: A2=4095
0000015091 [app] INFO: A2=4095
0000016093 [app] INFO: A2=4095
0000017095 [app] INFO: A2=4095
0000018097 [app] INFO: A2=4095
0000019099 [app] INFO: A2=4095
0000020101 [app] INFO: A2=4095
0000021102 [app] INFO: A2=4095
0000022104 [app] INFO: A2=4093
0000023106 [app] INFO: A2=4095

Here’s the code:

#include "Particle.h"

#include "nrfx_saadc.h"

SerialLogHandler logHandler;


void adcCalibrate();

void setup() {

	// Wait for a USB serial connection for up to 10 seconds
	waitFor(Serial.isConnected, 10000);

	// Calibrate the ADC at startup. You might want to do this after large temperature
	// changes as well.

void loop() {
	int a2 = analogRead(A2);"A2=%d", a2);

static void adcCallback(nrfx_saadc_evt_t const *event) {
	// We just poll for done during calibration instead of using this event but the
	// callback still needs to be defined.

void adcCalibrate() {
	nrfx_err_t err;

	// IMPORTANT: You must detach the IRQ handler from the system firmware and re-attach it to
	// user firmware, or this won't work right.
	attachInterruptDirect(SAADC_IRQn, nrfx_saadc_irq_handler, false);

	nrfx_saadc_config_t saadcConfig = NRFX_SAADC_DEFAULT_CONFIG;
	saadcConfig.low_power_mode = false;
	saadcConfig.resolution = NRF_SAADC_RESOLUTION_12BIT;
	saadcConfig.oversample = NRF_SAADC_OVERSAMPLE_DISABLED;
	saadcConfig.interrupt_priority = APP_IRQ_PRIORITY_LOW;

	// Initialize SAADC
	err = nrfx_saadc_init(&saadcConfig, adcCallback);
	if (err) {
		Log.error("nrfx_saadc_init err=%lu", err);

	// Now calibrate it. This does not require a channel be initialized first.
	err = nrfx_saadc_calibrate_offset();
	if (err == NRFX_SUCCESS) {
		while(nrfx_saadc_is_busy()) {
		}"calibration complete");
	else {"calibrate failed err=%lu", err);

We should probably put ADC calibration right into Device OS, but this is probably a reasonable thing to play around with and see if it helps in your case to be sure that’s what the problem is.


@rickkas7 @marekparticle
I tried the code on two different Borons and still am getting mixed results:
Boron #1
0000002139 [app] INFO: A2=4028
0000003140 [app] INFO: A2=4023
0000004141 [app] INFO: A2=4026
0000005143 [app] INFO: A2=4029
0000006144 [app] INFO: A2=4026
0000007146 [app] INFO: A2=4028
0000008147 [app] INFO: A2=4019
0000009148 [app] INFO: A2=4026
0000010149 [app] INFO: A2=4023
0000011150 [app] INFO: A2=4025
0000012152 [app] INFO: A2=4024
0000013153 [app] INFO: A2=4020
0000014155 [app] INFO: A2=4023

Boron #2
0000002058 [app] INFO: A2=4067
0000003059 [app] INFO: A2=4067
0000004060 [app] INFO: A2=4070
0000005061 [app] INFO: A2=4072
0000006062 [app] INFO: A2=4067
0000007064 [app] INFO: A2=4070
0000008065 [app] INFO: A2=4068
0000009066 [app] INFO: A2=4066
0000010067 [app] INFO: A2=4063
0000011069 [app] INFO: A2=4065
0000012070 [app] INFO: A2=4066



Is it printing out the calibration complete message before outputting the samples? Or is there an error code? It looks like it didn’t successfully calibrate.


I cut that piece of the output by accident. I just ran it again:
0000009280 [app] INFO: calibration complete
0000009282 [app] INFO: A2=4066
0000010283 [app] INFO: A2=4067
0000011284 [app] INFO: A2=4065
0000012286 [app] INFO: A2=4070
0000013287 [app] INFO: A2=4064
0000014288 [app] INFO: A2=4069
0000015289 [app] INFO: A2=4068
0000016291 [app] INFO: A2=4063
0000017292 [app] INFO: A2=4066

Any ideas?