Hi!
Have you ever wanted to make a project where you used your computer to control a robot, LEDs or other actuators? Usually you can use a serial monitor to send messages to microcontroller like Arduino by writing them in the console, but let's face it, that's not very practical, a graphical interface is much better.
Well, Processing can be really good for making just that, and I will show you how to make a very basic interface that allows you to control the color of a RGB LED.
First, what you need:For this tutorial I will use Processing 3 and a TM4C launchpad programmed with Energia - so it will be programmed like an Arduino.
The launchpad has a RGB LED in it so no need for an external. If you want to use an external LED, remember to connect through a resistor each color of the LED to a PWM capable pin (for this tutorial, it's best to use a common cathode RGB LED. If it's a common anode you need to reverse the logic a LOW output means the color is ON).
The CommunicationSerial communication will be used to communicate between the launchpad and the computer.
Energia/Arduino and Processing both have a pretty easy to use library for serial.
Both libraries will work the same, with pretty much the only difference being the initial setup. Everytime something is sent to the launchpad, the library catches it and stores it in a bufer and vice-versa. You check how many bytes are in the buffer with a fuction and read them in the order they were received (like a FIFO).
The Energia/Arduino partFor this application I have chosen this design:
For this you are gonna need 3 PWM capable pins. In the launchpad the pins connected to the RGB LED already have a name. They are "RED_LED", "GREEN_LED" and "BLUE_LED". In case you didn't know when using analogWrite(), you don't have to use pinMode().
Before starting the loop where the RGB LED code works, a button will have to be pressed in "setup", to signal the waiting state the red LED will blink every half a second - so you need to set the red LED pin to OUTPUT.
You can see the "while" that waits for the button to be pressed to be a bit big. Well if you simply did this:
Then the LED would indeed blink every 500ms, but the button would be monitored each second. So you would need to be pressing the button at the end of the loop = you would need to hold the button to make sure the code would catch it.
Now we can go to the void loop().
You might wonder why in the diagram of the code that first a byte is sent to the PC. This is just so that the microcontroller sets the timing of each communication - instead of the PC sending every x seconds, the launchpad requests the information and only then the PC sends a packet (here being 3 bytes, the each color value). This was my personal choice.
After sending that request byte, it waits for 3 bytes to be received and then it reads them all and updates the PWM duty - pretty simple right? Only 3 bytes are needed since the PWM in analogWrite() is just 8bits (1 byte), so 1 for each color.
The byte sent is the number 48 (character '0' by the way) for no particular reason, I don't even check the value in the PC side. If you never seen Serial.write(), it's used to send 1 single byte, unlike Serial.print which works for strings, integers, etc.
Now remember, if you replicate this with an external RGB LED and it's a common anode one (common positive), the logic is reversed, you have to do something like this before calling analogWrite():
red = 255 - red;
green = 255 - green;
blue = 255 - blue;
Processing partAll done with the microcontroller side, now the PC part.
Now the processing part takes a bit more work. Luckily there are pretty neat libraries for interfaces and for serial.
If you never used processing you must know at least that like Arduino/Energia there's a void setup() and instead of a void loop() there's a void draw()
For the interface library I used "controlP5" and adapted the ColorWheel example. To import this library go to "Sketch->Import Library->Add Library" and search and instal controlP5.
Now, for this project we're gonna use a Color Wheel. There's an example for that already made that shows it on the screen.
To use it you need to add the library on the top of the code and create an object:
import controlP5.*;
ControlP5 cp5; //with the name cp5 in this case, can be any other name
This is java so apparently cp5 is kinda like a empty name, like a pointer, so you still need to actually create the object like so (sorry never really learnt java).
You do that by adding this in "void setup"
cp5 = new ControlP5( this );
Add the color wheel
For this you use "cp5.addColorWheel".
cp5.addColorWheel("c",200, 200, 150).setRGB(color(128, 0, 255));
This creates a color wheel in the top left corner at coordinates 200,200 with the size 150. The setRGB is another function that takes a integer that represents the initial position of the cursor - color() returns the value or a certain color (each color as a number), this is just to set the cursor to a initial position, in this case is red=128, green = 0 and blue = 255.
"c" is the name of the color wheel. To add more you need to give them another name.
The way this 2 functions calls in a row work I don't quite get it (again not java knowledgeable, sorry D:)
Add to void setup either "fullScreen()" or "size(800,600)" to set the window size, run the code and something should appear.
But you can't quite do anything right? You need void draw().
Add it without nothing in it and you should be able to change the colors by clicking on the wheel.
For some reason without void draw() pretty much nothing will run. Nor you can't block it, you must let it keep running and looping (it's an infinite loop like void loop in Arduino).
To get the RGB values you select on the well on a variable simply use:
int value = cp5.get(ColorWheel.class, "c").getRGB();
This will return the composed value in 8bit format each component. This means that the first 8bits are for the color blue, the second 8bits are for green and the last 8bits are for red. You can extract them like so:
red = (value & 0xFF0000) >> 16;
green = (value & 0xFF00) >> 8;
blue = (value & 0xFF);
(I declared red, green and blue as global integers)
Serial part
Now let's add the serial.
Add on the top of the code:
import processing.serial.*;
Serial myPort; // Create object from Serial class
Now to initialize the port you need to do in void setup:
myPort = new Serial(this, portName, 9600);
portName is the name of your port. If you're on windows it can be something like "COM1" or "COM20". You can either check which port your microcontroller is connected to (like when you do to use the serial monitor) or use the following code since normally you don't have any coms being used besides the one for your MCU:
String portName = Serial.list()[0];
With that you should have this:
I have chosen 9600 for the baudrate like in the Energia code.
Now remember that we needed to wait for a request from the MCU. But we also can't block "draw" from running or else nothing will work. How will we do this? First is first, to check if there was anything received we use "myPort.available()", just like in Arduino/Energia! (difference is the object name, myPort instead of Serial". We just want 1 so if myPort.available() >= 1.
Since we don't want to block draw, instead of a while, we use a "if":
As you can see, like Arduino we use .read and .write to read and send 1 byte. "received" will hold the value read but it didn't really matter checking it, still you need to call myPort.read() to clear the buffer.
Put it all together and you have:
And this, plus the void setup will work to control the RGB LED of the launchpad.
Just connect the launchpad, program it, run the processing code, press the right button on it and watch the LED change color as you click the wheel.
To get a really big wheel and centered I change the void setup:
Making this final result:
I hope you liked it and that I helped you learn something :)
Feel free to ask any questions and until the next project.
Comments