Project 13: Interface/Applications Programming

This week I developed a basic interface that I hope to use for my final project using PyQT.

...

My Project

I started by downloading PyQT.

I then (with the help of ChatGPT) created a script to make an interface that allowed my two final project tools to communicate by pressing one button.

One tool sends a vibration using a transducer, and the other senses it with an ADXL343 for vibration analysis. I made the script such that when you press the button, the transducer starts its frequency sweep, and the piezo starts sending analog signals to the Xiao for ADC conversion, which sends that over wifi to my computer and stores the data in a folder. The signal measurement ends after 10 seconds, which is slightly longer than the ~8 second frequency sweep.


import sys
import socket
import csv
import time
import threading
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel

# Arduino and ESP32 server information
PIEZO_HOST = "172.20.10.12"  # Replace with your piezo server's IP address
PIEZO_PORT = 80
TRANSDUCER_HOST = "172.20.10.2"  # Replace with your transducer's IP address
TRANSDUCER_PORT = 80

# File to save data
output_file = "vibration_data_combined.csv"

def save_to_csv(data):
    """Saves a list of (time, value) tuples to a CSV file."""
    with open(output_file, mode="a", newline="") as file:
        writer = csv.writer(file)
        writer.writerows(data)

def piezo_measurement(duration, start_event, stop_event, update_status):
    """Handles data collection from the piezo sensor."""
    try:
        update_status("Connecting to piezo server...")
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as piezo_socket:
            piezo_socket.settimeout(5)
            piezo_socket.connect((PIEZO_HOST, PIEZO_PORT))
            update_status("Connected to piezo server. Waiting for start signal...")

            start_event.wait()
            piezo_socket.sendall(f"{duration}\n".encode())
            update_status("Piezo: Receiving data...")

            data_buffer = []
            start_time = time.time()

            while not stop_event.is_set():
                try:
                    data = piezo_socket.recv(1024).decode()
                    if not data:
                        break

                    # Process received data
                    lines = data.split("\n")
                    for line in lines:
                        if "," in line:
                            try:
                                timestamp, value = line.split(",")
                                data_buffer.append((int(timestamp), int(value)))
                            except ValueError:
                                pass

                except socket.timeout:
                    update_status("Piezo: Data Recieved.")
                    break

            # Save the data
            if data_buffer:
                save_to_csv(data_buffer)
                update_status(f"Piezo: Data saved to {output_file}")
            else:
                update_status("Piezo: Data received.")
    except Exception as e:
        update_status(f"Complete")

def run_transducer(start_event, update_status):
    """Handles the activation of the transducer."""
    try:
        update_status("Connecting to transducer server...")
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as transducer_socket:
            transducer_socket.settimeout(5)
            transducer_socket.connect((TRANSDUCER_HOST, TRANSDUCER_PORT))
            update_status("Connected to transducer server. Waiting for start signal...")

            start_event.wait()
            update_status("Transducer: Activating vibration...")
            transducer_socket.sendall(b"GET / HTTP/1.1\r\nHost: 172.20.10.13\r\n\r\n")
            response = transducer_socket.recv(1024)
            update_status("Transducer: Vibration activated.")
    except socket.error as e:
        update_status(f"Transducer: Error - {e}")

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Piezo and Transducer Control")
        self.setGeometry(200, 200, 400, 200)

        # Layout
        layout = QVBoxLayout()

        # Start button
        self.start_button = QPushButton("Start Measurement")
        self.start_button.clicked.connect(self.start_process)
        layout.addWidget(self.start_button)

        # Status label
        self.status_label = QLabel("Status: Waiting for user input.")
        layout.addWidget(self.status_label)

        self.setLayout(layout)

        # Thread control
        self.start_event = threading.Event()
        self.stop_event = threading.Event()

    def start_process(self):
        """Start the piezo measurement and transducer process."""
        self.status_label.setText("Status: Starting process...")

        # Duration for the piezo measurement
        duration = 10

        # Create threads
        piezo_thread = threading.Thread(
            target=piezo_measurement,
            args=(duration, self.start_event, self.stop_event, self.update_status)
        )
        transducer_thread = threading.Thread(
            target=run_transducer,
            args=(self.start_event, self.update_status)
        )

        # Start threads
        piezo_thread.start()
        transducer_thread.start()

        # Signal threads to start
        self.start_event.set()

        # Stop measurement after duration
        threading.Timer(duration, self.stop_measurement).start()

    def stop_measurement(self):
        """Stop the piezo measurement and save the data."""
        self.stop_event.set()
        self.update_status("Measurement stopped. Data saved.")

    def update_status(self, message):
        """Update the status label."""
        self.status_label.setText(f"Status: {message}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
                                    
                        


This is what it looks like. Pressing the button completes everything, prom signal sending to recieving, to data saving. I hope to make it such that it can include my MATLAB data processing in order to characterize date (stable versus unstable screws).
...
...
...
...


Heres's all my files for this week Week 13 Files/a>