Skip to content

14. Interface and Application Programming

For this week we had to:

  • Group assignment:

    • Compare as many tool options as possible.

    • Document your work on the group work page and reflect on your individual page what you learned.

  • Individual assignment

    • Write an application that interfaces a user with input and/or output device(s) on a board that you made.

Group assignment

As part of our group assignment, we compared the creation of interfaces using several tools. You can see our group assignment in more detail here.

The most notable for me were Python and Processing, and here’s why:

  1. Programming Language:

    • Python is a versatile programming language that can be used for various tasks, including creating a user interface.

    • Processing is specifically designed for visual arts and interactive graphics.

  2. Libraries and Tools:

    • Python utilizes different libraries for interface creation, such as Tkinter, PyQt, or PySide.

    • Processing provides its own functions and tools for interface development.

  3. Flexibility and Capabilities:

    • Python offers great flexibility and powerful tools for customizing and managing the interface, including widget placement, event handling, and integration with other Python modules.

    • Processing simplifies the creation of visual projects through a straightforward and intuitive syntax and API for graphics operations.

  4. Purpose of Use:

    • Python is commonly used for developing general applications, including GUIs.

    • Processing is focused on creating visual projects and facilitates working with graphics and interactivity.

Both approaches have their advantages, and the choice depends on the specific project requirements. Python offers greater flexibility and the capabilities of a general-purpose programming language, while Processing streamlines the creation of visual projects through its simple syntax and specialized tools for graphics and interactivity.

Individual assignment

As a program for creating an interface, I decided to use Processsing. Having studied this program a little, I found out that:

  1. Processing is an interface creation program that uses the same engine as the Arduino IDE. It is easy to use and supports many platforms.

  2. Processing has a simple and intuitive interface that allows you to quickly create interactive applications and visualizations.

  3. The program provides access to many libraries that can be used to create various effects and visual elements in projects.

  4. Processing can also be used to interface with Arduino and other devices, making it a great choice for creating control and monitoring interfaces for a variety of projects.

Download and install

The program can be downloaded here. It is very easy to install.

Establishing communication with my PCB

There is a good guide on establishing communication and data exchange between the code written in Arduino IDE and the program Processing. The site is in Russian, but if you wish, you can use the translation of the page.

Code for Arduino IDE

void setup() {
   Serial.begin(9600);
}

void loop() {
   Serial.println("Hello World!");
   // wait 500 milliseconds before next send
   delay(500);
}
import processing.serial.*;

Serial serial;    // create a serial port object
String received;  // data received from the serial port

void setup()
{
   String port = Serial.list()[0];
   serial = new Serial(this, port, 9600);
}

void draw() {

   if ( serial.available() > 0) {      // if there is data,
   received = serial.readStringUntil('\n');     // read data
   }
   println(received);     //display data in the console
}

Servo Motor Control Program

There are many libraries available for creating beautiful and functional interfaces in the Processing program. I want to use the G4P library.

Installing the G4P Library

To install a new library, follow these steps:

Install G4P

Enter the name G4P, select it from the list, and click the Install button:

Install G4P

This library provides ready-made templates, but it also has another interesting feature: you can use the G4P GUI Builder to create buttons, and the program will automatically convert them into code. To do this, let’s download the G4P GUI Builder from the Contribution Manager, under the Tools section:

Install G4P

Creating a New Document

Now, let’s create a new document and select G4P GUI Builder as the Tools.

G4P

This will create 3 files:

  1. A base sketch with basic settings.

I also had to install the PeasyCam library as it was used in the created sketch and the compiler was giving an error.

  1. The gui file, which we will approach later.

  2. And the G4P GUI Builder.

Let’s start with the G4P GUI Builder. It is a window where you can create different graphical components, and the program will convert it into code.

Install G4P

Let’s create a button as an example. After creating the menu, the editing menu for the button will appear in the right window. Here, you can specify the button’s size, position, label, and color. Additionally, a variable name is automatically assigned, and a button press event is added.

Install G4P

Let’s switch to the sketch. You may notice that the button is not visible there. Let’s click the Run button and see what happens:

Install G4P

A window opens with the button that I drew. I clicked on the button several times, and in the console, the button press event started to appear, showing the following content:

button1 - GButton >> GEvent.CLICKED @ 2923
button1 - GButton >> GEvent.CLICKED @ 5490
button1 - GButton >> GEvent.CLICKED @ 7357
button1 - GButton >> GEvent.CLICKED @ 8256
button1 - GButton >> GEvent.CLICKED @ 8939
button1 - GButton >> GEvent.CLICKED @ 10656
button1 - GButton >> GEvent.CLICKED @ 11056
button1 - GButton >> GEvent.CLICKED @ 11642
button1 - GButton >> GEvent.CLICKED @ 176715

If we look at the content, button1 is the Variable Name in the G4P GUI Builder window, which was assigned to the button during creation. GEvent.CLICKED represents the click event. The numbers, for example, 10656, represent the time of the click event since the program started.

If you open the gui file, you can see similar values that we created in the G4P GUI Builder window.

Install G4P

I have dealt with web development before, and that’s why the sketch file reminds me of an HTML file, while the gui file resembles a JavaScript file in its nature.

It seems like I’ve figured out the code a bit and noticed some patterns.

In my project, I want to create an interface for controlling the position of a servo motor. Let’s create a variable:

int position = 90;

And then let’s display the value in the Console with a 1-second delay:

public void draw(){
  background(230);
  println("position: " + position);
  delay(1000);
}

And then in the gui file, let’s modify the button1_click1 function so that when the click event occurs, the value of the position variable increases by 1:

public void button1_click1(GButton source, GEvent event) { //_CODE_:button1:814697:
  println("button1 - GButton >> GEvent." + event + " @ " + millis());
  position++;
} //_CODE_:button1:814697:

Now, if we look at the console, we can notice that the value of the position variable doesn’t change until the click event happens on the button.

Install G4P

This experience will be very helpful when creating two buttons for controlling the servo motor.

Let’s create another button that will decrease the angle, slightly move it, change the color, and modify the label of the existing button:

Install G4P

Then, in the code, for the click event on the second button, we will decrement the value of position:

public void button2_click1(GButton source, GEvent event) { //_CODE_:button2:212840:
  println("button2 - GButton >> GEvent." + event + " @ " + millis());
  position--;
} //_CODE_:button2:212840:

Let’s add another element called knob for aesthetics and the functionality of quick servo motor rotation. Then, I will set its dimensions and define the rotation range (0, 180). I will also set the minimum value to 0 and the maximum value to 180:

Install G4P

As you can see in the code, it is interactive, and you can change its position by clicking with the mouse:

Install G4P

But I want it to be synchronized with the servo motor position.

After some research on the internet, I found that this object has many available properties and functions. But I’m interested in two of them: setValue() and getValueI(). The first one sets the value, and the second one retrieves the value.

In the sketch, I will use the setValue() function and set it to position so that when the value changes, it will be reflected in the knob as well:

public void draw(){
  knob1.setValue(position);
  background(230);
  println("position: " + position);
  delay(1000);
}

And for the second function of this object, I will use it in the gui file. Whenever the arrow position changes, I will request the value of the arrow’s position and assign it to position:

public void knob1_turn1(GKnob source, GEvent event) { //_CODE_:knob1:208180:
  println("knob1 - GKnob >> GEvent." + event + " @ " + millis());
  position = source.getValueI();
} //_CODE_:knob1:208180:
The values for the Knob element are limited to the range [0, 180], but the values for the position variable are not limited. Since the servo motor operates in the range [0, 180], let’s make sure that the value of the position variable doesn’t go below 0 or above 180.

To do this, in the gui file, let’s add conditions to the button click events to enforce the limits:

public void button1_click1(GButton source, GEvent event) { //_CODE_:button1:814697:
  println("button1 - GButton >> GEvent." + event + " @ " + millis());
  if (position < 180) {
    position++;
  }
} //_CODE_:button1:814697:

public void button2_click1(GButton source, GEvent event) { //_CODE_:button2:212840:
  println("button2 - GButton >> GEvent." + event + " @ " + millis());
  if (position > 0) {
    position--;
  }
} //_CODE_:button2:212840:

For aesthetics, I will slightly increase the size of the interface for the program:

Install G4P

After that, all values and events became synchronized.

Now it’s time to establish a connection with the PCB and send it the values to control the servo motor. I will write the code for servo motor control in the Arduino IDE.

Communication between the Arduino IDE and Processing is done through a serial connection. The Arduino IDE sends data to the port, and Processing receives and processes it. This allows you to control Arduino from Processing and receive data from Arduino for further processing on the computer. Both Arduino IDE and Processing can exchange various data types, including integers (int), floating-point numbers (float), characters (char), strings (String), and bytes (byte).

Let’s write the complete code for the sketch file that will send the position values through Serial:

// Need G4P library
import g4p_controls.*;
// You can remove the PeasyCam import if you are not using
// the GViewPeasyCam control or the PeasyCam library.
import peasy.*;
import processing.serial.*;
Serial arduino;

public void setup(){
  arduino = new Serial(this, Serial.list()[0], 9600);
  size(720, 480, JAVA2D);
  createGUI();
  customGUI();
  // Place your setup code here
}
int position = 90;

public void draw(){
  background(230);
  knob1.setValue(position);
  arduino.write(byte(position));   
  println("position: " + position);
}

// Use this method to add additional statements
// to customise the GUI controls
public void customGUI(){
}

In the void draw() function, we pass the values to Serial:

arduino.write(position);

Now let’s connect a servo motor to my PCB, and connect the microcontroller via USB to the computer.

Connect

Now let’s move on to the Arduino IDE development environment. In the week Output Devices I connected a servo motor to my PCB and programmed the servo motor to work no third party libraries. And now I want to use this code, I just change it a little for this task:

const int servoPin = 2; // set the pin number for the servo
// int angle = 90; // variable for rotation angle

void setup() {
  Serial.begin(9600);
   pinMode(servoPin, OUTPUT); // set servo pin as output
}

void loop() {
  if (Serial.available() > 0) {
    int angle = Serial.read();
    angle = map(angle, 0, 180, 500, 2500);
     digitalWrite(servoPin, HIGH); // send a high signal to the servo pin
     delayMicroseconds(angle); // set the delay corresponding to the angle of rotation
     digitalWrite(servoPin, LOW); // send low signal to servo pin
     delay(10); // delay to stabilize the servo
  }
}

This code checks if there is data available to be read from the serial port. It uses the Serial.available() function, which returns the number of bytes available to read from the serial buffer.

If there is data available Serial.available() > 0, the code reads a single byte of data from the serial port using the Serial.read() function and stores it in the angle variable.

I replaced the expression for converting degrees into an analog value that is understandable for the operation of the servomotor with the map() function.

Let’s see how the program works:

From the video you can see that the servomotor changes its position in accordance with knob. The only thing I changed in the above code was to make the value symmetrical, that is, I changed

arduino.write(position);

on

arduino.write(180 - position);

Conclusion

The week was wonderful. The knowledge gained in the past weeks is becoming more and more valuable. This week we got acquainted with the ways of interacting with systems using the interface. Interaction with systems through an interface is an important aspect of system management. The use of interfaces facilitates interaction and understanding of the system. They provide convenient and clear ways to interact with the functions and capabilities of the system, making the process more efficient and intuitive.

Files

Servo Motor Control - RAR archive


Last update: June 21, 2023