├── INSTALL.txt ├── LICENSE ├── PiAnalog.py ├── README.md ├── examples ├── .AppleDouble │ ├── .Parent │ ├── gui.py │ ├── pi_vt_test.py │ ├── resistance_meter.py │ ├── test_button.py │ ├── test_led.py │ └── thermometer.py ├── pi_vt_test.py ├── resistance_meter.py └── thermometer.py ├── hardware ├── .AppleDouble │ └── .Parent ├── breadboard.png └── schematic.png └── setup.py /INSTALL.txt: -------------------------------------------------------------------------------- 1 | To install the module (only tested on Python2) 2 | 3 | $ sudo python setup.py install 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Simon Monk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PiAnalog.py: -------------------------------------------------------------------------------- 1 | import RPi.GPIO as GPIO 2 | import time, math 3 | 4 | class PiAnalog: 5 | 6 | a_pin = 18 7 | b_pin = 23 8 | C = 0.0 9 | R1 = 0.0 10 | Vt = 0.0 11 | Vs = 0.0 12 | T5 = 0.0 13 | 14 | def __init__(self, C=0.33, R1=1000.0, Vt = 1.346, Vs = 3.25): 15 | GPIO.setmode(GPIO.BCM) 16 | GPIO.setwarnings(False) 17 | self.C = C 18 | self.R1 = R1 19 | self.Vt = Vt 20 | self.Vs = Vs 21 | self.T5 = (C * R1 * 5) / 1000000.0 22 | 23 | # empty the capacitor ready to start filling it up 24 | def discharge(self): 25 | GPIO.setup(self.a_pin, GPIO.IN) 26 | GPIO.setup(self.b_pin, GPIO.OUT) 27 | GPIO.output(self.b_pin, False) 28 | time.sleep(self.T5) # 5T for 99% discharge 29 | 30 | # return the time taken for the voltage on the capacitor to count as a digital input HIGH 31 | def charge_time(self): 32 | GPIO.setup(self.b_pin, GPIO.IN) 33 | GPIO.setup(self.a_pin, GPIO.OUT) 34 | GPIO.output(self.a_pin, True) 35 | t1 = time.time() 36 | while not GPIO.input(self.b_pin): 37 | pass 38 | t2 = time.time() 39 | return (t2 - t1) * 1000000 # microseconds 40 | 41 | # Take an analog reading as the time taken to charge after first discharging the capacitor 42 | def analog_read(self): 43 | self.discharge() 44 | t = self.charge_time() 45 | self.discharge() 46 | return t 47 | 48 | # Convert the time taken to charge the cpacitor into a value of resistance 49 | # To reduce errors in timing, do it a few times and take the median value. 50 | def read_resistance(self): 51 | n = 7 52 | readings = [] 53 | for i in range(0, n): 54 | reading = self.analog_read() 55 | readings.append(reading) 56 | readings.sort() 57 | t = readings[int(n / 2)] 58 | T = -t / math.log(1.0 - (self.Vt / self.Vs)) 59 | RC = T 60 | r = (RC / self.C) - self.R1 61 | return r 62 | 63 | def read_temp_c(self, B=3800.0, R0=1000.0): 64 | R = self.read_resistance() 65 | t0 = 273.15 # 0 deg C in K 66 | t25 = t0 + 25.0 # 25 deg C in K 67 | # Steinhart-Hart equation - Google it 68 | inv_T = 1/t25 + 1/B * math.log(R/R0) 69 | T = (1/inv_T - t0) 70 | return T 71 | 72 | def read_temp_f(self, B=3800.0, R0=1000.0): 73 | return self.read_temp_c(B, R0) * 9 / 5 + 32 74 | 75 | 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pi_analog Python library for using resistive sensors with a Raspberry Pi 2 | 3 | ## Installation 4 | 5 | Run the following commands to install the library: 6 | 7 | ``` 8 | $ git clone https://github.com/simonmonk/pi_analog.git 9 | $ cd pi_analog 10 | $ sudo python3 setup.py install 11 | ``` 12 | 13 | If you want to use the library with python2 change _python3_ in the last coommand above into _python_. 14 | 15 | ## Hardware 16 | 17 | The library assumes that you have the hardware setup like this: 18 | 19 | ![Schematic](https://github.com/simonmonk/pi_analog/blob/master/hardware/schematic.png?raw=true) 20 | 21 | Which you could build on a breadboard using a photoresistor as a sensor like this: 22 | 23 | ![Breadboard](https://github.com/simonmonk/pi_analog/blob/master/hardware/breadboard.png?raw=true) 24 | 25 | The Monk Makes Electronics Starter Kit for Raspberry Pi (https://www.monkmakes.com/rpesk2) includes all the components you need to make the example above and also includes a thermistor for temperature measurement. 26 | 27 | 28 | 29 | ## Example Usage 30 | 31 | You will find a few examples on how to use the library in the examples folder. The simple example just displays the resistance value of the sensor every second. 32 | 33 | ``` 34 | from PiAnalog import * 35 | import time 36 | 37 | p = PiAnalog() 38 | 39 | while True: 40 | print(p.read_resistance()) 41 | time.sleep(1) 42 | ``` 43 | 44 | 45 | The library also includes methods for using Thermistors. So if you have a 1k thermistor with a Beta of 3800, you could use the following code to measure the temperature in degrees C. 46 | 47 | ``` 48 | from PiAnalog import * 49 | import time 50 | 51 | p = PiAnalog() 52 | 53 | while True: 54 | print(p.read_temp_c(3800, 1000)) 55 | time.sleep(1) 56 | ``` 57 | 58 | If you want to use different calues of C1 and R1, then you can supply them as parameters to the constructor like this: 59 | 60 | ``` 61 | p = PiAnalog(0.01, 10000) 62 | ``` 63 | 64 | The example above for a 10nF (0.01uF) capaciotor and a 10k resistor. 65 | 66 | 67 | ## How it Works 68 | 69 | This technique relies on the ability of GPIO pins to switch between being an input and an output while the controlling program is running. The basic sequence of events in taking a measurement is as follows: 70 | 71 | 1. Make pin A an input. Make pin B an output and LOW and wait until the capacitor is discharged 72 | 2. Make a note of the time. Make pin B and input and pin A a HIGH output. C1 will now start to charge. 73 | 3. When the voltage across C1 reaches about 1.35V it will stop being a LOW input and be measures as HIGH by the GPIO pin connected to B. The time taken for this to happen is a measurement of the resistance of the sensor and R1. 74 | 75 | 76 | The code in PyAnalog.py is pretty well commented, so take a look if you are curious. 77 | 78 | The key formula is: 79 | 80 | T = -t / (ln(1-(Vt / Vs)) 81 | 82 | Where: 83 | * The time constant T is also (R1 + Rsensor) * C1 84 | * t is the time at which the voltage of C1 reaches Vt 85 | * Vt is the voltage at which a digital input counts as HIGH on a Raspberry Pi GPIO pin (about 1.35V) 86 | * Vs is the supply voltage for the charging pin (always 3.3V) 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/.AppleDouble/.Parent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/examples/.AppleDouble/.Parent -------------------------------------------------------------------------------- /examples/.AppleDouble/gui.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/examples/.AppleDouble/gui.py -------------------------------------------------------------------------------- /examples/.AppleDouble/pi_vt_test.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/examples/.AppleDouble/pi_vt_test.py -------------------------------------------------------------------------------- /examples/.AppleDouble/resistance_meter.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/examples/.AppleDouble/resistance_meter.py -------------------------------------------------------------------------------- /examples/.AppleDouble/test_button.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/examples/.AppleDouble/test_button.py -------------------------------------------------------------------------------- /examples/.AppleDouble/test_led.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/examples/.AppleDouble/test_led.py -------------------------------------------------------------------------------- /examples/.AppleDouble/thermometer.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/examples/.AppleDouble/thermometer.py -------------------------------------------------------------------------------- /examples/pi_vt_test.py: -------------------------------------------------------------------------------- 1 | # Apply between 0 and 3.3V to pin 18 and note the voltage at wchich the input registers as high. 2 | 3 | import RPi.GPIO as GPIO 4 | import time 5 | 6 | a_pin = 18 7 | GPIO.setmode(GPIO.BCM) 8 | GPIO.setwarnings(False) 9 | GPIO.setup(a_pin, GPIO.IN) 10 | 11 | while True: 12 | while not GPIO.input(a_pin): 13 | pass 14 | print("Pin HIGH: Note Vth") 15 | while GPIO.input(a_pin): 16 | pass 17 | print("Pin LOW: Note Vtl") 18 | -------------------------------------------------------------------------------- /examples/resistance_meter.py: -------------------------------------------------------------------------------- 1 | from PiAnalog import * 2 | import time 3 | 4 | p = PiAnalog() 5 | 6 | while True: 7 | print(p.read_resistance()) 8 | time.sleep(1) 9 | -------------------------------------------------------------------------------- /examples/thermometer.py: -------------------------------------------------------------------------------- 1 | from PiAnalog import * 2 | import time 3 | 4 | p = PiAnalog() 5 | 6 | while True: 7 | print(p.read_temp_c()) 8 | time.sleep(1) 9 | -------------------------------------------------------------------------------- /hardware/.AppleDouble/.Parent: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/hardware/.AppleDouble/.Parent -------------------------------------------------------------------------------- /hardware/breadboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/hardware/breadboard.png -------------------------------------------------------------------------------- /hardware/schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonmonk/pi_analog/1cc647548df7d6e0f2f602db1d9020f8ed2f888a/hardware/schematic.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | setup(name='PiAnalog', version='1.0', py_modules=['PiAnalog']) 3 | --------------------------------------------------------------------------------