Skip to content

16. Interface and application programming

Group assignment

The group consisted of all the Oulu students. Most of us used Processing. Other used tools were, Blynk, PyQt5, MatLab, and Python.

Below is a quick overview of the different technologies

Processing

Processing is a flexible software sketchbook and a language for learning how to code within the context of the visual arts. Hello world equivalent with Processing looks like this:

line(15, 25, 70, 90);

Blynk

Blynk is a hardware-agnostic IoT platform with customizable mobile apps, private cloud, device management, analytics, and machine learning Hello world with Blynk looks like this:

BLYNK_LOG1("Hello World"); // Print a string

PyQt5

PyQt5 is a comprehensive set of Python bindings for Qt v5. It is implemented as more than 35 extension modules and enables Python to be used as an alternative application development language to C++ on all supported platforms including iOS and Android. Hello world widget with PyQt5:

import sys
from PyQt5.QtWidgets import QApplication, QWidget
if __name__ == '__main__': 
app = QApplication(sys.argv)
w = QWidget()
w.resize(250, 150) w.move(300, 300) 
w.setWindowTitle('Hello World')
w.show()
sys.exit(app.exec_())

Matlab

Hello world with Matlab looks like this:

str = 'Hello World';
disp(str)

Python

Hello world with Python looks like this:

 print(“Hello, World!”)

Individual assignment

Hello World in Pygames

I had always thought of learning about animations and computer graphics. Below is an example of Hello world using Pygames. I had been following the tutorials on this website. It is a still frame from an annimation where a picture of the cat and “Hello world” moves around.

Screenshot of the hello world animation in pygame.

GUI Design

For the individual assignment, however I decided to use tkinter for controlling the microcontroller via serial. I used the board from my output week (referred now onward as board1) for this assignment. Board1 provides a serial interface by using USB CDC (USB communications device) class. The embedded software for providing the CDC class is taken from LUFA. In other words, a virtual serial connection is provided using the USB CDC class. The physical layer underneath is the USB connection.

Complete python code of the GUI is attached below. Following is description of parts of the code.

Screenshot of the developed GUI.

Tkinter provides multiple widgets, here I am using the Scale widget. from_ and to parameters define the lower and upper bound of the scale.master is the root of this widget, created by calling Tk().

red = Scale(master, from_=0, to=255, tickinterval=20)

Underneath the widget, I have labels which tells which scale is for which color. The label widget is created in the following way.

rlbl = Label(master, text="red", bg="red", fg="white")

Tkinter provides three layout managers, pack, place, and grid. pack is the simplest one and it internally decides where to palce the widgets. In place, one has to explicitaly tell the exact or relative coordinates. In my gui, I have used place layout manager. grid is the best option in middle, where it places the widget on a 2D grid and position is defined using rows and columns.

red.place(x = 20, y = 30, width=100, height=400)
rlbl.place(x = 60, y = 430, width=30, height=30)

Finaly, to trigger the sending of data to the microcontroller, I have used the Button widget. It requires a funciton handle which is called whenever the button is pressed.

def set_values():
    print (red.get(), green.get(), blue.get())
    dlist = [128, 164, red.get(), green.get(), blue.get(), 128]
    zxc = bytearray(dlist)
    print(zxc)
    sdata.write(bytearray(dlist))

sdata= serial.Serial('COM10','9600')

btn = Button(master, text='Apply', command=set_values)

Embedded Design

The embedded design is very simple and there is no error handling. This code will only ever work in the correct conditions and even a single error in the reception of data will not be handled gracefully.

Below is an image of showing the connections of the microcontroller with the PC.

Image showing the microcontroller connections.

the USb virtual serial class is defined as shown below. There are three endpoints, one of receving, one for transmitting and one for notifications.

USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
    {
        .Config =
            {
                .ControlInterfaceNumber   = INTERFACE_ID_CDC_CCI,
                .DataINEndpoint           =
                    {
                        .Address          = CDC_TX_EPADDR,
                        .Size             = CDC_TXRX_EPSIZE,
                        .Banks            = 1,
                    },
                .DataOUTEndpoint =
                    {
                        .Address          = CDC_RX_EPADDR,
                        .Size             = CDC_TXRX_EPSIZE,
                        .Banks            = 1,
                    },
                .NotificationEndpoint =
                    {
                        .Address          = CDC_NOTIFICATION_EPADDR,
                        .Size             = CDC_NOTIFICATION_EPSIZE,
                        .Banks            = 1,
                    },
            },
    };

Under the main loop, code checks if there is any data available from the receive endpoint. If there is any data, then the code checks if the preamble and postamble matches. If that is true, the the data is send to the RGB LED library.

    if(CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface))      
        {
            if (i == 6)
            {
                i = 0;
            }

            data[i] = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
            i++;
                    //CDC_Device_SendByte(&VirtualSerial_CDC_Interface, data);
                if ((data[0] == 128) && (data[1] == 164) && (data[5] == 128))
                {
                    led[0].r = data[2];
                    led[0].g = data[3];
                    led[0].b = data[4];

                    ws2812_sendarray((uint8_t *)led, 3);
                    data[0] = 0;
                    data[1] = 0;
                    data[5] = 0;

                    i = 0;
                }
        }

Demo

In my GUI, one has to select a value of the red/green/blue channel and then hit the “Apply” button. This sends the corresponding values of the three channels over serial to the microcontroller. The three byte data has a two byte of preamble and one byte of postamble. All zeros corresponds to the OFF state of the RGB LED and all 255 corresponds to white color.

Files