diff --git a/example/src/main.rs b/example/src/main.rs
index c2b716144f84620ea8a7152b4a2b698ab45ddd4c..e0a9179187be677680777fb45238f439c5882f06 100644
--- a/example/src/main.rs
+++ b/example/src/main.rs
@@ -1,33 +1,46 @@
 #![no_std]
 #![no_main]
 
-use core::fmt::Write;
 use card10_l0dable::*;
+use core::fmt::{self, Write};
 
 main!(main);
 fn main() {
-    writeln!(UART, "Hello from Rust\r").unwrap();
+    let result = run();
+    if let Err(error) = result {
+        writeln!(UART, "error: {}\r", error).unwrap();
+    }
+}
+
+fn run() -> Result<(), Error> {
+    writeln!(UART, "Hello from Rust\r")?;
+
     let bme = BME680::start();
-    let a = BHI160::<Accelerometer>::start();
-    let g = BHI160::<Gyroscope>::start();
-    let o = BHI160::<Orientation>::start();
-    
+    let a = BHI160::<Accelerometer>::start()?;
+    let g = BHI160::<Gyroscope>::start()?;
+    let o = BHI160::<Orientation>::start()?;
+
     let display = Display::open();
     let light = LightSensor::start();
+
     for t in 0..Display::W {
-        writeln!(UART, "BME: {:?}\r", bme.read()).unwrap();
-        writeln!(UART, "A:\r").unwrap();
-        for d in &a.read() {
-            writeln!(UART, " - {:?}\r", d).unwrap();
+        writeln!(UART, "BME: {:?}\r", bme.read())?;
+        writeln!(UART, "A:\r")?;
+
+        for d in &a.read()? {
+            writeln!(UART, " - {:?}\r", d)?;
         }
-        writeln!(UART, "O:\r").unwrap();
-        for d in &o.read() {
-            writeln!(UART, " - {:?}\r", d).unwrap();
+
+        writeln!(UART, "O:\r")?;
+        for d in &o.read()? {
+            writeln!(UART, " - {:?}\r", d)?;
         }
-        writeln!(UART, "G:\r").unwrap();
-        for d in &g.read() {
-            writeln!(UART, " - {:?}\r", d).unwrap();
+
+        writeln!(UART, "G:\r")?;
+        for d in &g.read()? {
+            writeln!(UART, " - {:?}\r", d)?;
         }
+
         display.clear(Color::yellow());
         display.print(160 - t, 10, b"Hello Rust\0", Color::white(), Color::black());
 
@@ -49,8 +62,41 @@ fn main() {
         if b.right_top() {
             display.print(80, 30, b"Reset\0", Color::red(), Color::black());
         }
-        writeln!(UART, "Light: {:?}\r", light.get()).unwrap();
-        
+        writeln!(UART, "Light: {:?}\r", light.get())?;
+
         display.update();
     }
+
+    Ok(())
+}
+
+// -----------------------------------------------------------------------------
+// Error
+// -----------------------------------------------------------------------------
+
+#[derive(Debug)]
+pub enum Error {
+    UartWriteFailed(fmt::Error),
+    SensorInteractionFailed(BHI160Error),
+}
+
+impl From<fmt::Error> for Error {
+    fn from(error: fmt::Error) -> Self {
+        Error::UartWriteFailed(error)
+    }
+}
+
+impl From<BHI160Error> for Error {
+    fn from(error: BHI160Error) -> Self {
+        Error::SensorInteractionFailed(error)
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Error::UartWriteFailed(error) => error.fmt(f),
+            Error::SensorInteractionFailed(error) => error.fmt(f),
+        }
+    }
 }
diff --git a/l0dable/src/bhi160.rs b/l0dable/src/bhi160.rs
index 47be7de65a1244c24413e0f52446c273a40c2c22..63087893f5b57939515c595a5f51ab603b15d416 100644
--- a/l0dable/src/bhi160.rs
+++ b/l0dable/src/bhi160.rs
@@ -1,8 +1,10 @@
-use core::mem::uninitialized;
-use core::marker::PhantomData;
-use super::bindings::*;
+use core::{
+    fmt::{self, Display, Write},
+    marker::PhantomData,
+    mem::MaybeUninit,
+};
 
-use core::fmt::Write;
+use crate::{bindings::*, errno};
 
 pub trait SensorType {
     /// sensor_type in C, sensor_id in Python
@@ -48,43 +50,64 @@ pub struct Sensor<S: SensorType> {
 }
 
 impl<S: SensorType> Sensor<S> {
-    pub fn start() -> Self {
+    fn new(stream_id: i32) -> Self {
+        Self {
+            stream_id,
+            _kind: PhantomData,
+        }
+    }
+
+    pub fn start() -> Result<Self, Error> {
         let mut cfg = bhi160_sensor_config {
             sample_buffer_len: 200,
             sample_rate: 4,
             dynamic_range: 2,
             _padding: [0u8; 8],
         };
-        let stream_id = unsafe {
-            epic_bhi160_enable_sensor(S::sensor_type(), &mut cfg)
-        };
-        Sensor {
-            stream_id,
-            _kind: PhantomData,
+
+        let stream_id = unsafe { epic_bhi160_enable_sensor(S::sensor_type(), &mut cfg) };
+        if stream_id < 0 {
+            let error = match -stream_id {
+                errno::EBUSY => Error::DriverBusy,
+                _ => Error::Unknown(stream_id),
+            };
+
+            return Err(error);
         }
+
+        Ok(Sensor::new(stream_id))
     }
 
-    pub fn read(&self) -> SensorData<S> {
-        let mut buf: [bhi160_data_vector; DATA_MAX] = unsafe {
-            uninitialized()
-        };
-        let n = unsafe {
-            epic_stream_read(self.stream_id, buf.as_mut_ptr() as *mut _, buf.len())
-        };
-        if n < 0 {
-            panic!("epic_stream_read fail");
+    pub fn read(&self) -> Result<SensorData<S>, Error> {
+        let mut buffer = MaybeUninit::<[bhi160_data_vector; DATA_MAX]>::zeroed();
+        let buffer_pointer = buffer.as_mut_ptr() as *mut _;
+
+        let packet_count = unsafe { epic_stream_read(self.stream_id, buffer_pointer, DATA_MAX) };
+        if packet_count < 0 {
+            let error = match -packet_count {
+                errno::ENODEV => Error::SensorUnavailable,
+                errno::EBADF => Error::SensorDescriptorUnknown,
+                errno::EINVAL => Error::InvalidSampleCount,
+                errno::EBUSY => Error::CouldNotAcquireLock,
+                _ => Error::Unknown(packet_count),
+            };
+
+            return Err(error);
         }
-        let n = n as usize;
-        SensorData {
-            buf, n,
+
+        Ok(SensorData {
+            buf: unsafe { buffer.assume_init() },
+            n: packet_count as usize,
             _kind: PhantomData,
-        }
+        })
     }
 }
 
 impl<S: SensorType> Drop for Sensor<S> {
     fn drop(&mut self) {
-        unsafe { epic_bhi160_disable_sensor(S::sensor_type()); }
+        unsafe {
+            epic_bhi160_disable_sensor(S::sensor_type());
+        }
     }
 }
 
@@ -97,11 +120,9 @@ pub struct SensorData<S> {
 impl<'a, S: SensorType> IntoIterator for &'a SensorData<S> {
     type Item = SensorDataItem;
     type IntoIter = SensorDataIter<'a, S>;
+
     fn into_iter(self) -> Self::IntoIter {
-        SensorDataIter {
-            data: self,
-            pos: 0,
-        }
+        SensorDataIter { data: self, pos: 0 }
     }
 }
 
@@ -112,22 +133,27 @@ pub struct SensorDataIter<'a, S> {
 
 impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> {
     type Item = SensorDataItem;
+
     fn next(&mut self) -> Option<Self::Item> {
         while self.pos < self.data.n {
-            let vec = &self.data.buf[self.pos];
             self.pos += 1;
-            if vec.data_type == DATA_TYPE_VECTOR {
-                let item = SensorDataItem {
-                    x: S::convert_single(vec.x),
-                    y: S::convert_single(vec.y),
-                    z: S::convert_single(vec.z),
-                    status: vec.status,
-                };
-                return Some(item);
-            } else {
-                writeln!(crate::UART, "Sensor: skip type {}\r", vec.data_type).unwrap();
+
+            let vec = &self.data.buf[self.pos];
+            if vec.data_type != DATA_TYPE_VECTOR {
+                writeln!(crate::UART, "Sensor: skip type {}\r", vec.data_type).ok();
+                continue;
             }
+
+            let item = SensorDataItem {
+                x: S::convert_single(vec.x),
+                y: S::convert_single(vec.y),
+                z: S::convert_single(vec.z),
+                status: vec.status,
+            };
+
+            return Some(item);
         }
+
         None
     }
 }
@@ -152,3 +178,38 @@ pub struct bhi160_data_vector {
 }
 
 const DATA_TYPE_VECTOR: u8 = 0;
+
+// -----------------------------------------------------------------------------
+// BHI160 Error
+// -----------------------------------------------------------------------------
+
+#[derive(Debug)]
+pub enum Error {
+    /// The descriptor table lock could not be acquired.
+    CouldNotAcquireLock,
+    /// The BHI160 driver is currently busy with other tasks and could not be
+    /// acquired for enabling a sensor.
+    DriverBusy,
+    /// The requested sample `count` is not a multiple of the sensor's sample
+    /// size.
+    InvalidSampleCount,
+    /// The given sensor descriptor is unknown.
+    SensorDescriptorUnknown,
+    /// Sensor is not currently available.
+    SensorUnavailable,
+    /// Not yet documented and therefore unknown error types.
+    Unknown(i32),
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Error::CouldNotAcquireLock => writeln!(f, "Could not acquire BHI160 lock."),
+            Error::DriverBusy => writeln!(f, "The BHI160 Driver is busy."),
+            Error::InvalidSampleCount => writeln!(f, "Sample couldn't invalid."),
+            Error::SensorDescriptorUnknown => writeln!(f, "Unknown BHI160 sensor descriptor."),
+            Error::SensorUnavailable => writeln!(f, "The BHI160 sensor is currently unavailable."),
+            Error::Unknown(id) => writeln!(f, "Unknown error id: {}", id),
+        }
+    }
+}
diff --git a/l0dable/src/lib.rs b/l0dable/src/lib.rs
index d5dd5f463dd622645daeeb7cbbc3ae1b40324aa2..b84440864108d6a9ee1da19f37fa3181a5f326e9 100644
--- a/l0dable/src/lib.rs
+++ b/l0dable/src/lib.rs
@@ -58,6 +58,50 @@ pub mod ctypes {
     pub use core::ffi::c_void;
 }
 
+pub mod errno {
+    #![allow(non_snake_case)]
+    use crate::ctypes::c_int;
+
+    pub const EPERM: c_int = 1; // Operation not permitted
+    pub const ENOENT: c_int = 2; // No such file or directory
+    pub const ESRCH: c_int = 3; // No such process
+    pub const EINTR: c_int = 4; // Interrupted system call
+    pub const EIO: c_int = 5; // I/O error
+    pub const ENXIO: c_int = 6; // No such device or address
+    pub const E2BIG: c_int = 7; // Argument list too long
+    pub const ENOEXEC: c_int = 8; // Exec format error
+    pub const EBADF: c_int = 9; // Bad file number
+    pub const ECHILD: c_int = 10; // No child processes
+    pub const EAGAIN: c_int = 11; // Try again
+    pub const ENOMEM: c_int = 12; //Out of memory
+    pub const EACCES: c_int = 13; //Permission denied
+    pub const EFAULT: c_int = 14; //Bad address
+    pub const ENOTBLK: c_int = 15; //Block device required
+    pub const EBUSY: c_int = 16; //Device or resource busy
+    pub const EEXIST: c_int = 17; //File exists
+    pub const EXDEV: c_int = 18; //Cross-device link
+    pub const ENODEV: c_int = 19; //No such device
+    pub const ENOTDIR: c_int = 20; //Not a directory
+    pub const EISDIR: c_int = 21; //Is a directory
+    pub const EINVAL: c_int = 22; //Invalid argument
+    pub const ENFILE: c_int = 23; //File table overflow
+    pub const EMFILE: c_int = 24; //Too many open files
+    pub const ENOTTY: c_int = 25; //Not a typewriter
+    pub const ETXTBSY: c_int = 26; //Text file busy
+    pub const EFBIG: c_int = 27; //File too large
+    pub const ENOSPC: c_int = 28; //No space left on device
+    pub const ESPIPE: c_int = 29; //Illegal seek
+    pub const EROFS: c_int = 30; //Read-only file system
+    pub const EMLINK: c_int = 31; //Too many links
+    pub const EPIPE: c_int = 32; //Broken pipe
+    pub const EDOM: c_int = 33; //Math argument out of domain of func
+    pub const ERANGE: c_int = 34; //Math result not representable
+    pub const EAFNOSUPPORT: c_int = 97; //Address family not supported by protocol
+    pub const ECONNRESET: c_int = 104; //Connection timed out
+    pub const ETIMEDOUT: c_int = 110; //Connection timed out
+    pub const EINPROGRESS: c_int = 115; //Operation now in progress
+}
+
 pub mod bindings {
     #![allow(non_upper_case_globals)]
     #![allow(non_camel_case_types)]
@@ -86,5 +130,8 @@ pub use fmt_buffer::{FmtBuffer, str_to_cstr};
 mod bme680;
 pub use bme680::BME680;
 mod bhi160;
-pub use bhi160::{Sensor as BHI160, Accelerometer, Orientation, Gyroscope, SensorData as BHI160Data};
+pub use bhi160::{
+    Accelerometer, Error as BHI160Error, Gyroscope, Orientation, Sensor as BHI160,
+    SensorData as BHI160Data,
+};
 pub mod fs;