Moving a Servo With Arduino and a Java App
by jjosemayorga in Circuits > Arduino
296 Views, 1 Favorites, 0 Comments
Moving a Servo With Arduino and a Java App
In this Instructable I'll show you how to control the position of a servo witch an Arduino board and a desktop app developed in Java langauage.
This is a non-rigurous English translation for an article in my personal website: https://jjosemayorga.com/controlando-un-servomotor-desde-el-pc/
You can find this and many other interesting projects in my website and my social media.
Twitter ► https://twitter.com/jjosemayorga
Instagram ► https://www.instagram.com/jjosemayorga/
Facebook ► https://www.facebook.com/jjosemayorgau
Youtube ► https://www.youtube.com/@jjosemayorga
TikTok ► https://www.tiktok.com/@jjosemayorga
Supplies
For this project you will need:
- 1 x Arduino UNO rev 3
- 1 x servomotor
- 3 x «jumper» wires
- 1 x protoboard
Wire the Components All Together
In order to make the whole setup work, you just need to wire all the components in the way I show you in this picture.
If you need further explanation on how each element works or why I use them that way, you just need to visit the article on my website and get some instruction on it (it's in Spanish but, if you are not fluent in that language, Google translator will do the job 😉).
Load the Arduino Code
As for the Arduino part, I provide you the Arduino code I've used.
It's a pretty simple of the use of serial communication. Should you need to learn the very basics of this, let me address you again to the article on my website.
Downloads
Build the Java App
Here you will find the Java code.
package servomotorBT;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.metal.MetalSliderUI;
import java.io.*;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Enumeration;
public class servoBT implements SerialPortEventListener
{
int int_posicion=90;
String str_posicion="90";
JFrame marco=new JFrame("Control de servo");
JLabel titulo=new JLabel("<html><font size=10 color=blue>Control de servo por puerto serie</font></html>");
servomotor SV1=new servomotor(int_posicion);
JLabel lbl_puerto=new JLabel("Puerto de conexión:");
String[] str_puerto={"COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9","COM10","COM11","COM12","COM13","COM14","COM15","COM16","COM17","COM18","COM19","COM20","COM21","COM22","COM23","COM24","COM25","COM26"};
JComboBox cmb_puerto=new JComboBox(str_puerto);
JLabel lbl_baudrate=new JLabel("Baud Rate:");
String[] str_baudrate={"4800","9600","19200","38400","57600","115200","234000","460800","921600","1382400"};
JComboBox cmb_baudrate=new JComboBox(str_baudrate);
JButton btn_conectar=new JButton("Conectar");
JButton btn_desconectar=new JButton("Desconectar");
JLabel lbl_conectar=new JLabel(new ImageIcon("lightOFF.png"));
JTextField txt_posicion=new JTextField("90");
JSlider sld_posicion=new JSlider(0,179);
JTextField txt_noticias=new JTextField();
/** The output stream to the port */
private OutputStream output = null;
private BufferedReader input;
SerialPort serialPort;
private String PORT_NAME = "COM1";
/** Milliseconds to block while waiting for port open */
private static final int TIME_OUT = 2000;
/** Default bits per second for COM port. */
private static int DATA_RATE = 9600;
servoBT()
{
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
marco.setIconImage(Toolkit.getDefaultToolkit().createImage("servom_png.png"));
marco.setResizable(false);
GridBagLayout gridbag=new GridBagLayout();
GridBagConstraints gbc=new GridBagConstraints();
marco.setLayout(gridbag);
gbc.insets=new Insets(5,20,5,20);
gbc.gridx=0;
gbc.gridy=0;
gbc.gridwidth=6;
gbc.gridheight=1;
marco.add(titulo,gbc);
gbc.gridx=0;
gbc.gridy=1;
gbc.gridwidth=2;
gbc.gridheight=4;
SV1.setBackground(Color.cyan);
SV1.setSize(400,400);
marco.add(SV1,gbc);
gbc.gridx=2;
gbc.gridy=1;
gbc.gridwidth=1;
gbc.gridheight=1;
gbc.weighty=0.5;
gbc.anchor = GridBagConstraints.SOUTH;
marco.add(lbl_puerto,gbc);
gbc.gridx=3;
gbc.gridy=1;
gbc.gridwidth=1;
gbc.gridheight=1;
gbc.fill=GridBagConstraints.HORIZONTAL;
cmb_puerto.addItemListener(new PORTlistener());
marco.add(cmb_puerto,gbc);
gbc.gridx=2;
gbc.gridy=2;
gbc.gridwidth=1;
gbc.gridheight=1;
gbc.fill=GridBagConstraints.NONE;
gbc.weighty=0.5;
gbc.anchor = GridBagConstraints.NORTH;
marco.add(lbl_baudrate,gbc);
gbc.gridx=3;
gbc.gridy=2;
gbc.gridwidth=1;
gbc.gridheight=1;
cmb_baudrate.addItemListener(new BRlistener());
marco.add(cmb_baudrate,gbc);
gbc.gridx=4;
gbc.gridy=1;
gbc.gridwidth=1;
gbc.gridheight=1;
gbc.anchor = GridBagConstraints.SOUTH;
gbc.fill=GridBagConstraints.HORIZONTAL;
btn_conectar.setName("conectar");
btn_conectar.addMouseListener(new Conectar());
marco.add(btn_conectar,gbc);
gbc.gridx=4;
gbc.gridy=2;
gbc.gridwidth=1;
gbc.gridheight=1;
gbc.anchor = GridBagConstraints.NORTH;
gbc.fill=GridBagConstraints.HORIZONTAL;
btn_desconectar.setName("desconectar");
btn_desconectar.addMouseListener(new Desconectar());
marco.add(btn_desconectar,gbc);
gbc.gridx=5;
gbc.gridy=1;
gbc.gridwidth=1;
gbc.gridheight=2;
gbc.fill=GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.CENTER;
marco.add(lbl_conectar,gbc);
gbc.gridx=2;
gbc.gridy=3;
gbc.gridwidth=4;
gbc.gridheight=1;
gbc.weighty=1.0;
txt_posicion.setPreferredSize( new Dimension( 200, 50 ) );
txt_posicion.setHorizontalAlignment(JTextField.CENTER);
txt_posicion.setEditable(false);
txt_posicion.setBackground(Color.white);
Font font1 = new Font("SansSerif", Font.BOLD, 30);
txt_posicion.setFont(font1);
marco.add(txt_posicion,gbc);
gbc.gridx=2;
gbc.gridy=4;
gbc.gridwidth=4;
gbc.gridheight=1;
sld_posicion.setMajorTickSpacing(20);
sld_posicion.setMinorTickSpacing(5);
sld_posicion.setPaintTicks(true);
sld_posicion.setPaintLabels(true);
sld_posicion.setValue(90);
gbc.fill=GridBagConstraints.HORIZONTAL;
sld_posicion.addChangeListener(new SliderListener());
sld_posicion.addMouseListener(new SliderMListener());
marco.add(sld_posicion,gbc);
gbc.gridx=0;
gbc.gridy=5;
gbc.gridwidth=6;
gbc.gridheight=1;
gbc.fill=GridBagConstraints.HORIZONTAL;
txt_noticias.setEditable(false);
txt_noticias.setBackground(Color.white);
marco.add(txt_noticias,gbc);
marco.pack();
marco.setLocationRelativeTo(null);
marco.setVisible(true);
}
class SliderListener implements ChangeListener
{
@Override
public void stateChanged(ChangeEvent e)
{
int_posicion=sld_posicion.getValue();
str_posicion=String.valueOf(int_posicion);
txt_posicion.setText(str_posicion);
SV1.renovar(int_posicion);
txt_noticias.setText("Posición enviada: "+str_posicion);
sendData(str_posicion);
}
}
class SliderMListener extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
Point p = e.getPoint();
double percent = p.x / ((double) sld_posicion.getWidth());
int range = sld_posicion.getMaximum() - sld_posicion.getMinimum();
double newVal = range * percent;
int result = (int)(sld_posicion.getMinimum() + newVal);
sld_posicion.setValue(result);
}
}
class BRlistener implements ItemListener
{
@Override
public void itemStateChanged(ItemEvent evt)
{
// TODO Auto-generated method stub
JComboBox cb = (JComboBox) evt.getSource();
String str_DATA_RATE = (String) cb.getSelectedItem();
DATA_RATE=Integer.parseInt(str_DATA_RATE);
txt_noticias.setText("BaudRate cambiado a: "+str_DATA_RATE);
}
}
class PORTlistener implements ItemListener
{
@Override
public void itemStateChanged(ItemEvent evt)
{
// TODO Auto-generated method stub
JComboBox cb = (JComboBox) evt.getSource();
String str_PORT_NAME = (String) cb.getSelectedItem();
PORT_NAME=str_PORT_NAME;
txt_noticias.setText("Puerto cambiado a: "+str_PORT_NAME);
}
}
class Conectar extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
Component aux=e.getComponent();
}
public void mouseReleased(MouseEvent e)
{
Component aux=e.getComponent();
{
if(aux.getName().equals("conectar"))
{
initialize();
}
}
}
}
class Desconectar extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
Component aux=e.getComponent();
}
public void mouseReleased(MouseEvent e)
{
Component aux=e.getComponent();
{
if(aux.getName().equals("desconectar"))
{
serialPort.removeEventListener();
serialPort.close();
lbl_conectar.setIcon(new ImageIcon("lightOFF.png"));
txt_noticias.setText("Conexión cerrada");
}
}
}
}
public void initialize()
{
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
// iterate through, looking for the port
while (portEnum.hasMoreElements())
{
CommPortIdentifier currPortId = (CommPortIdentifier)
portEnum.nextElement();
if (PORT_NAME.equals(currPortId.getName()))
{
portId = currPortId;
break;
}
}
if (portId == null)
{
System.out.println("Could not find COM port.");
txt_noticias.setText("Conexión fallida");
return;
}
try
{
// open serial port, and use class name for the appName.
serialPort = (SerialPort) portId.open(this.getClass().getName(),
TIME_OUT);
// set port parameters
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// open the streams
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream()));
output = serialPort.getOutputStream();
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
lbl_conectar.setIcon(new ImageIcon("lightON.png"));
txt_noticias.setText("Conexión establecida");
}
catch (Exception e)
{
System.err.println(e.toString());
}
}
public synchronized void close()
{
if (serialPort != null)
{
serialPort.removeEventListener();
serialPort.close();
}
}
public synchronized void serialEvent(SerialPortEvent oEvent)
{
if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE)
{
try
{
}
catch (Exception e)
{
System.err.println(e.toString());
}
}
}
private void sendData(String data)
{
try
{
output.write(data.getBytes());
} catch (IOException e) {
showError("Error sending data");
//System.exit(ERROR);
}
}
private void showError(String errorMessage)
{
JOptionPane.showMessageDialog(marco,
errorMessage,
"Error",
JOptionPane.ERROR_MESSAGE);
}
public static void main(String[] args)
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e)
{
e.printStackTrace();
}
servoBT app=new servoBT();
}
}
In order to create the dynamic graphic we will need to create an additional class that inherits from tha Canvas class.
package servomotorBT;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class servomotor extends Canvas
{
int pos;
public servomotor(int posicion)
{
pos=posicion;
}
void renovar(int posicion)
{
pos=posicion;
repaint();
}
public void paint(Graphics g)
{
g.setColor(Color.black);
g.fillOval(50, 50, 300, 300);
Graphics2D g2 = (Graphics2D)g;
g2.setStroke(new BasicStroke(16));
g.setColor(Color.white);
g.drawLine((int) (200-175*Math.cos(Math.toRadians(pos))), (int) (200-175*Math.sin(Math.toRadians(pos))), (int) (400-(200-175*Math.cos(Math.toRadians(pos)))), (int) (400-(200-175*Math.sin(Math.toRadians(pos)))));
}
}
This code needs no frameworks, no libraries etc. It would even work just by compiling it in your CMD. As you will see, the interface is very simple.
I add as well the images required by the app. Place them in the right folder of the project.
Try the Whole Setup
Here you have a demo of the project. Should you have any doubt or difficulty to reach an optimal result, you can contact me.