Sinewaves e plotter FFT

Oct 18 2020

Estou tentando codificar uma onda sin com 5 controles deslizantes: frequência, amplitude, mudança de fase, número de pontos de dados e tempo. No momento, estou tentando vincular meu controle deslizante de mudança de fase ao meu gráfico para que ele o atualize quando movo o controle deslizante. Percebo que meu código provavelmente é muito confuso e poderia ser mais conciso, mas posso ajustar isso mais tarde.

Eu acho que adicionar um controle deslizante de mudança de fase e o tempo para o qual a função é plotada também seria bom, como os controles deslizantes de frequência e amplitude (que funcionam).

Para quem não está familiarizado com os termos da física: amplitude: altura da onda (no eixo y)

  • frequência: número de vezes que uma onda passa por certo ponto por unidade de tempo. 1 Hertz = 1 onda passando por segundo
  • Diferença de fase: a mudança na posição inicial da onda atual onde amplitude = 0 em t = 0. Uma mudança de fase de 90 graus mudaria a função para a esquerda ou direita, representando então uma função cos em vez de seno.

Qualquer conselho para meu código atual seria muito apreciado!

Meu código até agora:

import tkinter
import numpy as np
from scipy import signal
from scipy.fft import fft, ifft as sc
from matplotlib import pyplot as p, animation
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
from matplotlib.widgets import Slider

root = tkinter.Tk()
root.wm_title("Embedding in Tk")
fig = Figure(figsize=(6, 5), dpi=100)
t = np.linspace(0, 5, 200)
f = 1
time = np.linspace(0, 100, 101)
y = np.sin(f*t)

fig.subplots_adjust(left=0.15, bottom=0.45)  # Adjust subplots region leaving room for the sliders 
and buttons

canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)

toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)


def on_key_press(event):
    print("you pressed {}".format(event.key))
    key_press_handler(event, canvas, toolbar)


canvas.mpl_connect("key_press_event", on_key_press)


def _quit():
    root.quit()  # stops mainloop
    root.destroy()


button = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)

# Amplitude slider
initiala = 1  # starting value of amplitude on graph
asliderax = fig.add_axes([0.25, 0.15, 0.65, 0.03])  # setting amplitude slider position
aslider = Slider(asliderax, 'Amp', 0.1, 10.0, valinit=initiala)  # setting amplitude slider values

# Frequency slider
initialf = 1  # starting value of frequency on graph
fsliderax = fig.add_axes([0.25, 0.1, 0.65, 0.03])  # setting frequency slider position
fslider = Slider(fsliderax, 'Freq', 0.1, 3.0, valinit=initialf)  # setting frequency slider values

# Time slider
initialt = 1  # starting value of time on graph
tsliderax = fig.add_axes([0.25, 0.2, 0.65, 0.03])  # setting time slider position
tslider = Slider(tsliderax, 'Time', 0.1, 100.0, valinit=initialt)  # setting time slider values

# Number of Points slider
initialp = 99  # starting value of number of points on graph
psliderax = fig.add_axes([0.25, 0.25, 0.65, 0.03])  # setting points slider position
pslider = Slider(psliderax, 'Points', 3, 30.0, valinit=initialp)  # setting frequency points values

# Phase slider
initialph = 0  # starting value of number of points on graph
phsliderax = fig.add_axes([0.25, 0.3, 0.65, 0.03])  # setting points slider position
phslider = Slider(phsliderax, 'Phase Change', 0, np.pi*2, valinit=initialph)  # setting frequency 
points values


def update(val):
    amp = aslider.val
    freq = fslider.val
    t = np.linspace(0, 5, 200)
    y.set_ydata(amp*np.sin(2*np.pi*freq*t))


fslider.on_changed(update)
aslider.on_changed(update)
tslider.on_changed(update)
pslider.on_changed(update)


tkinter.mainloop()

Respostas

1 RootTwo Oct 20 2020 at 18:20

Parece-me que você só precisa adicionar a fase ao ângulo em update().

def update(val):
    amp = aslider.val
    freq = fslider.val
    phase = phslider.val
    t = np.linspace(0, 5, 200)

    y.set_ydata(amp*np.sin(2*np.pi*freq*t + phase))  # << add phase here


fslider.on_changed(update)
aslider.on_changed(update)
tslider.on_changed(update)
pslider.on_changed(update)
phslider.on_changed(update)  # update on slider change