Infinite blink Functionality


#1

Hi

Is there a documented way / specific function that will leave a specfic index RGB light in blink mode indefintely. I am looking to be able to set an RGB light to a certain frequency and let it run in the background until I set it to do something else.

Thanks in advance,
Sharif


#2

Nothing built in AFAIK but you could do this with a super basic python script like

import blinkstick
import time

channel = 0
index = 0
frequency = 0.1
r, g, b = 255, 255, 255

stick = blinkstick.find_first()

while True:
    stick.set_color(channel, index, r, g, b)
    time.sleep(frequency)
    stick.set_color(channel, index, 0, 0, 0)
    time.sleep(frequency)

And that’ll just blink the LED on and off until you kill the script.


#4

Hm. I can’t really tell you how you’d integrate it with your robot there but as far as independently blinking lights go, maybe something along the lines of this would work? I’ve never really screwed around with multithreaded python but it might be possible to “listen” for events on your main thread and pass messages back to a separate thread that’s only concerned with blinking.

from blinkstick import blinkstick
import time

bstick = blinkstick.find_first()
count = bstick.get_led_count()

# Doesn't need to be a function, just needs to be a way to poll if something's wrong.
# These just return true periodically.
def traction_issue():
	return time.time() % 3 < 2

def load_issue():
	return time.time() % 5 < 2

def explosion_issue():
	return time.time() % 10 < 1

class Issue():
	def __init__(self, poll, index, freq, color):
		self.poll = poll
		self.index = index
		self.freq = freq
		self.color = color

issues = {
	'traction': Issue(traction_issue, 0, 1.0, [255, 0, 0]),
	'load': Issue(load_issue, 1, 0.5, [255, 255, 0]),
	'explosion': Issue(explosion_issue, 2, 0.1, [0, 255, 0]),
}

while True:
	data = [0] * 3 * count
	now = time.time()

	for key, val in issues.items():
		if val.poll():
			if now % val.freq < val.freq/2:
				data[val.index*3:val.index*3+2] = val.color

	bstick.set_led_data(0, data)
	time.sleep(0.02)

#6

Hey, thanks for the reply.

I decided to take a different approach and have a timer function called freq_callback that is called 100 times a second. I then use differences in time to flash the LEDs on and off at the rate that I desire. The issue that I face now is that I constantly get a USB error number 5. This issue occurs randomly and with no pattern. I may be polling the device too fast or trying to send too many things at once.

#!/usr/bin/env python

import time

import rospy
from blinkstick import blinkstick
from rgb_lights.msg import RGB_light


class RgbListener:
    # Member variables # ---------------------------------
    max_index = 10
    light_to_index_mapping = {'rgb_lights/traction_control': 0,
                            'rgb_lights/Drive_motor_front_right_load': 1,
                            'rgb_lights/Drive_motor_front_left_load': 2,
                            'rgb_lights/Drive_motor_rear_right_load': 3,
                            'rgb_lights/Drive_motor_rear_left_load': 4,
                            }
    # Find the first BlinkStick
    bstick = blinkstick.find_first()
    bstick.set_error_reporting(True)

    def __init__(self):
        self.current_topic = 'init'
        self.current_freq = 0
        self.current_rgb = [0, 0, 0]  # np.zeros(3, dtype =np.uint8)

        self.old_topics = []  # [0]*max_index
        self.old_freqs = []  # [0]*max_index
        self.old_rgbs = []  # array of RGB's
        self.half_periods = []
        self.old_times = [rospy.Time.now().to_sec()] * self.max_index

        self.index_of_timer = -1

    # Member functions # ---------------------------------

    def listener(self):

        rospy.loginfo("Started node      " + self.bstick.get_description())

        rospy.Timer(rospy.Duration(0.01), self.freq_callback)

        for x in self.light_to_index_mapping:
            rospy.Subscriber(x, RGB_light, self.data_in_callback)

        rospy.spin()

    def data_in_callback(self, data):

        self.current_topic = data.RGB_id
        self.current_freq = data.freq
        self.current_rgb = list((int(ord(char)) for char in data.RGB))

        if self.current_topic not in self.old_topics:
            self.old_topics.append(self.current_topic)
            self.old_freqs.append(self.current_freq)
            self.old_rgbs.append(self.current_rgb)
            self.half_periods.append(0.5*(1/float(self.current_freq)))
        else:
            self.index_of_timer = self.old_topics.index(self.current_topic)
            self.old_freqs[self.index_of_timer] = self.current_freq
            self.half_periods[self.index_of_timer] = 0.5 * \
                (1/float(self.current_freq))
            self.old_rgbs[self.index_of_timer] = self.current_rgb

    def freq_callback(self, event):

        for x in range(len(self.old_freqs)):
            #time.sleep(0.00001)
            temp = rospy.Time.now().to_sec()

            t_check = (temp - self.old_times[x])
            #print(self.old_topics[x], self.old_freqs[x], t_check, (self.half_periods[x]))

            if (t_check > self.half_periods[x]):
                self.bstick.set_color(
                    0, x, self.old_rgbs[x][0], self.old_rgbs[x][1], self.old_rgbs[x][2])
            else:
                self.bstick.set_color(0, x, 0, 0, 0)

            #print (t_check.nsecs)
            #print (2*self.half_periods[x])

            if (t_check > (2 * self.half_periods[x])):
                self.old_times[x] = temp


if __name__ == '__main__':
    rospy.init_node('rgb_listener', anonymous=True)
    rgb_obj = RgbListener()
    rgb_obj.listener()

The error message I get is this:


#7


#8

Yeah the blinkstick requires like a 20ms wait between commands. If you don’t give it that, sooner or later it’ll just stop talking to you.

I’ve only glanced at your code but I notice you track old_rgbs. It might be easy to only send an update to the stick if there’s an actual change.


#9

Hi Diff,

Thanks for the reply. I require the LED’s to flash at a specific frequency and so that is why I need to set and unset them repeatedly. I am storing the previous values but I still need to flash the LED’s on and off. I will try add a 20ms delay in the loop and see how it goes. Thanks again.