Measuring analog values on a Raspberry Pi without ADC

Contrary to the ESP8266 or the Arduino, the Raspberry Pi has no analog ports. In order to measure analog values, you can add an ADC. These usually are driven by the I2C port or by SPI.

If however  you only need to measure one analog value with a variable resistor sensor, there is a quick and easy way to do that without adding an ADC converter on your I2C. But, it will still cost you two pins.

If you take a look at the picture, the working appears pretty simple:
The Charge pin, when made HIGH starts charging the 100nF capacitor through the NTC. When at a certain time the voltage over the 100nF capacitor is high enough to be seen as a HIGH by the Raspberry, the ‘measure pin’ gets set from LOW (in fact from Zero) to HIGH. The time it takes from the start of the charge till the measure pin goes to HIGH is then a time value that is a measure for the value of the NTC. It is only influenced by the  value of the NTC. When we feed a Raspberry with 3.3 Volt, a HIGH on a pin means a minimum of 1.6 Volt, so in fact we are measuring the time it takes to charge a capacitor from zero to 1.6 Volt. The 1k resistor is just a safety precaution to prevent too much current coming from the capacitor when it is discharged.

It is paramount that the measurement is always taken from the same starting position, meaning an empty capacitor. The measurement procedure thus looks like this:

Empty capacitor
Start charging capacitor
Start timer
Wait till capacitor is HIGH
Read timer

to decharge the capacitor we can use the measuring pin.

Fortunately very often someone already has written a code that can be used and in this case it was SimonMonk

import RPi.GPIO as GPIO
import time

# declare GPIO mode
GPIO.setmode(GPIO.BCM)

# define GPIO pins with variables charge_pin and measure_pin
# 18=chargepin 23=measure
charge_pin=18 
measure_pin = 

# discharge the capacitor
def discharge():
    GPIO.setup(charge_pin, GPIO.IN) #stop charging
    GPIO.setup(measure_pin, GPIO.OUT) #make the measure pin an output
    GPIO.output(measure_pin, False) # set it low to discharge the capacitor
    time.sleep(0.005)

def charge_time():
    GPIO.setup(measure_pin, GPIO.IN) 
    GPIO.setup(charge_pin, GPIO.OUT)
    count = 0
    GPIO.output(charge_pin, True) #start charging the capacitor
    while not GPIO.input(measure_pin): #wait till the pin goes HIGH
        count = count +1
    return count

def analog_read():
    discharge()
    return charge_time()

# loop to display analog data count
while True:
    print(analog_read())
    time.sleep(1)
    


                  
Advertisements

Reading the DHT11 or DHT22 on the Raspberry via an overlay and send it to the openHab REST API

In an earlier tutorial I showed how to read the popular DHTxx sensor on a Raspberry Pi and then to MQTT that into Openhab.
However, there are more ways to skin a cat, so what I like to do this time is:

1) Read the sensor with a device tree overlay on a Raspi and then
2) Send the data to OpenHab with the REST-API

I am not saying one method is better than the other, but suppose you dont want to install an MQTT server because all your other channels don’t need MQTT, then the REST API comes in handy.

1) Reading the DHT sensor
First we need to load the dht11 overlay at boot-up
Do
sudo nano /boot/config.txt
and add:

dtoverlay=dht11,gpiopin=4

obviously one can pick another pin here, or declare a different sensor such as the DHT22 or DHT21 (AM2301)

then all you have to do is to read the following 2 files:

/sys/devices/platform/dht11@0/iio:device0/in_temp_input
/sys/devices/platform/dht11@0/iio:device0/in_humidityrelative_input

Once you have loaded the overlay and connected your sensor, a simple:
cat /sys/devices/platform/dht11@0/iio:device0/in_temp_input,
would show you the temperature.
whereas:
cat /sys/devices/platform/dht11@0/iio:device0/in_humidityrelative_input, would show you the humidity

Upon doing that in a python program, I noticed there can be quite a number of I/O errors. This seems to be a frequent problem with this overlay, so in order not to interrupt the program, I had to do a bit of Error catching.

2) Sending values to OpenHab
The REST API is fairly simple to use. We only need 1 line for every Item we want to update. Such a line looks like this:
requests.put('http://192.168.xxx.yyy:800/rest/items/<YOUR ITEM>/state',value).
The ‘value’-variable needs to be a string.

3) Wrapping it up
A simple Python program would look like so:

import time
import requests
tfile='/sys/devices/platform/dht11@0/iio:device0/in_temp_input'
hfile='/sys/devices/platform/dht11@0/iio:device0/in_humidityrelative_input'

def read_temp_raw():
   f=open(tfile,'r')
   lines=float(f.read())/1000.0
   f.close()
   return lines

def read_humidity_raw():
   b=open(hfile,'r')
   hlines=float(b.read())/1000
   b.close()
   return hlines

while True:
   try:
     T=str(read_temp_raw())
     print(T)
     H=str(read_humidity_raw())
     print(H)
     time.sleep(2)
     #Put your own IP and Itemnames here,
     requests.put('http://192.168.1.103:8080/rest/items/<ITEMNAME>/state',T)
     requests.put('http://192.168.1.103:8080/rest/items/<ITEMNAME>/state',H)

   except IOError:
      print("I/O error")

Beware that Python programs rely on proper indenting. As this sometimes can be corrupted by publication on a website, I will leave an image of the properly indented program below:

As I am not the world’ s best python coder, I am sure improvements can be made, but at least this code will get you up and running fast.
Since the OpenHAB items are updated through the REST API, they do not need a channel in the itemsfile, that could look as simple as this:

Number HH "REST Humidity [%.0f %%]" <humidity> (Weather)
Number HT "REST temperature [%.1f °C]" <temperature> (Weather)