Raspberry Pi Pico Colour Changer.
by mr_fid in Circuits > Raspberry Pi
2698 Views, 7 Favorites, 0 Comments
Raspberry Pi Pico Colour Changer.
This is my first Raspberry Pi Pico project. This is the latest offering from raspberry pi and this time its not a SBC its a micro-controller. This is a new direction for the raspberry pi foundation and they have gone into it wholeheartedly by producing there own chip. But what do i think about it? well lets start with a simple project and see how it goes!
This is basically a colour maker. You have 4 full colour (RGB) LED's and 3 variable resistors, you select the required amount of each colour on the 3 outer LED's and the resultant mix is shown om the middle LED. And The LED light is defused by Ping Pong balls!
Supplies
4 * RGB LED's
3mm ply wood
6 * 330ohm resistors
raspberry pi Pico.
3 * 10Kohm pots
4 * Ping Pong balls
3 * 200mm posts and screws.
The Build.
Please see the video for the quick build!
But here are the steps.
- Print out plan and stick to plywood using stick glue.
- Pin two bits of plywood together and cut out.
- Drill the 3mm post holes and then pilot all other holes 6mm.
- Separate the two bits of ply and drill one bit 100 for the Pots and the other 20mm for the ping pong balls.
- Clean up around the edges with sand paper.
- Fit the posts to the ball side then stick down the ping pong balls using hot glue. Mind where the seams are.
- Melt a hole into the ping pong balls using a soldering iron.
- Fit the LED's and wire up the required legs. Only one colour around the outside and all in the middle.
- Fit the pots to the other side and wire up all the connections.
- Place resistors in each one of the LED coloured wires.
- Crimp dupont terminals to the ends of the wires
- connect the Pico and get programming.
More Detailed Wiring!
Some people might need a bit more detail and also some handy construction tips so please read on!
When I build any project I always try to keep things tidy and simple, so firstly lets have a look at the 3 variable resistors. Each one of the resistors needs a ground wire and a 3.3v wire so it makes common sense to make these common connections at the pots. If you think about it you could make all the connections at the Pico but then you would have 3 ground wires and 3 positive wires along with the 3 analogue input wires. So it makes sense to common these wire up at the pots.
I use a similar principle when I wire up the LED's. I have commoned up all the cathodes.
This might seem a bit overkill but think about it this way if you were to bring all the wires to the Pico you would have 7 ground wires! and 3 power wires. Now the Pico does have 8 ground connections so you could get away with that, however the Pico only has one 3.3V pin so things would get crowed at that pin very quickly!
Lastly I have put the resistors inline with the LED wires, this keeps it nice and neat and has nothing to do with the fact that I forgot about them!
Connect It All Together.
At this stage I fixed the two half's together and fed the wires up the hole in the middle of the pot board.
I prefer to use DuPont connections and have a crimping tool able to make these connections, you can see a close up of the connector. Once crimped I then heatsrink over the connectors. The best bit about using this style of connector is that if you get the wire in the wrong place you can just pull it off and connect it to anther pin.
The Pico only have 3 analogue pins so that's where the pots will be connected.
Pico Pin 34, GP28 (AD2), Red variable resistor.
Pico Pin 32, GP27 (AD1), Green variable resistor.
Pico Pin 31, GP26 (AD0), Red variable resistor.
Pico Pin 38, GND, Pots common Ground.
Pico Pin 36, 3.3V(OUT), Pots common positive.
Next we move onto the LED's and at this point its useful to explain that the Pico has options for each PWM input, most of the PWM pins appear in tow different locations on the Pico, and more helpfully both sides of the board. Because I need to drive two of each LED I have chosen to use the same pair for driving the LED's for example the Blue LED's are connected to Pico Pin 1, GP0 (PWM_A[0]) and Pico Pin 21, GP16 (PWM_A[0]) the same PWM but on different pins.
Pico Pin 1, GP0 (PWM_A[0]) Blue LED
Pico Pin 21, GP16 (PWM_A[0]) Blue LED
Pico Pin 2, GP1 (PWM_B[0]) Red LED
Pico Pin22, GP17 (PWM_B[0]) Red LED
Pico Pin 4, GP18 (PWM_A[1]) Green LED
Pico Pin 24, GP18 (PWM_A[1]) Green LED
Program Problems.
This should have been the easy bit, but I had a few problems so I will share them with you.
I am using MicroPython on the Pico and the program should have been a simple ADC read followed with a write to a PWM pin. Simple really! but straight away I had some weird problems.
Firstly when I wound up the variable resistors to max one of the pair of LED's would turn off? now I should point out at this stage I was using a different PWM pin for each LED and reading the variable resistors twice for each LED so in total I was reading and updating 6 LED's and maybe this wasn't I good idea? It looked like to me that the analogue reading was somehow going to a value more than a 16 bit number and hence the PWM received a very low value. But I cant really be sure because adding a delay by printing the analogue value to the screen solved the problem. Then I decided to pair up the PWM as explained before.
Next I spotted that on the lowest variable resistor value the LED's were still all glowing slightly. Printing the analogue on the screen proved this be returning numbers around 300! This seemed very high but there is another strange thing happening here. basically the analogue reading is a 12 bit number but for reasons I don't understand it is converted to a 16 bit number. What this means is that the error on zero was about 24 bits and this was been magnified by 16 times to give an error of 384 bits. either way this error equates to a voltage of around 20mV. The data sheet for the Pico explains "there will be an inherent offset of about 150μA*200 = ~30mV" Not ideal but there you go.
At this stage I thought I would use a different command in the program but quickly found that this didn't work! It turns out that the book (Get started with MicroPython on Raspberry Pi Pico) had an error and has since been recalled!
The First Program (that Didn't Work!)
#This was the first program, and it doesn't work. #at max setting on the pot one of the red and green LED's #turn off. import machine import utime ledRed = machine.PWM(machine.Pin(18)) ledRedCentre = machine.PWM(machine.Pin(21)) ledBlue = machine.PWM(machine.Pin(17)) ledBlueCentre = machine.PWM(machine.Pin(20)) ledGreen = machine.PWM(machine.Pin(16)) ledGreenCentre = machine.PWM(machine.Pin(19)) potBlue = machine.ADC(28) potRed = machine.ADC(27) potGreen = machine.ADC(26) ledRed.freq(1000) ledBlue.freq(1000) ledGreen.freq(1000) while True: ledRed.duty_u16(potRed.read_u16()) ledBlue.duty_u16(potBlue.read_u16()) ledGreen.duty_u16(potGreen.read_u16()) ledRedCentre.duty_u16(potRed.read_u16()) ledBlueCentre.duty_u16(potBlue.read_u16()) ledGreenCentre.duty_u16(potGreen.read_u16())
The Second Program (highlighted Another Problem!)
# The second program got rid of the LED's turning off # at high pot readings, but also showed that they weren't # turning off at zero voltage. # i also changed PWM to Share the same pin. import machine ledRed = machine.PWM(machine.Pin(18)) ledRed.freq(1000) ledBlue = machine.PWM(machine.Pin(17)) ledBlue.freq(1000) ledGreen = machine.PWM(machine.Pin(16)) ledGreen.freq(1000) ledRedCentre = machine.PWM(machine.Pin(2)) ledBlueCentre = machine.PWM(machine.Pin(1)) ledGreenCentre = machine.PWM(machine.Pin(0)) potRed = machine.ADC(27) potBlue = machine.ADC(28) potGreen = machine.ADC(26) while True: ledRed.duty_u16(potRed.read_u16()) ledBlue.duty_u16(potBlue.read_u16()) ledGreen.duty_u16(potGreen.read_u16())
The Fully Working Program.
# Working program which uses a routine # to read the pots and correct the offset. import machine ledRed = machine.PWM(machine.Pin(18)) ledRed.freq(1000) ledBlue = machine.PWM(machine.Pin(17)) ledBlue.freq(1000) ledGreen = machine.PWM(machine.Pin(16)) ledGreen.freq(1000) ledRedCentre = machine.PWM(machine.Pin(1)) ledBlueCentre = machine.PWM(machine.Pin(2)) ledGreenCentre = machine.PWM(machine.Pin(0)) def readVoltage(colour): voltage = (colour.read_u16()) voltage = voltage - 500 if voltage < 0: voltage = 0 return voltage potRed = machine.ADC(27) potBlue = machine.ADC(28) potGreen = machine.ADC(26) while True: ledRed.duty_u16(readVoltage(potRed)) ledBlue.duty_u16(readVoltage(potBlue)) ledGreen.duty_u16(readVoltage(potGreen))
Automatic Programs.
# This is an automatic program which sweeps # up and down the colours of each LED. # For example Green starts HI and and Blue # LOW they fade up and down respectfully while # Red remains off, then once the Green is LOW # Red fades up while Blue fades down..... so on. import machine ledRed = machine.PWM(machine.Pin(18)) ledRed.freq(1000) ledBlue = machine.PWM(machine.Pin(17)) ledBlue.freq(1000) ledGreen = machine.PWM(machine.Pin(16)) ledGreen.freq(1000) ledRedCentre = machine.PWM(machine.Pin(1)) ledBlueCentre = machine.PWM(machine.Pin(2)) ledGreenCentre = machine.PWM(machine.Pin(0)) RBG = [0,0,0] potRed = machine.ADC(27) potBlue = machine.ADC(28) potGreen = machine.ADC(26) def pickColour(number): if number < 21845: RBG = ((21845 - number) * 3,0,number *3) return RBG if number < 43690: number = number - 21845 RBG = (0,number * 3,(21845 - number)*3) return RBG number = number - 43690 RBG = (number * 3,(21845 - number) * 3,0) return RBG a = 0 while True: RBG=pickColour(a) a = a + 1 if a == 65535: a = 0 ledRed.duty_u16(RBG[0]) ledBlue.duty_u16(RBG[1]) ledGreen.duty_u16(RBG[2])second program uses sin waves. all the LED's are phased 120 degrees apart. This means that you will never get a pure colour in the middle.
# This uses a sin function to fade up and down # each LED which are out of phase by 120 degress. # this means you will never get a pure colour # in the middle and more mixing of all 3. import machine import math ledRed = machine.PWM(machine.Pin(18)) ledRed.freq(1000) ledBlue = machine.PWM(machine.Pin(17)) ledBlue.freq(1000) ledGreen = machine.PWM(machine.Pin(16)) ledGreen.freq(1000) ledRedCentre = machine.PWM(machine.Pin(1)) ledBlueCentre = machine.PWM(machine.Pin(2)) ledGreenCentre = machine.PWM(machine.Pin(0)) RBG = [0,0,0] def sinColour(number): a = (math.sin(math.radians(number))+1)*32768 b = (math.sin(math.radians(number+120))+1)*32768 c = (math.sin(math.radians(number+240))+1)*32768 RBG = (int(a),int(b),int(c)) return RBG a = 0 while True: RBG = sinColour(a) a = a + 0.01 if a == 360: a = 0 ledRed.duty_u16(RBG[0]) ledBlue.duty_u16(RBG[1]) ledGreen.duty_u16(RBG[2])