En esta entrega, les guiaré a través de un emocionante proceso para manipular los colores de un LED RGB empleando la técnica de modulación por ancho de pulsos (PWM). Para lograr esto, desarrollaremos una interfaz interactiva en Java, utilizando Sliders como herramientas para ajustar los colores del LED RGB.
Como muchos recordarán, ya hemos explorado el mundo de los LEDs RGB en una publicación anterior: Java + Arduino: Encendiendo un LED RGB desde un programa en nuestra PC. En aquel post, nos enfocamos en crear una interfaz con botones para seleccionar distintos colores. Esta vez, avanzaremos un paso más allá, buscando obtener una gama más amplia de tonalidades a través del ajuste de la intensidad de los colores mediante PWM.
Nuestro primer paso será diseñar y construir la interfaz. Para ello, iniciaremos un proyecto en Java, integraremos un JFrame e incluiremos controles específicos, los cuales serán de gran ayuda especialmente para aquellos que recién comienzan (para más detalles, pueden consultar Cómo crear nuestro primer programa en Java con NetBeans).
Pasando a la fase de programación, empezaremos por importar las bibliotecas RXTX y Arduino, ambas disponibles en este blog: RXTX y Arduino. Cabe destacar que la biblioteca Arduino es una creación propia, cuyo principal objetivo es facilitar la comunicación entre Arduino y Java.
A continuación, presento la declaración de variables:
1 2 3 |
int R = 0, G = 0, B = 0; //Variables para cada //color (Rojo, Verde y Azul) Arduino Arduino = new Arduino(); //Variable para //instanciar la librería Arduino String OutputR, OutputG, OutputB; //Variables que //contendrán los valores a enviar a Arduino |
Aquí está como debe quedar:
Ahora vamos a los métodos.
Haremos un método para el color de fondo del panel que colocamos en la interfaz. Dicho «cuadrito» mostrará el color que en teoría debería mostrar el LED.
El método es el siguiente:
1 2 3 4 5 6 7 |
public void backColor() { R = jSliderR.getValue(); G = jSliderG.getValue(); B = jSliderB.getValue(); Color color = new Color(R, G, B); jPanel1.setBackground(color); } |
Ahora crearemos un método para «setear» los datos que enviaremos a Arduino. Como los valores que mandaremos serán entre 0 y 255 lo que haremos será enviarlos cifra a cifra. Si vamos a mandar por ejemplo el 255, Arduino recibirá el 2, luego el 5 y luego el otro 5. Lo que haremos con Arduino será recibir las centenas, decenas y unidades. El 2 lo multiplicamos por 100, el 5 por 10 y el último 5 lo dejamos así. Luego los sumamos: 200+50+5=255.
Sin embargo para que esto funcione primero hay que mandar las centenas, luego las decenas y por último las unidades. Si mandos un 1, Arduino lo multiplicará por 100 y entonces no obtendremos los resultados deseados. Lo que haremos para evitar que esto suceda es mandar «001». Así que Arduino hará lo siguiente: (0)*100+(0)*10+1=1.
Lo mismo cuando son decenas. Si mandamos el 10, debemos hacerlo de la siguiente manera: «010». Arduino lo interpretará de la siguiente forma: (0)*100+(1)*10+(0)*0=10.
El método que se encargará de esto será el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public void SetData() { OutputR = "1"; OutputG = "2"; OutputB = "3"; if (R < 10) { OutputR = OutputR + "00" + R; } else if (R < 100) { OutputR = OutputR + "0" + R; } else { OutputR = OutputR + R; } if (G < 10) { OutputG = OutputG + "00" + G; } else if (G < 100) { OutputG = OutputG + "0" + G; } else { OutputG = OutputG + G; } if (B < 10) { OutputB = OutputB + "00" + B; } else if (B < 100) { OutputB = OutputB + "0" + B; } else { OutputB = OutputB + B; } } |
Este método prepara las variables para mandárselas a Arduino.
En el método principal iniciamos la comunicaión con Arduino:
1 2 3 4 5 6 7 8 9 10 11 12 |
public Window() { initComponents(); try { Arduino.ArduinoTX("COM6", 2000, 9600); } catch (Exception ex) { Logger.getLogger(Window.class.getName()).log(Level.SEVERE, null, ex); } jLabelR.setText("0 "); jLabelG.setText("0 "); jLabelB.setText("0 "); backColor(); } |
Aquí se muestra como debe quedar:
Ahora veamos como haremos el envío de datos.
Buscaremos la propiedad StateChanged de los Slider.
Aquí el código será el mismo para los tres colores, solo cambiando el nombre de la variable:
1 2 3 4 5 6 7 8 |
jLabelR.setText(jSliderR.getValue() + ""); backColor(); SetData(); try { Arduino.SendData(OutputR); } catch (Exception ex) { Logger.getLogger(Window.class.getName()).log(Level.SEVERE, null, ex); } |
Solo cambiamos la R en el jSlider por la B y la G del azul y verde.
Así debe quedarnos el código:
Con esto estamos listos con Java. Ahora pasamos a Arduino.
El código que vamos a usar es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
// Declaration of variables int u, d, c, p; // Variables for units, tens, hundreds, and processed value int input; // Variable for storing the input value int led; // Variable for LED (unused in this code) int p1, p2, p3; // Variables for LED pin numbers (unused in this code) // Setup function, runs once when the sketch starts void setup() { // Initialize serial communication at 9600 bits per second Serial.begin(9600); } // Loop function, runs over and over again void loop() { // Check if there is any serial input available if (Serial.available()) { // Read the first digit (input command) and convert from ASCII input = Serial.read() - 48; delay(10); // Read the hundreds place digit and convert from ASCII c = Serial.read() - 48; delay(10); // Read the tens place digit and convert from ASCII d = Serial.read() - 48; delay(10); // Read the units place digit and convert from ASCII u = Serial.read() - 48; delay(10); // Combine digits to form the complete number p = (100 * c) + (10 * d) + u; // Control the LED based on the input command if (input == 1) { analogWrite(10, p); // Write to pin 10 if input is 1 } if (input == 2) { analogWrite(11, p); // Write to pin 11 if input is 2 } if (input == 3) { analogWrite(12, p); // Write to pin 12 if input is 3 } } } |
Es un código bastante sencillo. Primero lee cual de los tres LEDs se le va a modificar la luminosidad. Luego lee las centenas, decenas y unidades que conforman el valor de la luminosidad. Por último hace la escritura PWM con analogWrite.
Los archivos de este proyecto se encuentran disponibles en el siguiente enlace:
https://docs.google.com/file/d/0B0hsUkhqWH97Y2hscXU0MEhiTzA/edit?usp=sharing
Acá está el esquema del circuito que usaremos:
Aquí les dejo un video donde se muestra el funcionamiento de este este código:
Espero que les guste.
Saludos.
Hola soy nuevo manejando Arduino, y quería saber si me puedes resolver dos dudas con el código que pones en esta publicación:
1- ¿De que sirve el -48 al final del Serial.read()?
2-No se supone que Arduino recibe los datos en codigo Ascii,¿Por qué en los if’s los comparas con enteros?
De ante mano muchas gracias y saludos.
Efectivamente Arduino recibe los datos en ASCII. Cuando se recibe el 0, Arduino lo interpreta como 48. El 1, 49, el 2, 50…
Si a los datos que recibo les resto 48, cuando reciba un 0(48) entonces… 48-48=0.
49-48= 1
50-48=2
y así sucesivamente. Eso me permite a mi comparar enteros en vez de caracteres
Yo pensé que era parte del Serial.read(); jeje pero ya veo lo que hiciste y observando mas códigos me surgió otra duda, si utilizo ‘1’ osea el dato que me están enviando desde java y lo encierro entre apóstrofos(o comillas simples) automáticamente Arduino identifica su código ASCII.
Por ejemplo:
Me envían el número «3» en forma de String desde java y en Arduino la guardo como una variable
variable=Serial.read();
y despues la utilizo en un if:
if(variable==’3′)
Puedo hacer eso en lugar de poner
if(variable==51) //donde 51 es 3 en codigo ASCII
Cuando hago la comparación con el ‘1’ estoy comparando un caracter. Ahí no hago la transformación ASCII a entero sino que trabajo directamente con el ASCII. Si quieres comparar caracteres usas las comillas, si quieres comparar enteros no lo haces. Con las comillas no necesitas transformar a entero
Muy bien, gracias.
amigo tengo una pregunta , lo que sucede es que desearía implementar éste sistema a una tira LED RGB para alimentarla usé un ULN2003AN ya que trabaja con 12 voltios, pero mi problema vino cuando me di cuenta que ese LED era de katodo común y el que yo tengo es de anodo común que debo hacer para editar la programación soy nuevo en esto por favor si alguien quisiera orientarme en más acerca de esto comunicarse a mi correo [email protected] gracias amigo tus post son muy buenos.
Hola, como hago para enviar un numero desde la interfaz en java y que sea guardada en una variable en arduino, sin interferir con otras variables. He intentado de diversas formas pero no me funciona. Les agradecería mucho cualquier información al respecto.
https://panamahitek.com/enviar-numeros-de-mas-de-un-digito-a-arduino/
También recomiendo ver este post: https://panamahitek.com/arduino-java-facil-y-rapido/
en los archivos en java dice graficas, creo que esta mal
Por que no hace una actualizacion de este video pero ahora con la libreria de PanamaHitek_Arduino 2.8.2 y que funcione para servomotores
Porque nadie me paga por hacerlo
Hola Antony! Estaba siguiendo el tutorial y bajé la nueva versión de la librería (PanamaHitek_Arduino 2.8.2) pero al momento de copiar esta línea en netBeans:
Arduino.ArduinoTX(«COM6», 2000, 9600);
Me aparece un error que se refiere a que la cantidad de parámetros es superior a la que le envío, perfecto, intenté con lo siguiente:
Arduino.arduinoTX(«COM6», 9600);
y al ejecutarlo me aparece un error:
com.panamahitek.ArduinoException: Nombre del puerto – COM3; Nombre del método – arduinoTX(); Tipo de excepción – Puerto no abierto.
Tenés idea de qué es lo que pasa? Qué me recomendas, utilizar una versión anterior de la librería?
Saludos, Juan
Utiliza la nueva. En algún lugar estás intentando abrir el puerto COM3
No tengo el nombre. Ni el número de serie Utilicé una bandeja que me encontre en un tiradero un día y construí la incubadora en base a eso
amigo, una pregunta, porque me marca error en
import Arduino.Arduino ??
el proyecto java en ese link de google docs es de un grafico, no para manejar los leds.
hola, me podrías ayudar con la siguiente cuestión, ¿Puedo guardar los datos que recibe java desde arduino? Utilizo la versión 3.0 de la librería. Estoy recibiendo 8 impresiones por el puerto serial, pero una de esas impresiones no necesita visualizarse en un campo de texto, sino, que sea un indicador para abrir una ventana emergente en Java (JOptionPane).
Gracias