Reading the ADCs with C Code

1,398 views
Skip to first unread message

Brendan Merna

unread,
Jul 13, 2015, 4:04:05 PM7/13/15
to beagl...@googlegroups.com

Hey Everyone,

I'm using the Beaglebone ADC on AIN0 (P9-39) to monitor a high voltage. I've used a divider (1/100) to put it within the 1.8V range of the ADC.I am using the cape overlay BB-ADC suggested by Derrick Molloy in Exploring BB. I've measured the voltage at the pin while using "cat /sys/devices/ocp.3/helper.12" and it agrees with my multimeter measurement at the pin. It seems the helper gives a direct mV value. They agree. Awesome!

I'm trying to use this same technique with my C code, but for some reason I'm getting weird values from my read function. I think it has something to do with reading two bytes from the 12 bit ADC converter. I'm thinking I'm getting some junk on the end or the beginning, but masking and getting rid of the first or last 4 bits does not get the number I received from the cat'ing the helper device.

Am I reading this wrong with my code?  Does anyone have any ideas to get the correct 12 bits?

Thanks! I think I gave enough information below.

Test Code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include "DDC2.h"


int main ( int argc, const char *argv[] )
{
float voltage;
voltage = atof ( argv[1] );
set_high_voltage ( voltage );
read_raw_high_voltage ( );
return 0;
}

Read Function:

/***********************************************************************
* Function- read_high_voltage
* Description- Reads the ADC on AIN0 and returns the measured value of the
* high voltage.
************************************************************************/
int read_raw_high_voltage(void)
{
uint16_t fd;
uint16_t value;
uint16_t value1;
uint16_t value2;
//Open "analog0=/sys/devices/ocp.3/helper.12/AIN0"
if ( ( fd = open ( analog0, O_RDONLY) ) < 0 )  
  {
      perror ("SPI: Can't open device.");
    return -1;
    }
    read ( fd, &value, 2);
    value1=value & 0x0FFF;
                        value2=value>>4;
                        printf ("All Bits=%d\n", value);
                        printf ("Bits 0-12=%d\n", value1);
                        printf ("Bits 4-16=%d\n", value1);
return(0);
}

From Command line:

./test 60

Output:

Voltage Given=60.0
All Bits= 14389
Bit 0-12=2101
Bit 4-16=899

Measured Voltage from Multimeter= 600mV (measured after 1/100 voltage divider)

Cat from the helper device = 587

Przemek Klosowski

unread,
Jul 13, 2015, 4:34:33 PM7/13/15
to beagl...@googlegroups.com
/sys/devices/ocp.3/helper.12/AIN0 returns the string '587'. In you C
code you are reading first two characters, '5' and '8', whose ASCII
codes are 0x38 and 0x35. You are collating them as an integer, whose
value indeed turns out to be 14389 (printf %x 14389 returns 3835).

You could use formatted reading (fscanf()), if you don't care for
speed; or google the way to get binary data from the ADC

Harvey White

unread,
Jul 13, 2015, 5:19:43 PM7/13/15
to beagl...@googlegroups.com
On Mon, 13 Jul 2015 13:04:05 -0700 (PDT), you wrote:

>
>Hey Everyone,
>
>I'm using the Beaglebone ADC on AIN0 (P9-39) to monitor a high voltage.
>I've used a divider (1/100) to put it within the 1.8V range of the ADC.I am
>using the cape overlay BB-ADC suggested by Derrick Molloy in Exploring BB.
>I've measured the voltage at the pin while using "cat
>/sys/devices/ocp.3/helper.12" and it agrees with my multimeter measurement
>at the pin. It seems the helper gives a direct mV value. They agree.
>Awesome!
>
>I'm trying to use this same technique with my C code, but for some reason
>I'm getting weird values from my read function. I think it has something to
>do with reading two bytes from the 12 bit ADC converter. I'm thinking I'm
>getting some junk on the end or the beginning, but masking and getting rid
>of the first or last 4 bits does not get the number I received from the
>cat'ing the helper device.
>
>Am I reading this wrong with my code? Does anyone have any ideas to get
>the correct 12 bits?

Several generic things may be bothering this:

1) you have interrupts enabled and you're getting a task switch during
the read. Solution: Make the read atomic.

2) the register order can be wrong. Some processors require a
specific order to read 8 bit registers. If this processor has that
same problem and you're not reading the entire register at one gulp,
then that can be a problem. This should be compensated for in the
compiler, though, so interrupts enabled could be more of a problem.

Harvey


>
>Thanks! I think I gave enough information below.
>
>*Test Code:*
>
>#include <stdio.h>
>#include <stdlib.h>
>#include <string.h>
>#include <stdint.h>
>#include <errno.h>
>#include <unistd.h>
>#include <fcntl.h>
>#include <poll.h>
>#include <sys/ioctl.h>
>#include <linux/spi/spidev.h>
>#include "DDC2.h"
>
>
>int main ( int argc, const char *argv[] )
>{
>float voltage;
>voltage = atof ( argv[1] );
>set_high_voltage ( voltage );
>read_raw_high_voltage ( );
>return 0;
>}
>
>*Read Function:*
>
>/***********************************************************************
>* Function- read_high_voltage
>* Description- Reads the ADC on AIN0 and returns the measured value of the
>* high voltage.
>************************************************************************/
>int read_raw_high_voltage(void)
>{
>uint16_t fd;
>uint16_t value;
>uint16_t value1;
>uint16_t value2;
>//Open "analog0=/sys/devices/ocp.3/helper.12/AIN0"
>if ( ( fd = open ( analog0, O_RDONLY) ) < 0 )
> {
> perror ("SPI: Can't open device.");
> return -1;
> }
> read ( fd, &value, 2);
> value1=value & 0x0FFF;
> value2=value>>4;
> printf ("All Bits=%d\n", value);
> printf ("Bits 0-12=%d\n", value1);
> printf ("Bits 4-16=%d\n", value1);
>return(0);
>}
>
>*From Command line:*
>
>./test 60
>
>*Output:*

TJF

unread,
Jul 15, 2015, 10:10:54 AM7/15/15
to beagl...@googlegroups.com
Hi Brendan!


Am Montag, 13. Juli 2015 22:04:05 UTC+2 schrieb Brendan Merna:
Does anyone have any ideas to get the correct 12 bits?

You could use libpruio for faster and easier ADC sampling, with better control over the subsystems configuration. Ie. check out the example 1.c

BR
Reply all
Reply to author
Forward
0 new messages