Hacking the AM2315 Humidity Sensor

NOTE: This content of this page is no longer relevant. Please go here for the latest AM2315 implementation “How-To.”

——————————————————————————————————————–

I recently discovered the AOSONG AM2315 humidity/temperature sensor and was quite intrigued. This is a very accurate and affordable device that is a nice addition to a current project. Supposedly, this device is i2c compliant, so I figured it would be easy to talk to. Little did I know….

After hacking around for a couple of long days I was able to get the device working on my breadboard with a Pi Cobbler. Google and forum searches determined there are a lot of people struggling to get the device to work.

So, Sopwith decided to write-up his adventure with the AM2315 and provide a very detailed step-by-step guide with screenshots.

I hope this helps save my fellow smoke-breathers some time and frustration.

Sopwith

37 thoughts on “Hacking the AM2315 Humidity Sensor

  1. thank you for taking on the challenge of hacking this sensor. I’ve resisted moving up to Python 3 but this may force me. I’m not a programmer at all, a plant physiologist. I copy code and hope it works. I’m working my way through codeacademy and a few books. As an alternative, I bought the SHT25 sensor. It is supposed to be truly i2c compatible. I’ll see. But as a matter of principle, I’ll do what I can to make the AM2315 work using your help.
    I’m building a dozen or so dataloggers based on the RPi. Low cost but they seem very durable if placed in the appropriate shelter. This is for some climate change research.
    Thanks again.

  2. Glad to be able to help you with your research. Please let me know if you need any more help in getting your sensor up and running. One point to note. The AM2315 library calculates the ‘relative’ humidity by using the current temperature and the ‘humidity’ reading from the sensor.

    Reading the AM2315 datasheet, it appears to me this calculation is already performed on the device. The datasheet says the humidity reading is the ‘relative’ humidity. The difference may be important to you depending on the accuracy of your research requirements.

    If you want to get on the phone and walk through the python code let me know. My email address is in the PDF document.

    Sopwith

  3. I appreciate the help. Before I jump into this in a week or so, one question. Adafruit told me I needed a bidirectional level shifter, which I purchased to deal with the incompatibility of RPi with 5V. Did you use one?

  4. I’m new to prototyping on the RPi, it took me half a day to get a light sensor working over I2C. From reading around I think your guide is going to save me a whole lot of time when my AM2315 arrives in the next couple of days! Thanks!

    Like mglenn I have the same level shifter in the post and would be interested to know if you used something similar or ran the risk with 5v?

    • A level-shifter is not required when connecting the AM2315 to a Rpi. It IS required if you are going to connect it to an Arduino. I wired my AM2315 the exact same way shown in Figure 11, page 10 of my write-up.

      From the AM2315 do the following:
      Power lead to Rpi pin 2
      Ground to Rpi pin-6
      SDA to Rpi pin 3
      SCL to Rpi pin 5

      You must also provide two pull-up resistors. These are shunted from SDA and SCL to the power lead. I used 10k ohm resistors because they lower the current draw. The datasheet says to use 4.8K ohm resistors.

      If you layout a circuit on a breadboard as shown in Figure 11, it should work fine. To move it to production I suggest using a very small solder-board to host the resistors.


      Sopwith

      • Hey, my sensor arrived last night and I was able to get it wired up and logging data within 15 mins with your guide (I already had I2C enabled and python 3 installed)

        Thanks again for saving me the headache!

  5. The 5c / b8 i2c address difference wasn’t a change in the hardware, it just two ways of describing i2c addresses. An address is an 8-bit value but the bottom bit is reserved for other reasons. So some (like your datasheet author) report all 8 bits (so 0xb8 or 1011 1000) wheras Linux just reports the top 7 bits 101 1100, or 0x5c). One is just the other right shifted by 1.

  6. I finally got back to this and it worked like a charm with one minor exception. Using the 10 ohm resistors, I was unable to register the device on the i2c matrix but using the bi-directional level shifters, it worked. I’m pretty sure I configured the resistors correctly. At any rate thanks so much for taking on this challenge and doing such a thorough job of documenting the process. Now I need to go into the AM2315.py and understand how it works. All the best.

  7. You are amazing! I searched everywhere and this is most detailed guide there is. I am still not getting anything from my sensor. I think it may be bad because i have the 10k resistors in place. I didn’t before, could that have damaged the sensor? I followed you guide very carefully. Even if I run the “sudo i2cdetect -y 1” command twice, it does nto appear. I see you listed a chronodot-RTC, is that something my i2c should also detect? I’m a noob to this.

    • Dorian,

      Remember Sopwith’s first rule: “If it works out of the box – what fun is that?” This essentially means you are having fun right now because your sensor does not work. It may not feel like you are having fun – but you are!

      Ok – let’s try and get your sensor working. First things first.
      Do you know what revision of Pi board you have?
      If you have a RevA board (No Ethernet port) then try the command $sudo i2cdetect -y 0 two times in quick succession.
      If you have a RevB board (Ethernet port) use the command $sudo i2cdetect -y 1 twice in quick succession.

      Still no luck? Then let’s look at your wiring. It is highly unlikely you damaged your sensor with the 10K ohm resistors. They must be used for you to read your sensor data. Turn to page 10 of my guide and study the diagram closely. If you can, lay out your components on a small breadboard exactly as shown. Notice the SDA (yellow) and SCL (blue) leads are connected in parallel with the VCC (red) lead AND are connected to the Pi pins 3 and 5. Make sure the wires are connected to the correct pins. Also make sure your 10k ohm resistors have the colors brown, black, orange, and gold.

      Once you have checked everything, twice, try the appropriate i2cdetect -y 1|0 command.

      If this still does not allow you to ‘see’ the sensor on the Pi bus, let me know and we will continue digging. If you have confidence and patience, you will figure out why your sensor is not working for you. 95% of the time the reason one cannot see the sensor is due to problems with the wiring.

      Do not worry about my references to my ChronoDot. It is not needed and has zero bearing on your issue.

      Sopwith

      • Thank you so much for taking the time to respond. I don’t have it setup on a breadboard. I have soldered my connections. I think the problem maybe that I didn’t have SDA and SCL as parallels. My solder point hold both the scl and sda and then it splits the resistors. Would that be a possible cause? I do have a new sensor here just in case I possibly caused damage to the sensor by doing this. I will go ahead and try to re-wire my sensor.

        • That was it. Instead of running the resistors from one solder point, I soldered from two different points on the power cable and got data!

          Thank you so much for your help. Now to try and understand the python script to get data written to an SQL db.

          • Never, ever give up. Your persistence resulted in a working sensor plus you learned things you never knew before. All without smoke!

            Sopwith

  8. Thank you very much! This guide is very easy to follow.

    Is it normal that humidity samplings can vary from each other up to 10% when querying one after another?

    • Jamik – it depends on the time gap between samplings. If you get a 10% variance in humidity when your samples are seconds apart, that is not normal. Depending on the climate conditions a variance in humidity over several minutes could occur. The AM2315 will respond with garbage data if you do not follow the correct wake-up sequence. I suggest you write a short Python program that reads the sensor every 15 seconds and prints out the temperature and humidity readings from the sensor. Have it loop 10 iterations and see what variance there is.

      Sopwith

  9. Hi Sopwith,
    I am interfacing an AM2315 RHT sensor with a PIC24F(pic24fj128gc010) development board and having issues as a lot of people out there. I stumbled upon your website on googling the same. I have tried everything that has been given in the datasheet and by people who got this thing to work, but still the sensor is not responding. As a embedded enthusiast to another, can you please help me in interfacing this sensor?

    I have developed my own library making use of the I2C2 module on the controller. The library is tested working with PCF2129 RTC and SI7013 RHT sensor. My current design involves an I2C bus extender (PCA9515A) with 4.7K pullups on either side. The I2C module on pic24f is working fine on my controller(checked with a scope). I am strictly running the I2C module at 100KHz.

    Please help……

    • Shreyas,

      I will help you in any way I can.

      I am certainly not a PIC expert, but I suspect you are running in to the same issues other hackers have had with this device.
      1) Understand the AOSONG devices do not strictly comply with the I2C standard. This outfit designs interfaces that disregard all the typical rules of engagement.
      2) This device requires a ‘wake-up’ call before it will send you any data. Since you are a PIC programmer, I suspect you do not mess around with Raspberry PI’s. Even so, please download and read this document to make sure you understand how the PI communicates with the device.
      http://sopwith.ismellsmoke.net/?p=46 From this document you can write some PIC tests to see if the device responds.
      3) There is a very slim possibility your device is defective. I seriously doubt this but I know a ton of folks send the device back to Adafruit or wherever they bought them when they do not work. I suspect most of these devices work just fine.
      4) You need to send the device a read request and then immediately do a raw read of everything it sends back.

      If I had to guess what is wrong – I suspect you are not waking up the device before you send it a ready request. Once the device is awake you need to do a block read of data that it returns. Also, do not attempt to read from the device in time increments less than 3 seconds.

      One final thing, switch out the pullups to 10k’s and see it that helps.

      Let me know if you do not get it working and I will arrange to get your device tested to make sure it works.

      Sopwith

  10. I’ve been referencing this guide while working on my own weather station. Great write-up! I was able to get the sensor going shortly after getting things wired up.

    I currently do not have pull up resistors on the i2c lines. I am still getting what appear to be good readings from the device. Do I still need to use pull-ups? The whole concept of a pull-up is a bit confusing for me… I’m a mechanical engineer and always try to translate electrical stuff to mechanical systems.. Does the pull-up act similarly to the spring in a drum brake system? When you step on the brakes, the shoes are forced into the drum. When you release the brakes, the spring (resistor) returns the shoes to their initial starting position. Good analogy?

    Thanks again for working this out!

  11. If you are getting good readings, then there is no need to add pullups. That said, you need to be a bit careful here. Depending on the temperature sensor you are using, it may already have the required pullup resistors built in. Some do – some don’t. If your device does not have pullups on-board, and it requires them, you might get valid sensor readings without them. Be aware, however, in most cases the device will behave erratically. You can get good readings, followed by garbage the next time you read the device.

    I am not an electrical engineer, so I am not qualified to give you a detailed description of pullup/pulldown resistors and their use. What I do know is they are used to provide an electrical circuit a reference point. In this case, this simply means a GPIO pin with a pullup/pulldown resistor in place will ‘pullup’ the circuit to some voltage (usually 3.3 or 5V) or ‘pulldown’ the circuit voltage to ground, depending on needs.

    Your mechanical analogy is pretty close. In the case of the temperature sensor, the pullup resistor will ensure the circuit is at 5V at the beginning of any i2c protocol communications.

    Anyone more qualified to answer this question feel free to jump in here.

    Sopwith

  12. Wow, a bit of digging later with no real answers.. but I wanted to share in case anyone else came across this.
    Following along with a rpi b+, I had to modify /usr/local/lib/python3.2/dist-packages/quick2wire_api-0.0.0.2-py3.2.egg/quick2wire/i2c.py and force default bus to 1. For some reason the revision() call was returning less than 1, forcing quick2wire to look at i2c-0 which is not where the AM2315 is plugged into.

    The message I was getting was [errno 2] the file or folder is not accessible /dev/i2c-0

    I am still learning, but wanted to put this out there in case anyone else was having similar issues. If anyone has a better explanation or fix, please post it, I don’t want my kludge of a fix to come back to bite me sometime in the future.

    Kevin

  13. Your guide has proven helpful, thanks.
    This device appears to be capable of being powered from the 3.3v line (pin1 instead of pin 2 on the PI), doing so eliminates the need for the pull up resistors as the logic levels on SDA SCL will be 3.3v already.

  14. Hi Sopwith,

    Many thanks for this detailed tutorial, that is very kind of you.
    As I was trying to get my AM2315 working, I failed in the last steps. Typing in sensor.temperature() or sensor.humidity() got me the same error. Could it possibly be related to the fact that I’m running the script on a RPi 3 Jessie ? Any idea/leads on how to circumvent this problem would be greatly appreciated, as I’m pretty stuck.

    >>> sensor.temperature()
    Traceback (most recent call last):
    File “”, line 1, in
    File “/usr/local/lib/python3.4/dist-packages/AM2315.py”, line 54, in temperature
    return self.values()[1]
    File “/usr/local/lib/python3.4/dist-packages/AM2315.py”, line 26, in values
    with i2c.I2CMaster() as bus:
    File “/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py”, line 48, in __init__
    FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

    Many thanks.

    • Hi Marc,

      The problem you are having is most likely related to the quick2wire library not recognizing the Pi3 hardware. There are two thing you should do.
      1) Download my test program from here: http://sopwith.ismellsmoke.net/?p=104
      Click on the download button and extract the contents of the zip file. There is a README.txt file to guide you. The test script should work.
      2) Look and see what i2c devices are on your system. Run the below command:
      $ls /dev | grep i2c

      My guess is the output of this command will show a “/dev/i2c-1” device. The quick2wire is looking for “/dev/i2c-0” device. We know this because the last line of the Python traceback is: “FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’.”

      Run the test program and send me the output of the ls command.
      This problem should be easy to fix if the problem is simply the wrong device file name.

      Sopwith

      • Hello Sopwith!

        Thank you for this great tutorial! It’s been a huge help 🙂

        I’ve been having the same problem as Marc above:

        Traceback (most recent call last):

        File “/usr/local/lib/python3.4/dist-packages/AM2315.py”, line 54, in temperature
        return self.values()[1]
        File “/usr/local/lib/python3.4/dist-packages/AM2315.py”, line 26, in values
        with i2c.I2CMaster() as bus:
        File “/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py”, line 48, in __init__
        FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

        I’m VERY new to all of this so I apologize in advance for bearing through my attempts but here’s what I have

        The Pi3 (that I’m using) uses i2c-1 instead of i2c-0 which was part of a revision a few versions ago.

        I’ve tried several things in the i2c.py file – changing “default_bus = 1 if revision() > 1 else 0” to just “default_bus = 1”, setting the extra_open_flags=1, and even changing the string on line 48 from “/dev/i2c-%i”%n to “/dev/i2c-1” no luck.

        The ONLY thing that worked for me was renaming the i2c-1 device in /dev to “i2c-0”, and that works fine as long as you don’t reboot, rebooting will change it back to i2c-1 (this also doesn’t seem like the best fix anyways).

        Any suggestions or directions to point me in?

        According to quick2wire it should detect whether i2c is at 0 or 1, but clearly it doesn’t.

        Any help is GREATLY appreciated!!

        Thank you in advance!!

        • I too am getting error codes see below

          Any help would appreciated

          pi@raspberrypi:~/heater $ ls /dev | grep i2c
          i2c-1
          pi@raspberrypi:~/heater $

          ======================================================================
          ERROR: test_GetPiI2CBusNumber (__main__.TestAOSONG_AM2315)
          ———————————————————————-
          Traceback (most recent call last):
          File “test_aosong_am2315.py”, line 35, in setUp
          self.sensor = AOSONG_AM2315()
          File “/home/pi/heater/aosong_am2315.py”, line 84, in __init__
          self.bus = i2c.I2CMaster() # quick2wire master
          File “/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py”, line 48, in __init__
          self.fd = posix.open(“/dev/i2c-%i”%n, posix.O_RDWR|extra_open_flags)
          FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

          ======================================================================
          ERROR: test_GetPiRevision (__main__.TestAOSONG_AM2315)
          ———————————————————————-
          Traceback (most recent call last):
          File “test_aosong_am2315.py”, line 35, in setUp
          self.sensor = AOSONG_AM2315()
          File “/home/pi/heater/aosong_am2315.py”, line 84, in __init__
          self.bus = i2c.I2CMaster() # quick2wire master
          File “/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py”, line 48, in __init__
          self.fd = posix.open(“/dev/i2c-%i”%n, posix.O_RDWR|extra_open_flags)
          FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

          ======================================================================
          ERROR: test_ReadHumidity (__main__.TestAOSONG_AM2315)
          ———————————————————————-
          Traceback (most recent call last):
          File “test_aosong_am2315.py”, line 35, in setUp
          self.sensor = AOSONG_AM2315()
          File “/home/pi/heater/aosong_am2315.py”, line 84, in __init__
          self.bus = i2c.I2CMaster() # quick2wire master
          File “/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py”, line 48, in __init__
          self.fd = posix.open(“/dev/i2c-%i”%n, posix.O_RDWR|extra_open_flags)
          FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

          ======================================================================
          ERROR: test_ReadSensorData (__main__.TestAOSONG_AM2315)
          ———————————————————————-
          Traceback (most recent call last):
          File “test_aosong_am2315.py”, line 35, in setUp
          self.sensor = AOSONG_AM2315()
          File “/home/pi/heater/aosong_am2315.py”, line 84, in __init__
          self.bus = i2c.I2CMaster() # quick2wire master
          File “/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py”, line 48, in __init__
          self.fd = posix.open(“/dev/i2c-%i”%n, posix.O_RDWR|extra_open_flags)
          FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

          ======================================================================
          ERROR: test_ReadTemperature (__main__.TestAOSONG_AM2315)
          ———————————————————————-
          Traceback (most recent call last):
          File “test_aosong_am2315.py”, line 35, in setUp
          self.sensor = AOSONG_AM2315()
          File “/home/pi/heater/aosong_am2315.py”, line 84, in __init__
          self.bus = i2c.I2CMaster() # quick2wire master
          File “/usr/local/lib/python3.4/dist-packages/quick2wire_api-0.0.0.2-py3.4.egg/quick2wire/i2c.py”, line 48, in __init__
          self.fd = posix.open(“/dev/i2c-%i”%n, posix.O_RDWR|extra_open_flags)
          FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

          ———————————————————————-
          Ran 5 tests in 0.009s

          FAILED (errors=5)

  15. Dear All,

    Thanks for sharing all your good information regarding the AM2315 – and especially for sharing the difficulties in trying to understand the documentation and getting the first “hello world” response. Its strange that so few manufactures understand the importance of getting started quickly. I often spend 90% of the time in any project getting the sensor to reply the first few bytes, the remaining is just hard work.

    Anyhow, I purchased a few of the AM2315 believing that I could easily change the address of each sensor in order to use the bus potential of the I2C, now it seems to me as if changing the address is not even possible. Strange combination of going through the extra work of having a bus enabled sensor and then not leaving the user the option for changing the address ? Beats my logic.

    Or perhaps I am mistaken and there is a hack to change the dev. address. If so, please share your knowledge.

    Btw I am using a RasPi2 running LabVIEW Linx and the way I “hacked” the sensor out of its sleep mode was to simply send the write request 03x 00x 04x twice with a 5 ms. delay between each transmit.

    /søren

    p.s. a special thanks to Sopwith for all the support on this page, I would not have made initial contact with the sensor had it not been for the help above and on the how to doc.

  16. Hi Sopwith,

    Thanks for your guide, I have been using my AM2315 indoor for quite sometime to test it.
    Though since I have installed it outdoor, I have been starting getting some erratic results. The first 2 days were very accurate, then, humidity started to be stuck at 98.70% and since last night, temperature is reporting 3276.9….

    I’m querying the sensor every 5min (with Cacti actually), so I guess it is not oeverwhelming.

    The current temperature is very humid (Env. Canada is reporting 100% humidity), just wondering is some water wouldn’t have find it’s way in the sensor.

    Any idea what could be wrong ?

    Have you heard some similar stories where the AM2315 is installed outdoor ?

    Thanks !

  17. Hi everyone

    Just received my Pi3 Rev B and the AM2315 and found this site here.
    I used the very well written How to-pdf and it all went very well… Almost…

    Just got the same error message when I try to read the temperature or humidity:

    FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

    Quote garret:
    “The ONLY thing that worked for me was renaming the i2c-1 device in /dev to “i2c-0”, and that works fine as long as you don’t reboot, rebooting will change it back to i2c-1 (this also doesn’t seem like the best fix anyways).”

    Where do I have to rename the 12c device? I stuck on this 🙁

    Thanks for your help!

  18. I am hoping someone can help. I am almost there….

    I have followed the guide explicitly and I can detect the device using ‘sudo i2cdetect -y 1’ twice in quick succession and it shows up as 5c. I was successful installing https://github.com/quick2wire/quick2wire-python-api.git and since https://code.google.com/p/am2315-python-api/ is no longer available, I installed https://github.com/camrex/am2315-python-api.git instead. I believe these to be identical but am not sure.

    Both seemed to install successfully, however, when I try step #22 of the guide I get the following:

    Python 3.5.3 (default, Jan 19 2017, 14:11:04)
    [GCC 6.3.0 20170124] on linux
    Type “help”, “copyright”, “credits” or “license” for more information.
    >>> from AM2315 import *
    >>> sensor = AM2315()
    >>> sensor.temperature()
    Traceback (most recent call last):
    File “”, line 1, in
    File “/usr/local/lib/python3.5/dist-packages/AM2315.py”, line 54, in temperature
    return self.values()[1]
    File “/usr/local/lib/python3.5/dist-packages/AM2315.py”, line 26, in values
    with i2c.I2CMaster() as bus:
    File “/usr/local/lib/python3.5/dist-packages/quick2wire_api-0.0.0.2-py3.5.egg/quick2wire/i2c.py”, line 48, in __init__
    FileNotFoundError: [Errno 2] No such file or directory: ‘/dev/i2c-0’

    As you can see, upon entering ‘sensor.temperature()’ it returns ‘No such file or directory: ‘/dev/i2c-0”

    I think it is clear that I should be reading from i2c-1, not i2c-0. I tried ‘mv i2c-1 i2c-0’ but it then it reported a constant temperature and humidity of 999, which appears to be a default.

    How do I get it to read from i2c-1 instead of i2c-0? Or does anyone have any other advice?

Leave a Reply

Your email address will not be published. Required fields are marked *