Individual assignment :
The objective of this week is to create an application or Graphics User Interface (GUI) that interfce with our input/output device as well as presenting the data to the user in a visual or graphical way. The application can also be seen as an extension to your board, in term of processing, as you can distribute certain portion of your workload from your board to the PC/notebook or other computing device like the smaller 'Raspberry Pi' that would be much more powerful and having more memory.
In my 'Input Device' week, I was using an ultrasonic distance sensor, so this week I am using back my ultrasonic Sensor and ATTiny44 board.
I am using Python to create a stand-alone application as well as trying out JavaScipt to create a simple web-based application. For Python programming, I am using Eclipse and for Javascript, I am using Visual Studio Code.
Content for this webpage includes :
Setup my HC-SR04 ultrasonic sensor and board
A. Progamming in Python using Eclipse
B. Progamming in JavaScript using Visual Studio Code
Programming language : Python :
Python is a powerful, portable open source programming language and it fully support object-oriented programming as well as structured programming. It is a popular programming language and is easy to learn for beginners.
JavaScript :
JavaScript is a cross-platform, object-oriented scripting programming langauage for web Development used to make webpages interactive (eg. click on a button, swipe, tap, create popup menus, complex animations, etc.).
|
Programming tools (text editor and IDE) :
|
I am using an ultrasonic sensor along with my ATTiny44A board that I had made in 'input device' week.
I setup up my ultrasonic sensor as shown in the photo. The measurement data is being sent over the serial port (baudrate speed : 9600) to my notebook.
My Audrino code for the
ATtiny44 board
is as follow :
/* Ultrasonic_sensor.ino by Lucas Lim created on 22/4/2020 Purpose: To activate Ultrasonic sensor and send data to computer Ultrasonic sensor Pins: VCC: +5V DC Trig : Trigger (INPUT) - Arduino Pin9 (PB1) Echo: Echo (OUTPUT) - Arduino Pin10 (PB0) GND: GND Original code created by Rui Santos, https://randomnerdtutorials.com */ #include <SoftwareSerial.h> SoftwareSerial mySerial(1, 0); // RX, TX const int trigPin = 9; // Trigger pin const int echoPin = 10; // Echo pin long duration, cm; int c = 1; void setup() { //Initialising Serial Port Communication mySerial.begin (9600); //Define inputs and outputs pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); } void loop() { // read from serial for stop character if (mySerial.available()>0){ // read from serial c = mySerial.read(); } while (c != 0){ // The sensor is triggered by a HIGH pulse of 10 or more microseconds. // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: digitalWrite(trigPin, LOW); delayMicroseconds(2); // set the trip pin high high for 10 smicroseconds digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // Read the signal from the sensor: a HIGH pulse whose // duration is the time (in microseconds) from the sending // of the ping to the reception of its echo off of an object. duration = pulseIn(echoPin, HIGH); // Convert the time into a distance cm = duration *0.034/2; mySerial.print(cm); mySerial.println(); delay(100); //delay 1 tenth of a sec } }
1. Install Python from Python website.
2. 'pip' is a Python package manager which is installed along with latest version of Python 3 and 'pip' is use to install, remove and manage external Python modules/libraries. Pip.exe is located in %python directory%\Scripts and runs from the
command line and not from Python Shell.
Check version of pip by typing :
python -m pip --version
3. Update pip to latest version by typing :
python -m pip install -U pip
4. Install "PySerial" allows Python to access the serial port to send and receive data.
pip install pyserial
The installed modules (using pip) can be found in the Eclipse's libraries directory -> under site packages on the 'Workspace' panel on the left.
5. I ran a simple Python code to test whether I can receive data from the target board with the
ultrasonic sensor.
6. I referred to Neil's Python2 code on the ultrasonic sensor in the 'Input devices' week on class site as a good starting point.
7. Command line option :
I used the built-in module known as "argparse" to take in user input from the command line. User has the option to specify which serial comm port to be use, otherwise the default comm port will be "COM6".
import argparse
parser = argparse.ArgumentParser(description='Ultrasonic Sensor GUI')
parser.add_argument("--c", default="COM6", type=str, help="enter com port")
args = parser.parse_args()
port = args.c
print(port)
8. Running the program :
To run the python program, user can type in the following statement at the command prompt.
python ultrasonic_sensor_gui.py
or
python ultrasonic_sensor_gui.py --c {serial comm port number} eg. python ultrasonic_sensor_gui.py --c COM6
9. User interaction buttons :
I used the module 'tkinter' which is a powerful graphic library for python and added in a few buttons, draw the rectangle, line, text, etc. and arrange my graphic objects in a grid foramt.
I created three buttons for the user to interact with the input device :
[Start] - start viewing the measurement data, reading data from board
[Stop] - pause reading, stop the ultrasonic sensor, incorporating serial.write() to board
[Exit] - stop the ultrasonic sensor and exit the program
It is a good practice to be able to stop the ultrasonic sensor as you are developming your application.
10. GUI design :
'tkinter' is built into the Python standard library which does not require additional installation and configuration. Which is also cross-platform, so the same code works on Windows, macOS, and Linux. There is a lot of online resouces and tutorial on learning to use 'tkinter'.
Some of the key functions are as follow :
from tkinter import * # this import tkinter lib
root = Tk() # this create my root (or master) window object
xxx = LabelFrame(parent window, option, ... ) # create a frame container with a text label text and a border.
canvas = Canvas(parent window, option, ... ) # the canvas is a rectangular area intended for drawing pictures or other complex layouts. You can place graphics, text, etc on a Canvas.
canvas.create_line(x0, y0, x1, y1, ..., options) # create a line item
canvas.create_rectangle(x0, y0, x1, y1, ..., options) # create a rectangle item
canvas.create_text(x0, y0, ..., options) # create a text item
xxx = Label(parent window, option, ... ) # this widget implements a display box where you can place text
xxx.pack() # after you created an tkinter graphic item, you can use pack() which is one of the three geometry managers and place the object into the parent(or root) window
xxx.grid(grid options... ) this is another type of geometry manager that organizes widgets in a table-like structure in the parent window.
root.mainloop() # the final line to start tkinter app
11. Developing my application using Eclipse.
12. My
Python code
for the GUI interface is as follow :
#! Python3 # # ultrasonic_sensor_gui.py # by Lucas Lim # created on 24/4/2020 # # Purpose: A GUI for Ultrasonic sensor to be display on the computer # # The work is provided for academic purpose for Fab Academy 2020. # Users accept all as is, no warranty is provided, no call/email # from users will get a response. Users accept all liability. # # from tkinter import * from time import sleep import serial import argparse import array as arr # var for distance calculation cm = 0 a = arr.array('i', [0, 0, 0, 0, 0]) # create an int array for aver_reading # var for ploting bar chart x0 = 50 y0 = 120 # option to take in command line argument for serial port parser = argparse.ArgumentParser(description='Ultrasonic Sensor GUI') parser.add_argument("--c", default="COM6", type=str, help="enter com port") args = parser.parse_args() port = args.c print(port) # # open serial port # try: ser = serial.Serial(port, 9600, timeout=8) except serial.serialutil.SerialException: print ("COM port specified is not connected!") quit() def move(): n = 0 aver_cm = 0 print("Start") # for debugging purpose # check whether serial port is open, as user might already run the program in another window # also check whether user have pressed "Start" multiple times if ser.is_open: ser.close() ser.open() else: ser.open() ser.write(1) # tell board to switch on ultrasonic sensor while ser.is_open: try: cm = int(ser.readline().decode('utf-8')) except Exception as e: print(e) # limit distance to 200cm for easy plotting of bar chart if cm >= 200: cm = 200 # average 5 readings a[n] = cm if n == 4: aver_cm = int(sum(a) / 5) n = 0 else: n += 1 # bar chart horizonal scale is 500px : 200 cm, therefore 1cm = 2.5px # multiply measure data by 2.5 to display onto the bar chart hori scale x = aver_cm * 2.5 # update bar chart canvas.itemconfigure("text",text=str(aver_cm) + " cm") canvas.coords('rect1', x0, y0-80, x0+x, y0-30) canvas.update() def stop(): # check if user have pressed "Stop" multiple times if not ser.is_open: return ser.write(0) # tell board to switch off ultrasonic sensor ser.close() print("Stop!") # for debugging purpose print(ser.is_open) def exit(): if ser.is_open: ser.write(0) ser.close() else: ser.close() root.quit() print("Exit!") # for debugging purpose # # set up GUI # root = Tk() root.title('Ultrasonic Sensor Program') # window title root.geometry('700x520') # overall window size myLabel = Label(root, text="\nUltrasonic Sensor Interface\n", font='Arial 16 italic bold') myLabel.pack() # Canvas for ploting bar chart is 600 x 200 canvas = Canvas(root, width=600, height=200, background="white") canvas.create_line(x0, 25, x0, y0) canvas.create_line(x0, y0, 550, y0) # measurement data in text below bar chart canvas.create_text(x0+250, y0+55, text=str(cm) + " cm", font=("Helvetica", 20), tags="text", fill="blue") # measurement data in blue color bar canvas.create_rectangle(x0, y0-80, x0+10, y0-30, tags="rect1", fill="blue") c1 = 0 c2 = 0 # drawing the horizontal scale of the bar chart while c1 <= 500: canvas.create_line(x0 + c1, y0, x0 + c1, y0+10) canvas.create_text(x0 + c1, y0+17, text=str(c2), font=("Helvetica", 9), fill="grey") c1 +=25 c2 += 10 canvas.pack() # set up a frame for text message and buttons frame = LabelFrame(root, text="Instruction :", font='Arial 12', padx = 30, pady =15) # this padding is inside the frame frame.pack(padx=5, pady=5) # this padding refer to the outside of the frame to the border # Creating a Label widget inside of "frame" myText = """ Hello, Welcome to my ultrasonic sensor program Press Start to start measuring distance Press Stop to pause Press Exit to close program """ myLabel = Label(frame, text=myText, font='Arial 12 italic', wraplength=600, anchor=NW, justify=LEFT) myLabel.grid(row=0, column=0, rowspan=5) # set a empty row/space between text and button emptySpace1 = Label(frame, text=" ") emptySpace1.grid(row=0, column=1, rowspan=5) emptySpace2 = Label(frame, text=" ") emptySpace2.grid(row=0, column=2) button_start = Button(frame, text="Start", command=move, padx=100, pady=5) button_start.grid(row=1, column=2) button_stop = Button(frame, text="Stop", command=stop, padx=100, pady=5) button_stop.grid(row=2, column=2) button_exit = Button(frame, text="Exit", command=exit, padx=102, pady=5, fg="red") button_exit.grid(row=3, column=2) root.mainloop()
Duration : 44 secs
No Audio
Programming Tool setup :
I be testing out and using Visual Studio Code to create a HTML (.html) webpage and a JavaScript (.js) resource file for my main html page. User can just double-click on the ultrasonic_sensor.html file to be openned by any web browser like
Google Chrome, Microsoft Edge, etc.
1. Install Visual Studio Code and install the extension "Live Server" which would allow me to run a web server and preview the changes I made immedaiely after I make a save on my html file.
2. Install node.js. After install, you can run "node -v" at the Command Prompt and it will show you the version that you had installed. Mine is ver 12.16.2. Node.js' Package Manager (NPM) is also installed,
this is same as python's 'pip', which allow you to install node.js modules.
3. Create a simple .js file and run it. The output is displayed in the console screen below.
Note that when you typed "console." The Intellisense extension introduces autocomplete feature and show you the methods available to you.
4. Install the serialport as well as the ws (websocket) npm package.
npm install serialport
npm install ws
5. Create a new folder called "node_modules" in the same directory where your node .js file is located. Copy the modules that you need from the master "C:\program files\nodejs\node_modules" into the newly created "node_modules" (eg. serialport
npm module) so that the module can be called by your .js file.
6. Refer to serialport 8.x.x readline online documentation to learn how to receive data from the serialport.
Note :
The default Parsers are Transform streams that process incoming data. To use the parsers, you must create them and then pipe the Serialport to the parser. Be careful to only write to the SerialPort object and not the parser (eg. use
port.write())
The "Readline parser" used, provide a delimiter (defaults to \n). It will tell parser-readline to finds the delimiter you configure, how to split the incoming stream and transform the incoming stream from serialport to string and the default
encoding is "utf8".
7. Setting up Websocket :
The node.js server established the communication link with the hardware I/O via the serialport.
The client browser displays the html web page and which the user can interact, like clicking to start viewing the measurement data, pause and exit the web page.
The html web page communicate with the node.js server at the back end, this is possible with the implementation of 'Websocket'. Websocket establises a stable and persistent connection which allow the server and client to communication with each
other in real time.
I refer to ws (websocket) online documentation to learn how to send and receive data via websocket.
wss = new WebSocket.Server -> create a new server instance on node.js and a HTTP server is automatically created, started, and using the port that you specify.
websocket.send(data)
Send data through the connection
websocket.onopen {Function}
An event listener to be called when the connection is established. The listener receives an OpenEvent named "open".
websocket.onerror {Function}
An event listener to be called when an error occurs. The listener receives an ErrorEvent named "error".
websocket.onmessage {Function}
An event listener to be called when a message is received from the server. The listener receives a MessageEvent named "message".
etc...
8. Drawing the bar chart using SVG (Scalable Vector Graphics) in drawing vector based graphic element like line, rectangular, etc. You can refer to SVG tutorial online.
9. Running the node.js codes and html client webpage:
In Visual Studio Code, you can run node.js code directly and creates your own node.js server. Alternatively, you can also run the node.js file using node.exe through the command line.
Having the "live preview" extension you had installed which become a live web server for you to host your html file which the client will see.
Server Code (Node.js) :
// Node.js (JavaScript) code // // ultrasonic_server.js // by Lucas Lim // created on 24/4/2020 // // Purpose: JavaScript to capture measurement data from // Ultrasonic sensor to be pass on to client browser (GUI) // // The work is provided for academic purpose for Fab Academy 2020. // Users accept all as is, no warranty is provided, no call/email // from users will get a response. Users accept all liability. // "use strict" // run code in strict mode // variables for serial port communication var serial_port = 'COM6' var baud = 9600 // variables for websocket communication var server_port = '1234' var client_address = '::ffff:127.0.0.1' //IP6 address var value = 0 // // open serial port // const SerialPort = require('serialport') const Readline = require('serialport/node_modules/@serialport/parser-readline') const port = new SerialPort(serial_port, { baudRate: baud }) const parser = port.pipe(new Readline({ delimiter: '\r\n' })) // // check serial port status // port.on("open", () => { console.log('serial port open') }); // // read data from serial port // parser.on('data', data =>{ console.log(data) value = parseInt(data) //convert data to int }); // // Setting up websocket // console.log("listening for connections from "+client_address+" on "+server_port) var WebSocket = require('ws') var wss = new WebSocket.Server({port:server_port}) // turn on websocket and listen to the connection wss.on('connection', function(ws) { if (ws._socket.remoteAddress != client_address) { console.log("error: client address " + ws._socket.remoteAddress + " doesn't match") // for debugging purpose return } console.log("connected to "+ client_address + " on port " + server_port) // for debugging purpose ws.on('message', function(data) { var check = parseInt(data) if (check == 1){ console.log("msg received from client is 1") // for debugging purpose if (port.isOpen == false) { port.open(function (err) { console.log('open port'); }); port.on("open", () => { console.log('serial port open') }); // // read data from serial port // parser.on('data', data =>{ console.log(data) value = parseInt(data) //convert data to int }); } } else if (check == 0){ console.log("msg received from client is 0) // for debugging purpose port.close(function (err) { console.log('port closed'); }); } // send measurement data to client ws.send(value) }) })
Client code (html) :
<!DOCTYPE html> <html lang="en"> <!-- // // ultasonic_client.html // by Lucas Lim // created on 24/4/2020 // // Purpose: A web-based GUI for Ultrasonic sensor to receive // and display measurement reading // // The work is provided for academic purpose for Fab Academy 2020. // Users accept all as is, no warranty is provided, no call/email // from users will get a response. Users accept all liability. // --> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Ultrasonic Sensor"> <meta name="author" content="Lucas Lim"> <title> Ultrasonic Sensor Interface </title> <!-- beautifying the click buttons --> <style> .button { background-color: #4CAF50; /* Green */ border: none; color: white; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer; padding: 10px 24px; } .button:hover { background-color: "black"; } </style> </head> <body style="font-family: Arial, Helvetica, sans-serif;"> <br> <!-- // // set up SVG bar chart // --> <svg width="600" height="150"> <line x1="30" y1="0" x2="30" y2="100" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="30" y1="100" x2="530" y2="100" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="30" y1="100" x2="30" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="55" y1="100" x2="55" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="80" y1="100" x2="80" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="105" y1="100" x2="105" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="130" y1="100" x2="130" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="155" y1="100" x2="155" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="180" y1="100" x2="180" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="205" y1="100" x2="205" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="230" y1="100" x2="230" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="255" y1="100" x2="255" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="280" y1="100" x2="280" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="305" y1="100" x2="305" y2="110" style="stroke:rgb(3, 3, 3); stroke-width:2" /> <line x1="330" y1="100" x2="330" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="355" y1="100" x2="355" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="380" y1="100" x2="380" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="405" y1="100" x2="405" y2="110" style="stroke:rgb(3, 3, 3); stroke-width:2" /> <line x1="430" y1="100" x2="430" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="455" y1="100" x2="455" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="480" y1="100" x2="480" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="505" y1="100" x2="505" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <line x1="530" y1="100" x2="530" y2="110" style="stroke:rgb(3, 3, 3);stroke-width:2" /> <text x="27" y="120" fill="dark grey" font-size="10">0</text> <text x="50" y="120" fill="dark grey" font-size="10">10</text> <text x="75" y="120" fill="dark grey" font-size="10">20</text> <text x="100" y="120" fill="dark grey" font-size="10">30</text> <text x="125" y="120" fill="dark grey" font-size="10"">40</text> <text x="150" y="120" fill="dark grey" font-size="10">50</text> <text x="175" y="120" fill="dark grey" font-size="10">60</text> <text x="200" y="120" fill="dark grey" font-size="10">70</text> <text x="225" y="120" fill="dark grey" font-size="10">80</text> <text x="250" y="120" fill="dark grey" font-size="10">90</text> <text x="272" y="120" fill="dark grey" font-size="10">100</text> <text x="299" y="120" fill="dark grey" font-size="10">110</text> <text x="324" y="120" fill="dark grey" font-size="10">120</text> <text x="349" y="120" fill="dark grey" font-size="10">130</text> <text x="374" y="120" fill="dark grey" font-size="10">140</text> <text x="399" y="120" fill="dark grey" font-size="10">150</text> <text x="423" y="120" fill="dark grey" font-size="10">160</text> <text x="448" y="120" fill="dark grey" font-size="10">170</text> <text x="473" y="120" fill="dark grey" font-size="10"">180</text> <text x="498" y="120" fill="dark grey" font-size="10">190</text> <text x="523" y="120" fill="dark grey" font-size="10">200</text> <text x="250" y="150" fill="blue" font-size="28" id="text">100</text> <text x="300" y="150" fill="blue" font-size="28"">cm</text> <rect x="30" y="25" width="0" height="40" id="rect" fill="blue"/> </svg> <br> <br> <script type="application/javascript"> function ws_connection(msg) { document.getElementById("message").innerHTML = "msg is " + msg; // for debugging purpose var server = "127.0.0.1:1234"; var socket = new WebSocket("ws://"+server); // open a websocket if (msg==0) { socket.onopen = function (event) { console.log("Stopping/pausing") // for debugging purpose document.getElementById("message").innerHTML = "Send msg 0 to server" // for debugging purpose socket.send(msg) } } if (msg==1) { document.getElementById("message").innerHTML = "Receiving data " + msg; // for debugging purpose var rect = document.getElementById("rect") var text = document.getElementById("text") socket.onopen = function (event) { console.log("connected to "+server) // for debugging purpose socket.send(msg) socket.send("request") } socket.onerror = function (event) { console.log("can't connect to "+server) } socket.onmessage = function (event) { value = event.data; // adjusting value to fit within bar chart if (value > 200) { value = 200 } // adjusting the SVG bar width rect.setAttribute("width", value * 2.5) text.firstChild.nodeValue = value socket.send("request") } } } // end of ws_connection --> function but_Exit() { window.close(); } // end of but_Exit() </script> <div style="max-width:550px; border: 0.5px groove; padding: 15px; background-color: #dee7ee;" > <h2>Ultrasonic Sensor Interface</h2> Hello,<br> Welcome to my ultrasonic sensor program<br> <br><br> Press Start to start measuring distance<br> Press Stop to pause<br> Press Exit to close the webpage<br> <br> <button class="button" type="button" onclick="ws_connection(1)">Start</button> <button class="button" type="button" onclick="ws_connection(0)">Stop</button> <button class="button" type="button" onclick="but_Exit()">Exit</button> </div> <br><br> </body> <footer> Fab Lab Singapore Polytechnic <br> <!-- for debugging purpose --> <p id="message"></p> </footer> </html>
Duration : 51 secs
No Audio
Application development :
The main challenge for this week was learning python as well as Javascript programming, in addition, we have to interface with the board and create a graphical or visual aid for the user, a simple data virtualisation to represent your data in a bar chart or graph...
Python vs Javascript :
After coding the same stuff in both python and javascript with node.js, I found that both are similiar in nature, with slight differences in the syntax and libraries, Python3 can be both object orientated programming as well as structure programming, but Javascript is not Object-orientated.
A server-client model open up the possiblity for multiple users to interact with your device(s), like node.js, but the programming require more effort like looking into coding integrating html/ccs/javascript/plug-ins, security, stability, monitoring connection status, etc. Web development
open up more possibilities, eg. your html web page can incorporate CCS style sheet/coding, embedding a video, adding other web componenets or other stuff, etc. It might be possible to install node.js on a small device like a Raspberry Pi 4
running linux.
Python3 is much user friendly and easy to learn. The javascript code is smiliar to C/C++ which is a bit hard to learn from a beginner point of view. Each of them primarily use in different scenario and serving different purposes, python more
toward application development while javascript web-based development. From a layman point of view, I believe python application would be more stable, it is a stand-alone application and it doesn't need to setup a node.js server or a web
server.
Issues faced with javascript/node.js :
1. The ws module is quite basic and limited.
2. I had problem trying to use "websocket.close()" on the node.js server as well as client. As I intended for the current user just to close the ws communication channel, but it seem not possible as server is still transmitting data to the
client. I looked at another ws module call "socket.io" but it would take me too much time to expriement with it...
Eclipse vs Visual Studio Code :
Both allows me to run my code off off my Editor windows. But I found that Visual Studio Code is much user friendly, easy to use, and can switch to other programming languages easily, like from html to javascript to python. However, it does not have a taskbar below the menu bar, or ribbon style task bar, it be nice to include one and a customisable one to add or remove icons.
If you just focus on python programming or just java or other, it be nice to use Eclipse, as it have a lot of features. Eclipse has a it's own Web Tools Platform (WTP) for web development, but I installed, the 'workspace' get a bit confused with I switch back-and-fo from python to html/javascript... This is maybe I am still new to Eclipse.
Future development to Phyton GUI application :
1. When user click on Start button, I should make it 'DISABLED' with it's text greyed out, so that user cannot click on the button again.
2. To build it into an stand-alone executable program (like .exe).
3. Maybe logging all the readings into a file and store on the harddisk
4. Maybe to look out for other ploting tool/packages like matplotlib, etc.
My files :
Arduino file Ultrasonic_sensor_for_GUI.ino
Python file ultrasonic_sensor_gui.py
ultrasonic_server.js
ultasonic_client.html
Python programming :
Python 3.8.2 documentation
Youtube video on "Learn Python - Full Course for Beginners [Tutorial]"
Python Module Index
Welcome to pySerial’s documentation
GUI on Python :
Youtube video on "Tkinter Course - Create Graphic User Interfaces in Python Tutorial"
https://www.tutorialspoint.com/python/python_gui_programming.htm
JavaScript programming :
JavaScript Guide
What exactly is Node.js?
serialport 8.x.x online documentation
ws (websocket) GitHub repo and documentation