The PCF8591 is a fairly inexpensive I2C ADC/DAC chip, with four 8-bit ADC inputs and one 8-bit DAC output.
It often comes on breakout boards. The boards, like eg. this one, sometimes come with example devices, here eg. a trimpot, a thermistor, and a photoresistor, on the inputs, and a red LED on the output. The LED doesn't light up below about half of the output range.
Python library is available.
For reading from shell scripts, especially on underpowered boards like Raspberry Pi 1, python is less suitable due to the overheads at process startup. Insane amount of files has to be read and interpreted. A frequently executed task will bring a significant load on the machine.
A simple C code was derived from the sw_chip_PCF8591 one.
As the sensor doesn't do conventional registers, and only bare reads and writes are used (so eg. i2cdump will show just all zeroes and confuse the register settings), the barest of interfacing will do. File and IOCTL access to /dev/i2c-something was therefore chosen.
The chip operates in a simple way. Send a one-byte configuration, optionally with another byte (or bytes) to be written to the DAC output. Read raw bytes from the ADC, from a fixed channel or from autoincrementing sequence of individual inputs.
The code first opens the I2C device (or fails when device doesn't exist or is inaccessible). IOCTL I2C_SLAVE is executed on the resulting file handle, with the chip's address as parameter.
The config byte is sent (code fails here if the chip is not on the given address), optionally followed with DAC value.
Then several reads are issued. First byte is an old value from previous read.
If executed without options, it queries first BH1750 sensor on the /dev/i2c-1 bus. This is a default configuration on raspberry pi boards.
PCF8591 sensor read Usage: pcf8591 [-v] [-x] [-O] [-o <DACval>] [-c <chan>] [-a <addr>] [-d <dev>] ADC: -c <num> display ADC channel (0..3), all if not specified -m <num> set the input mux (0..3) (bits 4,5 of config; default 0, four separate inputs) -x hex output -j json format DAC: -O force DAC output (do not unset when DAC value not specified) -o <num> set DAC value (0..255) I2C: -a <num> address, 0..7, default=0; adds to base address 0x48 -d <dev> specify I2C device, default /dev/i2c-1 general: -v verbose mode -h,--help this help
If all is okay, result code is 0. Otherwise, if something crashes, result is 1.
If not verbose or help, only the measured value of the selected channel, or all four separated by space, is spat to stdout.
read all four channels (0..3)
The code doesn't need any special compilation. A simple call will do: