diff --git a/.travis.yml b/.travis.yml
index 2dcac81..703d0c7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,5 +28,6 @@ script:
   - buildExampleSketch LoRaReceiver
   - buildExampleSketch LoRaReceiverCallback
   - buildExampleSketch LoRaSender
+  - buildExampleSketch LoRaSenderNonBlocking
   - buildExampleSketch LoRaSetSpread
   - buildExampleSketch LoRaSetSyncWord
diff --git a/API.md b/API.md
index 07c808e..7fb8c1a 100644
--- a/API.md
+++ b/API.md
@@ -71,7 +71,7 @@ LoRa.beginPacket(implicitHeader);
 
  * `implicitHeader` - (optional) `true` enables implicit header mode, `false` enables explicit header mode (default)
 
-Returns `1` on success, `0` on failure.
+Returns `1` if radio is ready to transmit, `0` if busy or on failure.
 
 ### Writing
 
@@ -98,8 +98,11 @@ Returns the number of bytes written.
 End the sequence of sending a packet.
 
 ```arduino
-LoRa.endPacket()
+LoRa.endPacket();
+
+LoRa.endPacket(async);
 ```
+ * `async` - (optional) `true` enables non-blocking mode, `false` waits for transmission to be completed (default)
 
 Returns `1` on success, `0` on failure.
 
diff --git a/examples/LoRaSenderNonBlocking/LoRaSenderNonBlocking.ino b/examples/LoRaSenderNonBlocking/LoRaSenderNonBlocking.ino
new file mode 100644
index 0000000..0f39077
--- /dev/null
+++ b/examples/LoRaSenderNonBlocking/LoRaSenderNonBlocking.ino
@@ -0,0 +1,35 @@
+#include <SPI.h>
+#include <LoRa.h>
+
+int counter = 0;
+
+void setup() {
+  Serial.begin(9600);
+  while (!Serial);
+
+  Serial.println("LoRa Sender non-blocking");
+
+  if (!LoRa.begin(915E6)) {
+    Serial.println("Starting LoRa failed!");
+    while (1);
+  }
+}
+
+void loop() {
+  // wait until the radio is ready to send a packet
+  while (LoRa.beginPacket() == 0) {
+    Serial.print("waiting for radio ... ");
+    delay(100);
+  }
+
+  Serial.print("Sending packet non-blocking: ");
+  Serial.println(counter);
+
+  // send in async / non-blocking mode
+  LoRa.beginPacket();
+  LoRa.print("hello ");
+  LoRa.print(counter);
+  LoRa.endPacket(true); // true = async / non-blocking mode
+
+  counter++;
+}
diff --git a/src/LoRa.cpp b/src/LoRa.cpp
index 5fb4256..f257887 100644
--- a/src/LoRa.cpp
+++ b/src/LoRa.cpp
@@ -124,6 +124,10 @@ void LoRaClass::end()
 
 int LoRaClass::beginPacket(int implicitHeader)
 {
+  if (isTransmitting()) {
+    return 0;
+  }
+
   // put in standby mode
   idle();
 
@@ -140,22 +144,40 @@ int LoRaClass::beginPacket(int implicitHeader)
   return 1;
 }
 
-int LoRaClass::endPacket()
+int LoRaClass::endPacket(bool async)
 {
   // put in TX mode
   writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
 
-  // wait for TX done
-  while ((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) {
-    yield();
+  if (async) {
+    // grace time is required for the radio
+    delayMicroseconds(150);
+  } else {
+    // wait for TX done
+    while ((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) {
+      yield();
+    }
+    // clear IRQ's
+    writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
   }
 
-  // clear IRQ's
-  writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
-
   return 1;
 }
 
+bool LoRaClass::isTransmitting()
+{
+  if ((readRegister(REG_OP_MODE) & MODE_TX) == MODE_TX) {
+    return true;
+  }
+
+  if (readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) {
+    // clear IRQ's
+    writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
+  }
+
+  return false;
+}
+
 int LoRaClass::parsePacket(int size)
 {
   int packetLength = 0;
diff --git a/src/LoRa.h b/src/LoRa.h
index 7616ebd..a51b47d 100644
--- a/src/LoRa.h
+++ b/src/LoRa.h
@@ -22,7 +22,7 @@ class LoRaClass : public Stream {
   void end();
 
   int beginPacket(int implicitHeader = false);
-  int endPacket();
+  int endPacket(bool async = false);
 
   int parsePacket(int size = 0);
   int packetRssi();
@@ -70,6 +70,7 @@ class LoRaClass : public Stream {
   void implicitHeaderMode();
 
   void handleDio0Rise();
+  bool isTransmitting();
 
   uint8_t readRegister(uint8_t address);
   void writeRegister(uint8_t address, uint8_t value);