Neopixel strip & Blinkstick Pro gives input/output error

Hi,

I’m using:
Blickstick Pro with a Neopixel strip.
2m - 60 LED’s.
Python on Mac

I’m running a test script that turns each subsequent LED on and the off. The problem is that it doesn’t always cycle through all 60 LED’s. It stops anywhere from 3/4 of the way through, to the end and throws out the error below.

I’m not using an external power source, BUT i’m only switching on one LED at a time.

[Errno 5] Input/output error
Traceback (most recent call last):
File “./devicetest.py”, line 29, in
bstick.set_color(channel=chan, index=offcounter, name=‘green’)
File “/Library/Python/2.7/site-packages/blinkstick/blinkstick.py”, line 341, in set_color
self._usb_ctrl_transfer(0x20, 0x9, report_id, 0, control_string)
File “/Library/Python/2.7/site-packages/blinkstick/blinkstick.py”, line 246, in _usb_ctrl_transfer
raise BlinkStickException(“Could not communicate with BlinkStick {0} - it may have been removed”.format(self.bs_serial))
blinkstick.blinkstick.BlinkStickException: Could not communicate with BlinkStick BS001433-2.2 - it may have been removed

Could you please post your script? You need to add delays, because BlinkStick needs to send data to the LEDs and while it’s doing that, it can’t communicate to the computer.

Hi, sure, here it is…

#!/usr/bin/python

#Import blinkstick module
from blinkstick import blinkstick
import time

#Find the first BlinkStick
bstick = blinkstick.find_first()

counter = 0
while counter < 60:
        bstick.set_color(channel=0, index=counter, name="black")
        counter = counter+1
        bstick.set_color(channel=0, index=counter, name="green")
        time.sleep(0.2)

You need to wait at least 1/8000002460=1.8 milliseconds after you call set_color before calling the next one. It’s safer to double it. When BlinkStick is sending data to the LEDs, it can’t respond to USB requests. The math is as follows:

  • 800000 is the speed in bytes/second at which data is transmitted to LEDs
  • 24 is the amount of data that needs to be transmitted to each LED, 8 bytes per each channel
  • 60 is the amount of LEDs you are controlling

Your script should look something like this:

#!/usr/bin/python

#Import blinkstick module
from blinkstick import blinkstick
import time

#Find the first BlinkStick
bstick = blinkstick.find_first()

counter = 0
while counter < 60:
        bstick.set_color(channel=0, index=counter, name="black")
        time.sleep(0.003) #<----- You need to add this to wait for black color to be sent to the LEDs 
        counter = counter+1
        bstick.set_color(channel=0, index=counter, name="green")
        time.sleep(0.2)

This actually adds a slight delay when LED is turned off before the next one is turned on. To avoid this, you need to send LED frames, which means that you are sending all LED data at once. I’ve created a BlinkStickPro class for this specific reason. There is a very nice RGB analogue clock example you can find in the wiki which is using this class.

The steps include:

  • create a subclass of blinkstick.BlinkStickPro
  • in the initialization, you can specify delay parameter which defaults to 0.002. You also have to specify how many LEDs are connected to each channel.
  • set_color function will not send data to the device, instead it will store the color data in the internal buffer.
  • when you have all colors set and ready to send to BlinkStick, you need to call send_data_all. It will automatically send the whole LED data at once to the BlinkStick and then wait the amount of time specified in the delay
  • then you can prepare the next frame of data and send it again to the device

The code example to utilize this looks like this (I haven’t tested though :smiley:) :

import time
from blinkstick import blinkstick

class Main(blinkstick.BlinkStickPro):
    def run(self):
        self.off() # sets all LEDs to black and send the data

        try:
            index = 0
            while (True):
                self.clear() # sets all LEDs to black internally
                self.set_color(0, index, 255, 0, 0) #this only sets the color on internal buffer
                #you can add more lines here to control LEDs
                
                self.send_data_all() #sends the data to BlinkStick Pro

                index = index + 1
                if (index == 61):
                    index = 0
        except KeyboardInterrupt:
            self.off()
            return


main = Main(r_led_count=60, delay=0.004)

if main.connect():
    print "Press any key to exit..."
    main.run()
else:
    print "No BlinkSticks found"

print "exit"

Hope this helps :smiley:

1 Like

SPOT ON! Excellent, works like a charm and first time!

I wasn’t aware of the timing limitations. I upped the timer to 0.05 but I did test down to 0.02 and it got a bit unstable and generated errors in the shell.

MANY THANKS!

@marks glad to hear it works. Let me know if you need anything else!