Unfortunately all the 17 pins of Raspberry Pi are digital which can either output HIGH or LOW. But by using a simple circuit (poor man's A/D converter) you can measure multiple level of values using a single GPIO pin. It consists of a basic “RC” charging circuit in which a Resistor in placed series with a Capacitor. The voltage across the capacitor rises when voltage is applied across the RC network. Using the formula [t = RC ] where t is the time,R is resistance in ohms,and C is capacitance in Farads and the time taken to register a HIGH on a GPIO pin we can roughly estimate the analog value.
Algorithm:-
Step 1: Set any GPIO pin as an output and set it Low.This ensures that no charge is present in capacitor and both the terminals are at 0V.
Step 2: Now set the GPIO pin as an input.This will starts a flow of current through the resistors and through the capacitor to ground. The voltage across the capacitor starts to rise. The time taken will be proportional to the input.
Step 3: Read the value from GPIO pin and keep incrementing a counter variable until the value is LOW.
Step 4: At some point the value from GPIO will register a HIGH. When it does return the value of the counter.
Step 5: Set the GPIO pin as an output and repeat the process as required.
Python Implementation:-
Example Circuit:-
Note:- The above technique will only work with sensors that act like resistors like photocells, thermistors, flex sensors, force-sensitive resistors, etc.
It cannot be used with sensors that have a pure analog output like IR distance sensors or analog accelerometers.
Source:- Adafruit
Algorithm:-
Step 1: Set any GPIO pin as an output and set it Low.This ensures that no charge is present in capacitor and both the terminals are at 0V.
Step 2: Now set the GPIO pin as an input.This will starts a flow of current through the resistors and through the capacitor to ground. The voltage across the capacitor starts to rise. The time taken will be proportional to the input.
Step 3: Read the value from GPIO pin and keep incrementing a counter variable until the value is LOW.
Step 4: At some point the value from GPIO will register a HIGH. When it does return the value of the counter.
Step 5: Set the GPIO pin as an output and repeat the process as required.
Python Implementation:-
#!/usr/local/bin/python # GPIO : RPi.GPIO v3.1.0a import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) # Define function to measure charge time def RC_Analog (Pin): counter = 0 # Discharge capacitor GPIO.setup(Pin, GPIO.OUT) GPIO.output(Pin, GPIO.LOW) time.sleep(0.1) GPIO.setup(Pin, GPIO.IN) # Count loops until voltage across capacitor reads high on GPIO while(GPIO.input(Pin)==GPIO.LOW): counter =counter+1 return counter # Main program loop while True: print RC_Analog(4) # Measure timing using GPIO4
Example Circuit:-
Note:- The above technique will only work with sensors that act like resistors like photocells, thermistors, flex sensors, force-sensitive resistors, etc.
It cannot be used with sensors that have a pure analog output like IR distance sensors or analog accelerometers.
Source:- Adafruit
In this post I will demonstrate how you can utilize a modest PICAXE micro-controller as a multi channel ADC.We would be utilizing I2C bus to access the PICAXE, which will dump the values to memory registers.Your Pi must be configured to use the I2C bus.You can refer to this post for setting up I2C.
Very few PICAXEs can act as an I2C slave.One of them is 28X1. I have collected some fundamental information about PICAXEs, but in the event that you have never utilized one before, I suggest you to get basic knowledge about PICAXE's (Google is your friend ;) ).
You will require a minimum working circuit for PICAXe with power,reset and download socket to proceed.Here I am connecting 4 potentiometer with the ADC channel of PICAXE to demonstrate the working.
You will need to download the below code into your PICAXE. Values from ADC is dumped into the micro-controller's scratchpad memory which can be accessed via I2C bus.
#no_data
#no_table
hi2csetup i2cslave, 100000
main:
readadc 0,b1
readadc 1, b2
readadc 2, b3
readadc 3, b4
put 1, b1
put 2, b2
put 3, b3
put 4, b4
goto main
Code for Raspberry Pi:-
I have created a python script to access the PICAXE's scratchpad memory over I2C bus.It reads and displays the values.Save the script as read_adc.py.
import smbus
import time
bus=smbus.SMBus(0)
add=0x10
def read(reg):
value=bus.read_byte_data(add, reg)
return value
adc_channel1=0
adc_channel2=0
adc_channel3=0
adc_channel4=0
while True:
adc_channel1=read(1)
adc_channel2=read(2)
adc_channel3=read(3)
adc_channel4=read(4)
print adc_channel1
print adc_channel2
print adc_channel3
print adc_channel4
time.sleep(0.3)
Testing:-
Run the script on your pi as-
[email protected]:~# sudo python read_adc.py
It should now display the ADC values in your screen!
Warning:- Use a voltage level shifter ( 5V <----> 3.3V ) when interfacing the PICAXE with Raspberry Pi, as Pi cannot tolerate 5V!.
(Update):- If you have a Raspberry Pi with a revision 2.0 board, you need to use I²C bus 1, not bus 0, so you will need to change the bus number used. In this case, the line bus=smbus.SMBus(0) would become bus=smbus.SMBus(1).
You can check that the device is present on the bus by using the i2cdetect program from the i2ctools package-
i2cdetect 0 -y or i2cdetect 1 -y
Tutorial credit: AntMan232