Wednesday, April 24, 2013

Raspberry Pi and snmp polling using am2302 (wired dht22) temp sensor

Yipes. This sensor has been interesting. First off, because of the fast polling of data off the sensor, a C program was written because python seems to be too slow. Ugh. I don't know C at all but managed to get through it with a little help from a bunch of ppl to whom I will credit as the post continues.

What is this post concerning? Well, it is written on the heels of another one of my posts, SNMP polling using a DS18B20 sensor. Many assumptions will be made during this post but those assumptions all come from the know-how that is in that article, for example, I assume you have a working SNMP server/client set up and configured. If not, cruise over to the other article and scroll down a bit and it shows you how. So, on that note, lets go.

What is needed (again with the assumptions):

Let me get this out of the way. I didn't create any of this from scratch. What I've done is harvest all the information into one spot from me jumping all over the internet trying to find a way to get this done. So I take no credit in any of these pieces as pieces. I will take credit for bringing this all together in a very readable, easy to understand tutorial that anyone can follow and have a working sensor giving data to any program that uses SNMP.

Wiring the AM2302 to the Pi:

This is pretty much it. Nothing to it. Because we have used the Prototyping Pi Plate, we just need to find pins for GROUND, 3.3 VOLTS and PIN #25 (ill explain later why 25 and not 4) and screw the leads into the screw down terminals. That's it. Because this is the AM2302 and NOT the DHT22, we do NOT need a  pull-up resistor anywhere in the wiring. The resistor is INSIDE the casing of the AM2302. Sweet.

Once its wired, we gotta look at the software side. Ugh.

I followed the directions on THIS LINK to the "t" and everything worked exactly how it should with Pin 4 and everything exactly how they stated it there (there's no need to copy and paste everything since it is on that page pretty well formatted so cruise on over and then jump back when you have it working).

This was just to test that the wiring and software compiling was working on your end. Now we have to edit everything to get it to do what we need it to do, so here goes.

What I didn't know is that you need to compile each time you make a change. yeah, i remember saying I didn't know C right? Anyway, after figuring that out, I was able to come up with some pretty quick changes to the main C program and then compiled it.

First change to the file Adafruit_DHT.c I made was commenting out this line:

printf("Using pin #%d\n", dhtpin);

This messes up the SNMP output. So does this line so comment it out as well:

printf("Data (%d): 0x%x 0x%x 0x%x 0x%x 0x%x\n", j, data[0], data[1], data[2], data[3], data[4]);

After commenting both those lines out, i got into the nitty gritty of the actual output. I commented out this line at the end of the file:

printf("Temp =  %.1f *C, Hum = %.1f \%\n", f, h);

and added these lines:

printf("%.0f\n", f*1.8+32);
printf("%.0f\n", h);

What this will do is change the output from that one line to two separate lines with just the temp and humidity in it. Then I compiled it using the compiler line in the link above on adafruits website:

gcc Adafruit_DHT.c -l bcm2835 -std=gnu99 -o Adafruit_DHT

This makes an executable file called Adafruit_DHT that has our code in it. This is where the pin move comes into effect. I had something on pin 4 that couldn't be moved for one reason or another so I had to use pin 25. So from now on, I will be referencing pin 25 instead of pin 4 but there is NO code that forces it on pin 25 or pin 4, only the executable when you run it. So running this:

sudo ./Adafruit_DHT 2302 4

will set the pin to 4 and running this:

sudo ./Adafruit_DHT 2302 25

will set the pin to 25. Easy. The 2302 part is calling the code to reference that you are using a 2302 sensor.

Here comes the tricky part. Getting it to run with SNMP and dump this data. Because the sensor fails to dump data every time its polled (I found this somewhere that if you run that executable too quickly, it wont show data both times - you have to wait 3 seconds until you poll it again), you must grab both the temp and humidity at the same time even tho you might want to grab the temp separately and the humidity separately through your SNMP program.

This is where we trick it. By calling that executable OUTSIDE of SNMP altogether through cron, we can then poll against a SED output to two separate files. Oh Snap! This is what I did:

I made a bash script called "getboth" and put it in /var/scripts made up of this code:



sudo /home/pi/Adafruit-Raspberry-Pi-Python-Code/Adafruit_DHT_Driver/Adafruit_DHT_both 2302 25 > /home/pi/both.txt

while [ ! -s "/home/pi/both.txt" ]
        sleep 5
        sudo /home/pi/Adafruit-Raspberry-Pi-Python-Code/Adafruit_DHT_Driver/Adafruit_DHT_both 2302 25 > /home/pi/both.txt


sed '1d' /home/pi/both.txt > /home/pi/humid.txt
sed '2d' /home/pi/both.txt > /home/pi/temp.txt


The code between the lines is what you want to copy and paste. Blogger doesn't have a decent code box to paste special code into.... Anyway, to explain what I did, 

  • the first line runs the Adafruit exe (which i renamed to Adafruit_DHT_both) with the syntax 2302 for the sensor type and 25 for the pin i used then dumps the output to a local file called "both.txt" in my home dir. Remember knowing this, you can put the files anywhere but Im only adding it here so this could be a direct copy and paste and everything works.
  • Next is the WHILE loop that looks at "both.txt" and if it is 0 bytes, it sleeps for 5 seconds and runs it again. This is because sometimes the sensor doesn't give back info the first time you poll it. This is all documented on other pages. Feel free to search for it but since I found a workaround, I didn't feel the need to go into detail about the inner worksings of the sensor, only that it has this "issue".
  • the second to last line looks inside "both.txt" and uses SED to dump the FIRST line and read only the SECOND line and it dumps it to a file called "humid.txt"
  • the last line does what the previous line does but backwards; it dumps the SECOND line and reads only the first line then dumps that output to a file called "temp.txt"
If you remember, when we added and changed all those lines in the original C program code, we added those lines at the end that stated printf blah blah blah but there were two lines, one for the temp and the other for the humidity. That output from that original C program is being outputted into our "both.txt" file so SED can look through it easily and grab what it needs.

Now that that script is done, we gotta call it using cron. By typing this:

sudo crontab -e

I was able to edit the cron in order to run that script as root every minute by copying that Adafruit_DHT_both file to /var/scripts and putting this line at the end of my cron file:

*/1 * * * * /var/scripts/getboth

This will run the "getboth" script every 1 minute which will poll the sensor only ONCE per minute but more than 3 seconds apart due to our constraints (what i explained above with the polling once every 3 seconds at least).

The last part of this equation is making sure SNMP likes us. What I did was make two more bash scripts and put them with the others in /usr/local/bin. One to parse out the humidity and the other to parse out the temp.

Temp script:

echo .
echo gauge
cat /home/pi/humid.txt

Humidity script:

echo .
echo gauge
cat /home/pi/temp.txt


sudo chmod +x scriptname

These two files will be run by your snmpd.conf to post the correct OID, gauge and output to the proper SNMP output that is liked by SNMP. They are called something different because they do different things. They each will be called separately to grab what was originally polled by cron from the two txt files in your home dir.

I had to do this because of the restriction against polling the device too quickly. Also had to do it this way because of an issue I ran into trying to run sudo from inside the snmpd.conf file. I could have written this all in the original C program but i was unable to run sudo from snmpd.conf so I could call the adafruit exe correctly. Looking back, i dont think that would have been feasible because of the polling issue with getting data too fast from the sensor...

Of course this is open to a LOT of assistance. For one, I did run into some trouble with sometimes the polling doesnt happen and I would like to put an if then else in the "getboth" script somewhere that would poll the sensor again until it got results. Why this is needed is because, as the code sits now, sometimes when the sensor is polled, it gives blank results. It will then save the "both.txt" as blank. That means when the "humid.txt" and "temp.txt" are created, they are created blank as well. When that happens and SNMP rolls through, it grabs no data and throws an error inside my Nagios setup until the next time it comes through and data has been successfully retrieved from the sensor and those three text files are populated with data. If anyone has any code to do that, I would appreciate it! :) What I do know is that the way it is describe above, it is working quite well so I imagine I am on the right track!!  Code is in as of 04-25-13.

Some of this might not have made sense. I explained everything in much more detail in my previous post so if there is something that is confusing, cruise over to the other article and it will most likely be explained there!

Update 05-31-13
I have 2 50 foot remote sensors and a local sensor attached to the Pi. After seeing some strange power issues after the first weekend of testing, I opted to switch out the 1 amp power supply I was using and put a 2 amp power supply in. One came with my cell phone (Note 2) so on a whim I tried it and haven't had problems since.

1 comment:

  1. Thanks from Spain!, I had some problems.
    but currently works with cacti and monitoring temperature and humidity