ADC Pi Plus in C
4407 Views - Created 07/01/2016
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
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.
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.
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.
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.
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...
dpkg -L libi2c-dev
package diverts others to: /usr/include/linux/i2c-dev.h.kernel
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.
- 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,
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.
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.
The IO Pi and ADC Pi examples both use the library so if that is not available it would display those errors.
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.