diff --git a/klippy/extras/neopixel.py b/klippy/extras/neopixel.py
index 6988b645c..2a03da00f 100644
--- a/klippy/extras/neopixel.py
+++ b/klippy/extras/neopixel.py
@@ -25,7 +25,7 @@ class PrinterNeoPixel:
     def build_config(self):
         cmd_queue = self.mcu.alloc_command_queue()
         self.neopixel_send_cmd = self.mcu.lookup_command(
-            "neopixel_send oid=%c data=%*s", cq=cmd_queue)
+            "neopixel_send oid=%c data=%u", cq=cmd_queue)
     cmd_SET_NEOPIXEL_help = "Set the color of a neopixel led"
     def cmd_SET_NEOPIXEL(self, params):
         # Parse parameters
@@ -35,11 +35,11 @@ class PrinterNeoPixel:
         red = int(red * 255. + .5)
         blue = int(blue * 255. + .5)
         green = int(green * 255. + .5)
+        val = (green << 16) | (red << 8) | blue
         # Send command
         print_time = self.printer.lookup_object('toolhead').get_last_move_time()
         minclock = self.mcu.print_time_to_clock(print_time)
-        self.neopixel_send_cmd.send([self.oid, [green, red, blue]],
-                                    minclock=minclock)
+        self.neopixel_send_cmd.send([self.oid, val], minclock=minclock)
 
 def load_config_prefix(config):
     return PrinterNeoPixel(config)
diff --git a/src/neopixel.c b/src/neopixel.c
index 41ca98dc7..2fc02dd7e 100644
--- a/src/neopixel.c
+++ b/src/neopixel.c
@@ -35,7 +35,7 @@ timer_from_ns(uint32_t ns)
 }
 
 static int
-send_data(struct neopixel_s *n, uint8_t *data, uint_fast8_t data_len)
+send_data(struct neopixel_s *n, uint32_t data)
 {
     // Make sure at least 50us has passed since last request
     uint32_t last_req_time = n->last_req_time, cur = timer_read_time();
@@ -46,45 +46,42 @@ send_data(struct neopixel_s *n, uint8_t *data, uint_fast8_t data_len)
 
     struct gpio_out pin = n->pin;
     uint32_t expire_time = cur + 0x40000000;
-    while (data_len--) {
-        uint_fast8_t byte = *data++;
-        uint_fast8_t bits = 8;
-        while (bits--) {
-            // Calculate pulse duration
-            uint32_t on, off;
-            if (byte & 0x80) {
-                on = timer_from_ns(700 - 150);
-                off = timer_from_ns(600 - 150);
-            } else {
-                on = timer_from_ns(350 - 150);
-                off = timer_from_ns(800 - 150);
-            }
-            byte <<= 1;
-
-            // Set output high
-            gpio_out_toggle(pin);
-            uint32_t on_start_time = timer_read_time();
-            if (timer_is_before(expire_time, on_start_time))
-                goto fail;
-            cur = on_start_time;
-            while (timer_is_before(cur, on_start_time + on)) {
-                irq_poll();
-                cur = timer_read_time();
-            }
-
-            // Set output low
-            gpio_out_toggle(pin);
-            uint32_t off_start_time = timer_read_time();
-            expire_time = on_start_time + on + timer_from_ns(300);
-            if (timer_is_before(expire_time, off_start_time))
-                goto fail;
-            cur = off_start_time;
-            while (timer_is_before(cur, off_start_time + off)) {
-                irq_poll();
-                cur = timer_read_time();
-            }
-            expire_time = off_start_time + off + timer_from_ns(300);
+    uint_fast8_t bits = 24;
+    while (bits--) {
+        // Calculate pulse duration
+        uint32_t on, off;
+        if (data & 0x800000) {
+            on = timer_from_ns(700 - 150);
+            off = timer_from_ns(600 - 150);
+        } else {
+            on = timer_from_ns(350 - 150);
+            off = timer_from_ns(800 - 150);
         }
+        data <<= 1;
+
+        // Set output high
+        gpio_out_write(pin, 1);
+        uint32_t on_start_time = timer_read_time();
+        if (timer_is_before(expire_time, on_start_time))
+            goto fail;
+        cur = on_start_time;
+        while (timer_is_before(cur, on_start_time + on)) {
+            irq_poll();
+            cur = timer_read_time();
+        }
+
+        // Set output low
+        gpio_out_write(pin, 0);
+        uint32_t off_start_time = timer_read_time();
+        expire_time = on_start_time + on + timer_from_ns(300);
+        if (timer_is_before(expire_time, off_start_time))
+            goto fail;
+        cur = off_start_time;
+        while (timer_is_before(cur, off_start_time + off)) {
+            irq_poll();
+            cur = timer_read_time();
+        }
+        expire_time = off_start_time + off + timer_from_ns(300);
     }
     n->last_req_time = cur;
     return 0;
@@ -99,16 +96,15 @@ command_neopixel_send(uint32_t *args)
 {
     uint8_t oid = args[0];
     struct neopixel_s *n = oid_lookup(oid, command_config_neopixel);
-    uint_fast8_t data_len = args[1];
-    uint8_t *data = (void*)(size_t)args[2];
+    uint32_t data = args[1];
 
     uint_fast8_t retry = 8;
     while (retry--) {
-        int ret = send_data(n, data, data_len);
+        int ret = send_data(n, data);
         if (!ret)
             break;
     }
 }
 #if !CONFIG_MACH_AVR
-DECL_COMMAND(command_neopixel_send, "neopixel_send oid=%c data=%*s");
+DECL_COMMAND(command_neopixel_send, "neopixel_send oid=%c data=%u");
 #endif