diff --git a/py/binary.c b/py/binary.c
index e5518c4bf013dc42f92d901f9eb6c13f04fea82e..7a1597161d5247fc7f6386703bd5a03d25ed91ba 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -194,6 +194,14 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
     } else if (val_type == 'S') {
         const char *s_val = (const char*)(mp_uint_t)val;
         return mp_obj_new_str(s_val, strlen(s_val), false);
+#if MICROPY_PY_BUILTINS_FLOAT
+    } else if (val_type == 'f') {
+        union { uint32_t i; float f; } fpu = {val};
+        return mp_obj_new_float(fpu.f);
+    } else if (val_type == 'd') {
+        union { uint64_t i; double f; } fpu = {val};
+        return mp_obj_new_float(fpu.f);
+#endif
     } else if (is_signed(val_type)) {
         if ((long long)MP_SMALL_INT_MIN <= val && val <= (long long)MP_SMALL_INT_MAX) {
             return mp_obj_new_int((mp_int_t)val);
@@ -249,6 +257,27 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
         case 'O':
             val = (mp_uint_t)val_in;
             break;
+#if MICROPY_PY_BUILTINS_FLOAT
+        case 'f': {
+            union { uint32_t i; float f; } fp_sp;
+            fp_sp.f = mp_obj_get_float(val_in);
+            val = fp_sp.i;
+            break;
+        }
+        case 'd': {
+            union { uint64_t i64; uint32_t i32[2]; double f; } fp_dp;
+            fp_dp.f = mp_obj_get_float(val_in);
+            if (BYTES_PER_WORD == 8) {
+                val = fp_dp.i64;
+            } else {
+                int be = struct_type == '>';
+                mp_binary_set_int(sizeof(uint32_t), be, p, fp_dp.i32[MP_ENDIANNESS_BIG ^ be]);
+                p += sizeof(uint32_t);
+                val = fp_dp.i32[MP_ENDIANNESS_LITTLE ^ be];
+            }
+            break;
+        }
+#endif
         default:
             // we handle large ints here by calling the truncated accessor
             if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
diff --git a/tests/float/float_struct.py b/tests/float/float_struct.py
new file mode 100644
index 0000000000000000000000000000000000000000..8ad0e492c6c9ef31da9491cdef24141affd377dd
--- /dev/null
+++ b/tests/float/float_struct.py
@@ -0,0 +1,12 @@
+# test struct package with floats
+
+import struct
+
+i = 1. + 1/2
+# TODO: it looks like '=' format modifier is not yet supported
+# for fmt in ('f', 'd', '>f', '>d', '<f', '<d', '=f', '=d'):
+for fmt in ('f', 'd', '>f', '>d', '<f', '<d'):
+    x = struct.pack(fmt, i)
+    v = struct.unpack(fmt, x)[0]
+    print('%2s: %.17f - %s' % (fmt, v, (i == v) and 'passed' or 'failed'))
+