Welcome back to the factory. This week the PiicoDev Color Sensor gets a huge codebase upgrade to make it much more friendly to use to classify colors and we've got some hardware prototypes to show off. Let's do it.
I haven't talked about the PiicoDev Color Sensor in a while and that's because we've been thinking about the tutorials and how we're going to demonstrate how to use this device. The last time we talked about this I gave a brief demo just showing how the RGB values change when you hold an object over the sensor. That's all well and good for measuring the colour components of light but if you want to do something like identify a lime as a lime it's not quite right.
The reason for that is the reflected light that comes off the sample is going to change as it approaches the sensor and if you're working in an RGB colour space the amount of light that's reflected is going to change those RGB values and so it's going to change the colour that you might infer from that point in three-dimensional colour space.
So there was a bit of an aha moment where we decided to convert from RGB data into HSV or hue saturation and value which is kind of like the lightness. Unlike RGB colour which just measures the relative components of red green and blue light that make up a color, HSV separates the colour space into hue which is represented as like an angle in this cylinder, saturation which is like the intensity of the colour how how colorful that colour is, and value which is like the measure of lightness.
And so by working in HSV we can actually just ignore saturation and importantly we can ignore value to identify a color. We just look at the hue dimension to pick out whether it's red green blue orange etc. As you bring thatSample closer and closer, the value is going to change, but the hue is going to stay about the same. And so, by ignoring saturation and value, you can basically ignore the differences that different amounts of light entering the sensor make and just look at the hue.
Of course, the proof is in the pudding, so I've put together a little demo for you. You can see in the shell, I have a label on the left currently that's none because there's no sample, and just the measured hue on the right. We're in a pretty light noisy environment, we've got some lights shining for this video shoot at the moment. But if I bring this object close to the sensor, we can see that the label turns to lime for a hue of about 78, 75, 73. As I move that around, it's pretty consistent that it's either lime or nothing if there's nothing in front of the sensor.
I've got an apple and hold that to the sensor, and we get an apple with a hue of 20. And finally, a carrot with a hue of about 35. This is exactly what I envisaged a sensor like this being used for, some kind of colour sorting project. So, you want that to be as easy as possible to set up. You don't want to have to figure out normalizing red, green, blue components to try to figure out which is the dominant color. It's just not worth it.
This experience where you have just one variable hue on a colour wheel, and then you can just define positions on that wheel that mean certain colors. And so, in this example code right at the top, I just create a Python dictionary. A dictionary in Python is basically a way to associate a label, say apple, with something else. In this case, an integer value 20. So, I've measured my apple, and when I measured it, it had a hue of 20, so I've just put.In the dictionary, there are 20 labelled hues. I sampled the carrot and lime to determine their hues, resulting in a list of labelled hues. To initialize the sensor, I called the initialization function, just like with any other PiicoDev device. When we call the classify hue function, it prints out the label. We pass the list of known hues as an argument and find the closest entry in the dictionary to return the label. We also filter out hues with minimum brightness, so if there is very little reflected light or nothing being held in front, nothing will be returned.
I had come across the idea of different colour spaces before, such as HSV, but I never really understood the motivation behind them until now. I thought they were just for artists or printers, but now I see how they solve this problem. The colour sensor is equipped with a high CRI LED to illuminate a target. If you want to measure reflected color, the LED will illuminate the target and the colour will be reflected back. If you want to measure the colour of a light source, you can disable the LED by connecting the LED pin to ground.
I'm not sure how we missed this initially. It could be because we work in a bright office or because looking at the LED can be dazzling. When you disable it, it may appear that the LED is off, but if you cover it with darkness, you can...See, it's still glowing very slightly. Now, I haven't experienced this before. I'm used to working with MOSFETs where you turn them on, you turn them off, you're done. Maybe you operate in the triode region if you're switching them very quickly or if you're using them as a constant current load or something, but I haven't experienced this kind of situation where the gate of this MOSFET is being pulled to ground, but there's still some leakage. There is clearly some leakage through that MOSFET.
This is the topology that the MOSFET is being used in on this device. We have a 3.3 volt supply flowing through a current limiting resistor. There's our LED, and there's our MOSFET switch. It's being constantly pulled high by a pull-up resistor. There's also a pin connected to the gate so we can pull that down, disable the MOSFET, and disable the LED. But when this gate is being pulled to ground, as I've just shown you, there's still some current flowing through this path.
Here's the BSS138 datasheet, and if we scroll down through to the characteristics, we can find the parameter we're after: IDSS, or the zero gate voltage drain current. This is basically the current that will leak through the MOSFET when you've got it turned off. According to this datasheet, we should be sitting at somewhere between 0.5 and 5 microamps. Oh no, and according to this, we should be at around 100 nanoamps. Now, I'm not quite sure what's going on there. I've measured the voltage across this resistor to infer the current that's flowing through the LED, and we're at somewhere in the order of a couple of microamps. So either my transistor is out of spec, maybe during the prototyping process...This is an early prototype, maybe we left it on the hot plate for too long, not quite sure what's going on there but regardless, I think this represents a bit of a worst-case scenario. Maybe the LED was disabling before, but now through some quirk, there's some leakage. In any case, we really want to use this transistor. We use it in other circuits, we've got heaps of them for assembling our four-channel logic level converter, so there's no good reason to re-specify this part. Maybe it's just prone to a slightly higher leakage than other transistors, and you know, a couple of microamps. This must be an extremely efficient LED to be lighting up, albeit very dimly, at a few microamps by leaking some small amount of current.
This MOSFET is essentially a constant current driver, so there's enough voltage being developed across the LED with that small current to turn the LED on. A simple fix is that we can grab a 4k7 I2C pull-up resistor from somewhere else on the circuit. We can take that 4k7 and just put it in parallel with the LED. This will add some kind of parasitic loading, so of course, the circuit is going to draw slightly more current. Not a big deal if there's an extra milliamp going through this resistor if it means that we can guarantee that the LED will turn off.
By putting this resistor in the path, that small current will preferentially flow through this resistor. So now, the voltage across the LED is going to be in the order of about 0.23 or 0.24 volts, which is well below its forward voltage, and that will guarantee that the LED turns off. We can really easily test that by connecting a 4k resistor across the LED while we're trying to disable it and observe its behavior. So there you have it.Here's an assembled 1x8 GlowBit stick and here we have two soldered together to make one rather long bar graph. The breadboardable 4x4 is assembled with its nice labels on the back and we're yet to assemble the 8x8 one because you know 64 LEDs so it's quite a bit of effort to hand place those LEDs.
But we've had a little bit of an idea about how we could make the tiling of this a bit more friendly. As it stands with these modules, there's many power and ground connections and there's a V-in on one side and a V out on the other side. So they'll tile very easily in one direction, say from left to right.
The idea is if we can make some kind of rotational symmetry to this tile, then we can tile it in more flexible ways without having to use things like air wires between devices. With the current tiling scheme, you could tile a row and then to tile the next row, you would have to wrap that signal with a cable. But if we can create some kind of rotational symmetry with the tile, you can stack it up in a row and then create another row beneath it that will automatically feed that data path through, kind of like in a serpentine path or something. Then potentially we could tile these without any kind of air wiring. That's a really interesting idea.
So we've discussed a few ideas with how we would handle passing that signal along between tiles. Perhaps there would be some solder jumpers involved so the user could be very prescriptive with the way that the data flows through the matrix using a solder jumper.To choose which edge the data passes through, we've also thought about including some resistors so that we can actually create some kind of biasing or preferential data path. This means that if you have two sides soldered, then the data in will be accepted from one of those sides preferentially. The idea behind this is that all you would have to do is solder your matrix together to find the dimensions of the tiling in the code. And because that preferential signal path should be known, the code can just do the rest for you.
We've kind of seen this idea before with say the Adafruit Neopixel matrix. Their 8x8 Neopixel matrix has these large tabs that look like they're just ground tabs. I have seen other versions that have a kind of rotational symmetry that implies some kind of tiling potential. But it would be really interesting to see if we could get that signal path integrated into these kind of like load-bearing tiling tabs that are used to solder the matrices together.
In any case, that's all I have for you today. If you have any ideas on how we could integrate that preferential signal path into an easily tileable matrix so that we can create libraries around that, which kind of break down those coordinates very easily for the user, I'd love to hear your thoughts. We're going to update the colour sensor with that resistor modification to the LED, regenerate the gerbers, and we're going to work on some guides as well. Until next time, thanks for watching.
Makers love reviews as much as you do, please follow this link to review the products you have purchased.