Computing stuff tied to the physical world

10-bit ADC on LPC810 and 812

With our new-found insight on how to construct a delta-sigma ADC, we can now turn to the LPC81x series microcontrollers, which have two analog comparators built in.

We’ll also need a reference voltage to compare to, roughly at the mid-point of our measurement range. Luckily, that too is available, in the form of a programmable ladder network – which is just a tap on a bunch of internal resistors, all connected in series between Vcc and ground.

The task at hand is fairly simple:

  • compare the input and set the output either high or low
  • count how many 1’s we have generated, over a fixed number of cycles

As it turns out, this task can be handled by a fairly unique hardware peripheral inside several new microcontrollers from NXP. It’s called the “State Configurable Timer”.

There’s an application note (#11329) from NXP which describes the implementation, including full source code and quite a bit of background information. The essence of this has been extracted into a C++ source file adc_sct.h on GitHub.

The code is fairly impenetrable, but fortunately its use is not, as you can see in this demo:

#include "sys.h"
#include "adc_sct.h"

AdcSct<1> adc;  // use ACMP_I1

extern "C" void SCT_IRQHandler () { adc.sctIrqHandler(); }

int main () {
  tick.init(1000);
  serial.init(115200);

  printf("\n[sigmadc]\n");

  LPC_SWM->PINENABLE0 |= (3<<2);      // disable SWDIO and SWCLK
  LPC_SWM->PINASSIGN[8] = 0xFFFF02FF; // enable ACMP_O on PIO_2
  LPC_SWM->PINASSIGN[5] = 0x02FFFFFF; // enable CTIN_0 on PIO_2

  adc.init();

  while (true) {
    tick.delay(500);
    printf("%d\n", adc.result());
  }
}

But first, let’s build up the little circuit needed for our home-made ADC:

DSC 5014

The comparator input is fixed as pin 8 (PIO0_0), the digital out is set to pin 4 (PIO0_2).

This is using an LPC810, connected to an FTDI header (on the left) which allows uploading new code into it via USB, but which also includes the diodes necessary to allow re-using all the I/O pins for the application itself. Here is the final circuit, connected to a modified FTDI adapter on the left and a variable voltage source (lab power suppy) on the right:

DSC 5013

As it turns out, this circuit can interfere with actual uploads, so the top board needs to be taken off while re-programming the LPC810 chip. After that, it can be placed back on.

Here is some sample output on the serial port (reported twice per second):

[sigmadc]
1024
1024
623
625
625
636
635
637
637
637
636
508
379
379

Manually adjusting the power supply, and plotting the resulting values gives this graph:

Adc chart

As you can see, the ADC is working very nicely from 0.5 to 3.0V, with a nearly straight line. Better results will require more accurate measurement of the input voltage. For the low range, proper choice of resistor- and capacitor-values are likely to improve results further – the current setup just used a couple of very common values: both resistors are 10 kΩ, the capacitor is a 0.1 µF ceramic type.

The current implementation runs the delta-sigma cycle at 400 KHz (assuming the default 12 MHz µC clock), which translates to some 400 ADC readings per second, since we’re using 1024-fold oversampling. These settings are all defined in the “adc_stc.h” source code.

Just like 2 simple components can turn a PWM signal into a voltage, this shows that with no more than two resistors and one capacitor, voltages can measured digitally. Neat tricks.

[Back to article index]