Support Forum

Share your projects and post your questions

Register   or   Sign In
The Forum

ADC Pi Plus in C

4407 Views - Created 07/01/2016

07/01/2016

Posted by:
stefanovic

stefanovic Avatar

Hello,
I tried the code down in https://github.com/abelectronicsuk/ABElectronics_C_Libraries, but when I compile adcpi.c as indicated:
gcc adcpi.c -o adcpi
I get:
gcc adcpi.c -o adcpi/tmp/ccQGRaUs.o: In function `getadc':adcpi.c:(.text+0x210): undefined reference to `i2c_smbus_write_byte'adcpi.c:(.text+0x22c): undefined reference to `i2c_smbus_read_i2c_block_data'collect2: ld returned 1 exit status
I also tried the demos in tje IOPi directory, but only obtained:
Failed to write to i2c device for write
I'm seeking for a simple C example that works with multiple pin reads. I successfully read one pin using the method described here: http://hertaville.com/2013/04/01/interfacing-an-i2c-gpio-expander-mcp23017-to-the-raspberry-pi-using-c/
...basically an ioctl with I2C_RDWR. However, I cannot use the same code to read a second pin: I always get the same value for both pins, the value of the last pin I query. I tried to insert a delay between the two reads to no avail.
Any tips?
Thx !
Stéphane

07/01/2016

Posted by:
andrew

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

Hi Stéphane

The errors you are getting could mean that the code can not access the I2C port on the Raspberry Pi. The IO Pi and ADC Pi examples both use the library so if that is not available it would display those errors.

Please can you try going through our I2C tutorial and check that everything on your Linux install is configured correctly. If you are not using python then you should be able to miss Step 3 in the tutorial.

07/01/2016

Posted by:
stefanovic

stefanovic Avatar

Well actually if <linux/i2c-dev.h> were not installed it would not compile at all. Here it compiles, but does not link. And as I said, I successfully wrote, compiled, linked and ran some code that reads a potentiometer value, so everything is installed correctly IMO. But I can't make it read two values. Hence I'm looking for other examples that do it in order to copy it...

07/01/2016

Posted by:
andrew

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

I am out of the office at the moment so I don't have access to a Raspberry Pi to test the adcpi.c code but first thing tomorrow I will try to find out why the code is not working.

Most of our customers use Python to communicate with our boards which is why we don't currently have a proper C library for the ADC Pi Plus but I will try and work on one over the next few days and post here once it is working.

In the meantime, it may be worth looking at our Arduino ADC library to see how it talks to the MCP3424 ADC chip. The code will need a few modifications to make it work on the Raspberry Pi, basically, replace anything related to the Wire library with the Raspberry Pi equivalent but it may give you a better idea of how to communicate with the ADC chip.

07/01/2016

Posted by:
stefanovic

stefanovic Avatar

ok thanks, meanwhile I'll stick with one value only, that will do for the next few days...

08/01/2016

Posted by:
andrew

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

Hi Stéphane
I just want to give you a quick update on my progress so far.
I have tried compiling the adcpi.c code on a fresh install of Raspian Jessi and it compiled and ran ok returning different values for each channel. Before compiling it I enabled I2C using the steps in our I2C tutorial and installed libi2c-dev. After compiling I ran the code with ./adcpi 1 and it returned voltages for channel 1. I repeated this for channels 2 and 3 and it worked on those channels as well. Both the adcpi code and the IO Pi library use the i2c_smbus functions so it might be worth checking that you have smbus installed.
Can you try running sudo apt-get install python-smbus and sudo apt-get install i2c-tools and check that both packages are installed?
I will continue working on a new ADC Pi C library and let you know once it is ready.

08/01/2016

Posted by:
stefanovic

stefanovic Avatar

ok thanks. My raspbian is wheezy... Do not know if that makes a difference. I'll check I have smbus installed as soon as I can get my hands on a rpi...

09/01/2016

Posted by:
stefanovic

stefanovic Avatar

actually the python examples were already running, and python-smbus is already installed, and I guess any smbus related stuff on which python-smbus depends.
what puzzles me is that this is a link error, and the compile command does not specify any extra lib to link against. It suggests that the smb functions are embedded in an automatically linked lib, such as libc or whatnot. Could you figure out which lib embed those functions? I tried to read to code of the python-smbus extension, but I have not find anything yet...

09/01/2016

Posted by:
andrew

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

The adcpi.c code was written by one of our users so I am not sure exactly how it works or what it links to but I just did a quick google for the error you are getting and one response on this forum that seems to work is to check that libi2c-dev is installed as that may be the library that i2c_smbus_write_byte is referencing.

09/01/2016

Posted by:
stefanovic

stefanovic Avatar

I saw this post as well, but there is only a header file in it:
dpkg -L libi2c-dev
/usr
/usr/share
/usr/share/doc
/usr/share/doc/libi2c-dev
/usr/share/doc/libi2c-dev/dev-interface.gz
/usr/share/doc/libi2c-dev/copyright
/usr/share/doc/libi2c-dev/changelog.Debian.gz
/usr/share/doc/libi2c-dev/changelog.gz
/usr/include
/usr/include/linux
/usr/include/linux/i2c-dev.h
package diverts others to: /usr/include/linux/i2c-dev.h.kernel

09/01/2016

Posted by:
andrew

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

Do you have a spare SD card you could install a clean version of Wheezy or Jessi on just in case one of the libraries on your install is corrupted?

09/01/2016

Posted by:
andrew

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

I have uploaded a new ADC Pi library to GitHub. As C is not object-orientated I had to change the way the library works compared to the Python version. Instead of initialising the ADC and setting the bit rate and other settings individually you just have to provide them as parameters with the readvoltage function.

If you want to read from pin 1 on the ADC Pi which is normally on I2C channel 0x68 you would use read_voltage(0x68,1, 18, 1, 1)); which sets the I2C address to 0x68, chip channel to 1, bit rate to 18, gain to 1 and the conversion mode to 1. Unless you are using the ADC Pi Plus in a project that needs to be very low current consumption it is best to set the conversion mode to 1 which is continuous conversion as this allows the ADC to sample the pins continuously and returns the voltage faster.

Hopefully, it should compile and run ok on your Raspberry Pi but if you have any problems or find any bugs please let me know.

10/01/2016

Posted by:
stefanovic

stefanovic Avatar

Yes, it works flawlessly! Thank you for this work, your support and your commitment (actually I did not expect you to work during the weekend, I hope you were not feeling obligated to do so...)
3 questions:
- can you point me to an explanation of the 'bit rate', the 'gain' and the 'conversion' parameter?
- do you have an idea of the time needed to read a value?
- would it be possible if this time is relatively long to write code using something like select(2) (to make a difference between requesting a value as opposed to actually getting it and being able to read it?
Thank you again,
Stéphane

11/01/2016

Posted by:
andrew

andrew Avatar

Location:
United Kingdom

andrew Twitter  andrew Website  

I'm glad you managed to get it working.

The bit rate is the resolution or the number of bits the ADC uses to sample the voltage. The MCP3424 IC used on the ADC Pi Plus can support 12-bit, 14-bit, 16-bit and 18-bit modes. Basically, the higher the bit rate the more accurate the reading will be but at the expense of taking longer to read each sample. You can find a more detailed description of the different bit rates in our knowledge base article. Due to the way the ADC Pi Plus is designed one of the bits is never used so the actual resolution in each mode is 11 bits, 13 bits, 15 bits and 17 bits but for setting the bit rate in the code use the values of 12, 14, 16 or 18.

In 18-bit mode, the ADC can return 3.75 samples per second. In 16-bit mode, the ADC returns 15 samples per second, 14-bit mode is 60 samples per second and in 12-bit mode is 240 samples per second. When you take a reading using the readvoltage function the code will request a sample from the ADC and then wait in a while loop until the sample is ready. This can take anywhere from around 4ms in 12-bit mode to around 270ms in 18-bit mode and the code will hang until the sample is ready.

The gain value controls the internal programable gain amplifier. This basically multiplies the voltage at the input to increase the resolution and the accuracy of the reading. The gain amplifier supports four settings, 1, 2, 4 and 8 which are the multiplication factors for each mode. If you put 1V into the input when the gain is set to 1 the ADC would only use around a quarter of the sample space for the reading but if you set the gain to 4 the voltage is multiplied so 1V would be measured by the ADC as 4V which will take up four times as much sample space and therefore give you a reading which is 4 times more accurate.

When using the gain amplifier you have to make sure your input voltage does not exceed the limits of the ADC.

With a gain of 1, you can use a maximum voltage of 5V.

With a gain of 2, you can use a maximum voltage of 2.5V.

With a gain of 4, you can use a maximum voltage of 1.25V.

With a gain of 8, you can use a maximum voltage of 0.625V.

If you set the gain to 8 and then put 1V into the ADC this would be multiplied by the amplifier to 8V and would damage the ADC so you need to know what the maximum voltage your circuit will produce and then set the gain so the voltage will not exceed this.

When you change the gain the ADC library automatically compensates for the new setting so if you have the gain set to 4 and put 1V into the input the read_voltage() function will return 1V even though the ADC is actually measuring 4V internally.

The conversion parameter is for the conversion mode inside the ADC. The MCP3424 has two possible conversion modes, one-shot and continuous.

In one-shot mode the ADC will sit in a sleep state until it receives a command to take an ADC measurement, it will then wake up, take the measurement and then go back to sleep. In continuous conversion mode the ADC is awake all of the time and continuously samples the ADC channel which was last selected.

When the ADC is asleep it uses very little power but waking up takes a small amount of time so ADC measurements will take slightly longer than in continuous mode. As continuous conversion mode samples the same ADC channel repeatedly if you are only reading from a single channel using this mode can in some instances reduce the amount of time it takes to take a reading but at the expense of using a tiny bit more power.

The datasheet for the MCP3424 ADC has a more detailed description of how all of the features work and may be worth reading if you want a better understanding of what is going on inside the chip.

The ADC Pi library can only read from one input at a time and while it is doing this the program will wait for a reply so if your program needs to be doing something else at the same time the best way to get around this problem would be to use threading and have the ADC readings done in a separate thread. Unfortunately, I don't have any experience of using threading in C as most of the programming I do in C is on microcontrollers which don't have multithreading in the normal desktop OS sense so I am afraid this is something I can not help you with.

If you have any other questions about the library or the ADC Pi please let me know.

11/01/2016

Posted by:
stefanovic

stefanovic Avatar

Thank you again for this very comprehensive answer, I think I got all of it.
I thought about using threading if need be, I'll investigate this solution if performance matters. However, a select(2)-based solution would be better. Anyway I think 12 bits is enough for my needs, I tried it, it's definitly faster.

21/04/2016

Posted by:
NobeRinker

NobeRinker Avatar

Location:
Canada

The errors you are getting could mean that the code can not access the I2C port on the Raspberry Pi.

The IO Pi and ADC Pi examples both use the library so if that is not available it would display those errors.

Sign in to post your reply

Note: documents in Portable Document Format (PDF) require Adobe Acrobat Reader 5.0 or higher to view, download Adobe Acrobat Reader or other PDF reading software for your computer or mobile device.