diff --git a/Cargo.toml b/Cargo.toml
index fb84d20..0cb3b6c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,31 +1,30 @@
 [package]
-name = "sht4x"
-description = "Sensirion SHT4x Driver for Embedded HAL"
-version = "0.1.0"
+name = "sht4x-ng"
+description = "Sensirion SHT4x Driver for Embedded HAL 1.0 with optional async support"
+version = "0.2.2"
 edition = "2021"
 
-authors = ["Christian Meusel <christian.meusel@posteo.de>"]
+authors = [
+    "Christian Meusel <christian.meusel@posteo.de>",
+    "Brian Bustin",
+    "Moritz Bitsch",
+]
 
 license = "MIT OR Apache-2.0"
 
 categories = ["embedded", "hardware-support", "no-std"]
 keywords = ["driver", "embedded-hal-driver", "sensirion", "sht40"]
 
-documentation = "https://docs.rs/sht4x"
-repository = "https://github.com/sirhcel/sht4x"
-readme = "README.md"
-
-exclude = [
-    "/.github/",
-    ".gitignore",
-]
+exclude = ["/.github/", ".gitignore"]
 
 
 [dependencies]
-defmt = { version = "0.3.2", optional = true }
-embedded-hal = "0.2.7"
-fixed = "1.20.0"
-sensirion-i2c = "0.2"
+defmt = { version = "0.3.8", optional = true }
+embedded-hal = "1.0.0"
+embedded-hal-async = { version = "1.0.0", optional = true }
+fixed = "1.27.0"
+sensirion-i2c = "0.3.0"
 
 [features]
 defmt = ["dep:defmt"]
+async = ["dep:embedded-hal-async"]
diff --git a/README.md b/README.md
index b6e8f32..84277e4 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,8 @@
+# Fork of https://github.com/sirhcel/sht4x/
+This is a fork of sirhcel's sht4x library. It brings async to the library and updates it to use embedded_hal 1.0.0. I based this code on [madmo's branch](https://github.com/madmo/sht4x/) as he already did the embedded-hal updating work in [his pull request](https://github.com/sirhcel/sht4x/pull/3).
+
+The fork is hopefully temporary. [I have tried to get these changes pulled into the sht4x repo without success](https://github.com/sirhcel/sht4x/pull/5).
+
 # Sensirion SHT4x Driver for Embedded HAL
 
 A platform agnostic device driver for the Sensirion [SHT4x temperature and
@@ -13,31 +18,31 @@ tested with the SHT40-AD1B so far.
 [![crates.io](https://img.shields.io/crates/v/sht4x.svg)](https://crates.io/crates/sht4x)
 ![Documentation](https://docs.rs/sht4x/badge.svg)
 
-
 ## Features
 
 - Blocking operation
+- Async operation if the `async` feature is specified
+- Uses the latest embedded_hal 1.0.0
 - Supports all commands specified in the
   [datasheet](https://sensirion.com/media/documents/33FD6951/624C4357/Datasheet_SHT4x.pdf)
-- Explicitly borrows `DelayMs` for command execution so that it could be shared
+- Explicitly borrows `DelayNs` for command execution so that it could be shared
   (among multiple sensors)
 - Could be instantiated with the alternative I2C address for the SHT40-BD1B
 - Uses fixed-point arithmetics for converting raw sensor data into measurements
   in SI units
-    - Based on `I16F16` from the [`fixed`](https://gitlab.com/tspiteri/fixed)
-      crate
-    - Allows conversion to floating-point values, if needed
-    - Convenience methods for fixed-point conversions to milli degree Celsius
-      or milli percent relative humidity which are commonly used by drivers for
-      other humidity and temperature sensors from Sensirion
+  - Based on `I16F16` from the [`fixed`](https://gitlab.com/tspiteri/fixed)
+    crate
+  - Allows conversion to floating-point values, if needed
+  - Convenience methods for fixed-point conversions to milli degree Celsius
+    or milli percent relative humidity which are commonly used by drivers for
+    other humidity and temperature sensors from Sensirion
 - Optional support for [`defmt`](https://github.com/knurling-rs/defmt)
 
-
 ## Example
 
 ```rust ignore
-use embedded_hal::blocking::delay::DelayMs;
-use sht4x::Sht4x;
+use embedded_hal::delay::DelayNs;
+use sht4x_ng::Sht4x;
 // Device-specific use declarations.
 
 let mut delay = // Device-specific initialization of delay.
@@ -59,13 +64,11 @@ if let Ok(measurement) = measurement {
 }
 ```
 
-
 ## Related Work
 
 [sensor-temp-humidity-sht40](https://github.com/lc525/sensor-temp-humidity-sht40-rs)
 is another driver for this sensor family.
 
-
 ## License
 
 Licensed under either of
@@ -78,7 +81,6 @@ Licensed under either of
 
 at your discretion.
 
-
 ### Contribution
 
 Unless you explicitly state otherwise, any contribution intentionally submitted
diff --git a/src/commands.rs b/src/commands.rs
index 132e12f..3d78617 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -31,7 +31,7 @@ impl Command {
         }
     }
 
-    pub(crate) fn duration_ms(&self) -> u16 {
+    pub(crate) fn duration_ms(&self) -> u32 {
         // Values rounded up from the maximum durations given in the datasheet
         // table 4, 'System timing specifications'.
         match self {
diff --git a/src/error.rs b/src/error.rs
index c4af875..edf2a0a 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,5 +1,4 @@
-use embedded_hal::blocking::i2c::{Read, Write};
-use sensirion_i2c::i2c;
+use embedded_hal::i2c::I2c;
 
 /// Error conditions from accessing SHT4x sensors.
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -12,16 +11,21 @@ pub enum Error<E> {
     Crc,
 }
 
-impl<E, W, R> From<i2c::Error<W, R>> for Error<E>
-where
-    W: Write<Error = E>,
-    R: Read<Error = E>,
-{
-    fn from(err: i2c::Error<W, R>) -> Self {
+impl<I: I2c> From<sensirion_i2c::i2c::Error<I>> for Error<I::Error> {
+    fn from(err: sensirion_i2c::i2c::Error<I>) -> Self {
         match err {
-            i2c::Error::Crc => Error::Crc,
-            i2c::Error::I2cRead(e) => Error::I2c(e),
-            i2c::Error::I2cWrite(e) => Error::I2c(e),
+            sensirion_i2c::i2c::Error::Crc => Error::Crc,
+            sensirion_i2c::i2c::Error::I2cRead(e) => Error::I2c(e),
+            sensirion_i2c::i2c::Error::I2cWrite(e) => Error::I2c(e),
+        }
+    }
+}
+
+#[cfg(feature = "async")]
+impl<E> From<sensirion_i2c::crc8::Error> for Error<E> {
+    fn from(value: sensirion_i2c::crc8::Error) -> Self {
+        match value {
+            sensirion_i2c::crc8::Error::CrcError => Error::Crc,
         }
     }
 }
diff --git a/src/sht4x.rs b/src/sht4x.rs
index a49bf7d..5ae13b8 100644
--- a/src/sht4x.rs
+++ b/src/sht4x.rs
@@ -4,11 +4,12 @@ use crate::{
     types::{Address, HeatingDuration, HeatingPower, Measurement, Precision, SensorData},
 };
 use core::marker::PhantomData;
-use embedded_hal::blocking::{
-    delay::DelayMs,
-    i2c::{Read, Write, WriteRead},
-};
-use sensirion_i2c::i2c;
+
+#[cfg(not(feature = "async"))]
+use embedded_hal::{delay::DelayNs, i2c::I2c};
+
+#[cfg(feature = "async")]
+use embedded_hal_async::{delay::DelayNs, i2c::I2c};
 
 const RESPONSE_LEN: usize = 6;
 
@@ -46,10 +47,9 @@ impl From<Precision> for Command {
     }
 }
 
-impl<I, D, E> Sht4x<I, D>
+impl<I: I2c, D> Sht4x<I, D>
 where
-    I: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
-    D: DelayMs<u16>,
+    D: DelayNs,
 {
     /// Creates a new driver instance using the given I2C bus. It configures the default I2C
     /// address 0x44 used by most family members.
@@ -78,6 +78,7 @@ where
         self.i2c
     }
 
+    #[cfg(not(feature = "async"))]
     /// Activates the heater and performs a measurement returning measurands in SI units.
     ///
     /// **Note:** The heater is designed to be used up to 10 % of the sensor's lifetime. Please
@@ -89,12 +90,31 @@ where
         power: HeatingPower,
         duration: HeatingDuration,
         delay: &mut D,
-    ) -> Result<Measurement, Error<E>> {
+    ) -> Result<Measurement, Error<I::Error>> {
         let raw = self.heat_and_measure_raw(power, duration, delay)?;
 
         Ok(Measurement::from(raw))
     }
 
+    #[cfg(feature = "async")]
+    /// Activates the heater and performs a measurement returning measurands in SI units.
+    ///
+    /// **Note:** The heater is designed to be used up to 10 % of the sensor's lifetime. Please
+    /// check the
+    /// [datasheet](https://sensirion.com/media/documents/33FD6951/624C4357/Datasheet_SHT4x.pdf),
+    /// section 4.9 _Heater Operation_ for details.
+    pub async fn heat_and_measure(
+        &mut self,
+        power: HeatingPower,
+        duration: HeatingDuration,
+        delay: &mut D,
+    ) -> Result<Measurement, Error<I::Error>> {
+        let raw = self.heat_and_measure_raw(power, duration, delay).await?;
+
+        Ok(Measurement::from(raw))
+    }
+
+    #[cfg(not(feature = "async"))]
     /// Activates the heater and performs a measurement returning raw sensor data.
     ///
     /// **Note:** The heater is designed to be used up to 10 % of the sensor's lifetime. Please
@@ -106,7 +126,7 @@ where
         power: HeatingPower,
         duration: HeatingDuration,
         delay: &mut D,
-    ) -> Result<SensorData, Error<E>> {
+    ) -> Result<SensorData, Error<I::Error>> {
         let command = Command::from((power, duration));
 
         self.write_command_and_delay_for_execution(command, delay)?;
@@ -116,22 +136,58 @@ where
         Ok(raw)
     }
 
+    #[cfg(feature = "async")]
+    /// Activates the heater and performs a measurement returning raw sensor data.
+    ///
+    /// **Note:** The heater is designed to be used up to 10 % of the sensor's lifetime. Please
+    /// check the
+    /// [datasheet](https://sensirion.com/media/documents/33FD6951/624C4357/Datasheet_SHT4x.pdf),
+    /// section 4.9 _Heater Operation_ for details.
+    pub async fn heat_and_measure_raw(
+        &mut self,
+        power: HeatingPower,
+        duration: HeatingDuration,
+        delay: &mut D,
+    ) -> Result<SensorData, Error<I::Error>> {
+        let command = Command::from((power, duration));
+
+        self.write_command_and_delay_for_execution(command, delay)
+            .await?;
+        let response = self.read_response().await?;
+        let raw = self.sensor_data_from_response(&response);
+
+        Ok(raw)
+    }
+
+    #[cfg(not(feature = "async"))]
     /// Performs a measurement returning measurands in SI units.
     pub fn measure(
         &mut self,
         precision: Precision,
         delay: &mut D,
-    ) -> Result<Measurement, Error<E>> {
+    ) -> Result<Measurement, Error<I::Error>> {
         let raw = self.measure_raw(precision, delay)?;
         Ok(Measurement::from(raw))
     }
 
+    #[cfg(feature = "async")]
+    /// Performs a measurement returning measurands in SI units.
+    pub async fn measure(
+        &mut self,
+        precision: Precision,
+        delay: &mut D,
+    ) -> Result<Measurement, Error<I::Error>> {
+        let raw = self.measure_raw(precision, delay).await?;
+        Ok(Measurement::from(raw))
+    }
+
+    #[cfg(not(feature = "async"))]
     /// Performs a measurement returning raw sensor data.
     pub fn measure_raw(
         &mut self,
         precision: Precision,
         delay: &mut D,
-    ) -> Result<SensorData, Error<E>> {
+    ) -> Result<SensorData, Error<I::Error>> {
         let command = Command::from(precision);
 
         self.write_command_and_delay_for_execution(command, delay)?;
@@ -141,8 +197,26 @@ where
         Ok(raw)
     }
 
+    #[cfg(feature = "async")]
+    /// Performs a measurement returning raw sensor data.
+    pub async fn measure_raw(
+        &mut self,
+        precision: Precision,
+        delay: &mut D,
+    ) -> Result<SensorData, Error<I::Error>> {
+        let command = Command::from(precision);
+
+        self.write_command_and_delay_for_execution(command, delay)
+            .await?;
+        let response = self.read_response().await?;
+        let raw = self.sensor_data_from_response(&response);
+
+        Ok(raw)
+    }
+
+    #[cfg(not(feature = "async"))]
     /// Reads the sensor's serial number.
-    pub fn serial_number(&mut self, delay: &mut D) -> Result<u32, Error<E>> {
+    pub fn serial_number(&mut self, delay: &mut D) -> Result<u32, Error<I::Error>> {
         self.write_command_and_delay_for_execution(Command::SerialNumber, delay)?;
         let response = self.read_response()?;
 
@@ -154,15 +228,53 @@ where
         ]))
     }
 
+    #[cfg(feature = "async")]
+    /// Reads the sensor's serial number.
+    pub async fn serial_number(&mut self, delay: &mut D) -> Result<u32, Error<I::Error>> {
+        self.write_command_and_delay_for_execution(Command::SerialNumber, delay)
+            .await?;
+        let response = self.read_response().await?;
+
+        Ok(u32::from_be_bytes([
+            response[0],
+            response[1],
+            response[3],
+            response[4],
+        ]))
+    }
+
+    #[cfg(not(feature = "async"))]
+    /// Performs a soft reset of the sensor.
+    pub fn soft_reset(&mut self, delay: &mut D) -> Result<(), Error<I::Error>> {
+        self.write_command_and_delay_for_execution(Command::SoftReset, delay)
+    }
+
+    #[cfg(feature = "async")]
     /// Performs a soft reset of the sensor.
-    pub fn soft_reset(&mut self, delay: &mut D) -> Result<(), Error<E>> {
+    pub async fn soft_reset(&mut self, delay: &mut D) -> Result<(), Error<I::Error>> {
         self.write_command_and_delay_for_execution(Command::SoftReset, delay)
+            .await
     }
 
-    fn read_response(&mut self) -> Result<[u8; RESPONSE_LEN], Error<E>> {
+    #[cfg(not(feature = "async"))]
+    fn read_response(&mut self) -> Result<[u8; RESPONSE_LEN], Error<I::Error>> {
         let mut response = [0; RESPONSE_LEN];
 
-        i2c::read_words_with_crc(&mut self.i2c, self.address.into(), &mut response)?;
+        sensirion_i2c::i2c::read_words_with_crc(&mut self.i2c, self.address.into(), &mut response)?;
+
+        Ok(response)
+    }
+
+    #[cfg(feature = "async")]
+    async fn read_response(&mut self) -> Result<[u8; RESPONSE_LEN], Error<I::Error>> {
+        let mut response = [0; RESPONSE_LEN];
+
+        self.i2c
+            .read(self.address.into(), &mut response)
+            .await
+            .map_err(Error::I2c)?;
+
+        sensirion_i2c::crc8::validate(&response)?;
 
         Ok(response)
     }
@@ -174,16 +286,36 @@ where
         }
     }
 
+    #[cfg(not(feature = "async"))]
     fn write_command_and_delay_for_execution(
         &mut self,
         command: Command,
         delay: &mut D,
-    ) -> Result<(), Error<E>> {
+    ) -> Result<(), Error<I::Error>> {
         let code = command.code();
 
-        i2c::write_command_u8(&mut self.i2c, self.address.into(), code).map_err(Error::I2c)?;
+        sensirion_i2c::i2c::write_command_u8(&mut self.i2c, self.address.into(), code)
+            .map_err(Error::I2c)?;
         delay.delay_ms(command.duration_ms());
 
         Ok(())
     }
+
+    #[cfg(feature = "async")]
+    async fn write_command_and_delay_for_execution(
+        &mut self,
+        command: Command,
+        delay: &mut D,
+    ) -> Result<(), Error<I::Error>> {
+        let code = command.code();
+
+        self.i2c
+            .write(self.address.into(), &code.to_be_bytes())
+            .await
+            .map_err(Error::I2c)?;
+
+        delay.delay_ms(command.duration_ms()).await;
+
+        Ok(())
+    }
 }