{"id":20989851,"url":"https://github.com/robtillaart/dht20","last_synced_at":"2025-05-14T18:32:15.371Z","repository":{"id":45061756,"uuid":"446929723","full_name":"RobTillaart/DHT20","owner":"RobTillaart","description":"Arduino library for DHT20 I2C temperature and humidity sensor.","archived":false,"fork":false,"pushed_at":"2024-04-13T08:58:12.000Z","size":942,"stargazers_count":21,"open_issues_count":0,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-08-07T18:27:15.877Z","etag":null,"topics":["arduino","humidity","i2c","temperature"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RobTillaart.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"RobTillaart","custom":"https://www.paypal.me/robtillaart"}},"created_at":"2022-01-11T18:05:54.000Z","updated_at":"2024-05-15T20:55:40.000Z","dependencies_parsed_at":"2023-01-30T04:45:33.404Z","dependency_job_id":"a589d878-3bfa-4d87-a9be-4d75afc051b3","html_url":"https://github.com/RobTillaart/DHT20","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FDHT20","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FDHT20/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FDHT20/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FDHT20/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobTillaart","download_url":"https://codeload.github.com/RobTillaart/DHT20/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225305728,"owners_count":17453438,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","humidity","i2c","temperature"],"created_at":"2024-11-19T06:26:24.859Z","updated_at":"2024-11-19T06:26:25.446Z","avatar_url":"https://github.com/RobTillaart.png","language":"C++","funding_links":["https://github.com/sponsors/RobTillaart","https://www.paypal.me/robtillaart"],"categories":[],"sub_categories":[],"readme":"\n[![Arduino CI](https://github.com/RobTillaart/DHT20/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)\n[![Arduino-lint](https://github.com/RobTillaart/DHT20/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/DHT20/actions/workflows/arduino-lint.yml)\n[![JSON check](https://github.com/RobTillaart/DHT20/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/DHT20/actions/workflows/jsoncheck.yml)\n[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/DHT20.svg)](https://github.com/RobTillaart/DHT20/issues)\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/DHT20/blob/master/LICENSE)\n[![GitHub release](https://img.shields.io/github/release/RobTillaart/DHT20.svg?maxAge=3600)](https://github.com/RobTillaart/DHT20/releases)\n[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/DHT20.svg)](https://registry.platformio.org/libraries/robtillaart/DHT20)\n\n\n# DHT20\n\nArduino library for I2C DHT20 temperature and humidity sensor.\n\n\n## Description\n\nThe DHT20 is a humidity and temperature sensor. \n\nThe sensor has a fixed address of **0x38**.\nIt is not known if the address can be changed.\n\nThe library must be initiated by calling the **begin()** function.\n\nThereafter one has to call the **read()** function to do the actual reading,\nand call **getTemperature()** and **getHumidity()** to get the measured values.\nCalling these latter again will return the same values until a new **read()** is done.\n\nThe **read()** call of this sensor is blocking for 80+ milliseconds (datasheet 7.4)\nso the library also has a asynchronous interface. See below.\n\nSince 0.1.3 and 0.1.4 the performance of **read()** has been optimized, \nstill blocking but less long for about 45 milliseconds.\n\n\n### 0.2.0\n\nIn #8 a bug is described that the sensor \"freezes\".\nCause is not well understood.\n\nTwo solutions / workarounds are found:\n- call **resetSensor()** before EVERY **read()**. \nThis is the preferred solution.\n- use **Wire.setClock(200000)** 100 K and lower speeds freezes the sensor.\nWith clock set to 200 K and above the sensor seems to work for longer periods.\nTested several speeds on UNO, no pull ups, \u003c 10 cm wire.\n\nNote: setting the I2C clock possibly interferes with other devices on the I2C bus,\nso it is not a solution in the end.\n\nThe 0.2.0 version embeds the **resetSensor()** into **requestData()** to \nreset the sensor if needed in both synchronous and asynchronous calls.\nThis keeps the API simple. The reads are 1-2 ms slower than 0.1.4. (\u003c 50 ms).\nStill far below the 80 ms mentioned in the datasheet. \n\n\n#### 0.3.0 Breaking change\n\nVersion 0.3.0 introduced a breaking change.\nYou cannot set the pins in **begin()** any more.\nThis reduces the dependency of processor dependent Wire implementations.\nThe user has to call **Wire.begin()** and can optionally set the Wire pins\nbefore calling **begin()**.\n\n\n#### Tested\n\nVerified to work with Arduino UNO and ESP32 and ESP8266 (see #8)\nPlease let me know if other platforms work (or not).\n\n\n## I2C\n\n#### Address\n\nThe sensor has a fixed address of **0x38**.\nIt is not known if the address can be changed.\n\n\n#### I2C multiplexing\n\nSometimes you need to control more devices than possible with the default\naddress range the device provides.\nThis is possible with an I2C multiplexer e.g. TCA9548 which creates up \nto eight channels (think of it as I2C subnets) which can use the complete \naddress range of the device. \n\nDrawback of using a multiplexer is that it takes more administration in \nyour code e.g. which device is on which channel. \nThis will slow down the access, which must be taken into account when\ndeciding which devices are on which channel.\nAlso note that switching between channels will slow down other devices \ntoo if they are behind the multiplexer.\n\n- https://github.com/RobTillaart/TCA9548\n\n\n#### Connection\n\nAlways check datasheet!\n\nFront view\n```\n          +--------------+\n  VDD ----| 1            |\n  SDA ----| 2    DHT20   |\n  GND ----| 3            |\n  SCL ----| 4            |\n          +--------------+\n```\n\n#### Performance\n\nThe datasheet states 400 KHz as the maximum speed.\nBelow the results of a small test that works well up to 800 KHz.\n\n - Arduino UNO + 10 cm wires + no pull up + DHT20_I2C_speed.ino\n\nSpeed in KHz, Time in microseconds. \n\n\n**read()**\n\n|  Speed  |  Time   |  notes  |\n|:-------:|:-------:|:--------|\n|   100   |  44588  |  default I2C speed  |\n|   200   |  43988  |\n|   400   |  44040  |  datasheet maximum  |\n|   600   |  43224  |\n|   800   |  43988  |\n\n\n**ASYNC: requestData()**\n\n|  Speed  |  Time   |  notes  |\n|:-------:|:-------:|:--------|\n|   100   |  1676   |  default I2C speed  |\n|   200   |  1384   |\n|   400   |  1240   |  datasheet maximum  |\n|   600   |  1188   |\n|   800   |  1168   |\n\n\n**ASYNC: readData()**\n\n|  Speed  |  Time   |  notes  |\n|:-------:|:-------:|:--------|\n|   100   |   832   |  default I2C speed  |\n|   200   |   464   |\n|   400   |   284   |  datasheet maximum  |\n|   600   |   212   |\n|   800   |   188   |\n\nThe numbers indicate that the conversion takes \u003e 40 milliseconds.\nRequesting the measurement and fetching the data \u003c 2.5 milliseconds.\n\nUsing the asynchronous interface frees up a lot of clock cycles.\nGoing beyond 400 KHz (datasheet max) does not save much extra time,\nand should only be used if you are in a need for speed.\n\n\n## Interface\n\n```cpp\n#include \"DHT20.h\"\n```\n\n#### Constructor\n\n- **DHT20(TwoWire \\*wire = \u0026Wire)** constructor, using a specific Wire (I2C bus).\n- **bool begin()** initializer. Returns true if connected.\nThe user must call **Wire.begin()** before calling this function.\n- **bool isConnected()** returns true if the address of the DHT20 can be seen on the I2C bus.\n- **uint8_t getAddress()** returns the (fixed) address - convenience.\n\n#### Core\n\n- **int8_t read()** read the sensor and store the values internally. \nReturns the status of the read which should be 0 == **DHT20_OK**.\n- **float getHumidity()** returns last Humidity read.\nMultiple calls will return same value until a new **read()** is made.\n- **float getTemperature()** returns last Temperature read.\nMultiple calls will return same value until a new **read()** is made.\n\n\n#### Offset\n\n- **void setHumOffset(float offset = 0)** set an offset to calibrate the sensor (1st order).\nDefault offset is 0.\n- **float getHumOffset()** return current humidity offset, default 0.\n- **void setTempOffset(float offset = 0)** set an offset to calibrate the sensor (1st order).\nDefault offset is 0.\n- **float getTempOffset()** return current temperature offset, default 0.\n\n\n#### Asynchronous interface\n\nThere are two timings that need to be considered (from datasheet):\n- time between requests = 1000 ms.\n- time between request and data ready = 80 ms.\n\nThe async interface allows one to continue processing after a **requestData()** has been made. \nNote there should be at least **1000 milliseconds** between subsequent requests.\n\nWith **bool isMeasuring()** one can check if a new measurement is ready.\nAlternative is to delay for up to 80 ms.\nIf so the sensor can be read with **readData()**.\n\nTo interpret the read bits to temperature, humidity and status one needs to call **convert()** as last step.\n\n\n- **int requestData()** signals the sensor to make a new measurement.\nNote there must be at least 1000 milliseconds between requests!\n- **int readData()** does the actual reading of the data.\n- **int convert()** converts the read bits to temperature and humidity.\n\nSee the example **DHT20_async.ino**\n\n\n#### Status\n\n- **uint8_t readStatus()** forced read of the status only.\nThis function blocks a few milliseconds to optimize communication.\n- **bool isCalibrated()** idem, wrapper around **readStatus()**\n- **bool isMeasuring()** idem, wrapper around **readStatus()**\n- **bool isIdle()** idem, wrapper around **readStatus()**\n- **int internalStatus()** returns the internal status of the sensor. (for debug).\n\n|  status bit  |  meaning                   |\n|:------------:|:---------------------------|\n|    7         |  1 = measurement, 0 = idle |\n|  6 - 4       |  unknown                   |\n|    3         |  1 = calibrated, 0 = not   |\n|  2 - 0       |  unknown                   |\n\n\n#### Experimental 0.1.4 resetSensor\n\nUse with care!\n\n- **uint8_t resetSensor()** if at startup the sensor does not return a status of 0x18, \nthree registers 0x1B, 0x1C and 0x1E need to be reset. \nSee datasheet 7.4 Sensor Reading Process, point 1.\nThere is no documentation about the meaning of these registers.\nThe code is based upon example code for the AHT20 (from manufacturer).\n\nThe call is needed to get the **read()** working well so it has been embedded into\nthe read calls. (0.2.0)\n\n\n#### Timing\n\n- **uint32_t lastRead()** last time the sensor is read in milliseconds since start.\n- **uint32_t lastRequest()** last time a request is made to make a measurement.\n\n\n#### Return codes\n\n|  name                        |  value  |  notes  |\n|:-----------------------------|:-------:|:--------|\n|  DHT20_OK                    |    00   |  OK\n|  DHT20_ERROR_CHECKSUM        |   -10   |  values might be OK if they are like recent previous ones.\n|  DHT20_ERROR_CONNECT         |   -11   |  check connection\n|  DHT20_MISSING_BYTES         |   -12   |  check connection\n|  DHT20_ERROR_BYTES_ALL_ZERO  |   -13   |  check connection\n|  DHT20_ERROR_READ_TIMEOUT    |   -14   |\n|  DHT20_ERROR_LASTREAD        |   -15   |  wait 1 second between reads\n\n\n## Future\n\n#### Must\n\n- improve documentation.\n- sync AM2315C developments\n  - see https://github.com/RobTillaart/AM2315C\n- investigate the bug from #8 further\n  (is done in 0.2.1 see issue #8)\n\n\n#### Should\n\n\n#### Could\n\n- improve unit tests.\n- investigate \n  - sensor calibration (website aosong?)\n  - can sensor address be changed?\n- investigate optimizing timing in readStatus()\n  - delay(1) ==\u003e microSeconds(???).\n- connected flag?\n- keep in sync DHT12 ?\n\n\n#### Wont\n\n- **void setIgnoreChecksum(bool = false)** ignore checksum flag speeds up communication a bit\n- **bool getIgnoreChecksum()** get checksum flag. for completeness.\n\n\n## Support\n\nIf you appreciate my libraries, you can support the development and maintenance.\nImprove the quality of the libraries by providing issues and Pull Requests, or\ndonate through PayPal or GitHub sponsors.\n\nThank you,\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtillaart%2Fdht20","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobtillaart%2Fdht20","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtillaart%2Fdht20/lists"}