Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1f7043f2ed | |||
| 727885e6be | |||
| ecd35bfffa | |||
| 4471b9c224 | |||
| a8e8bea6e4 |
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 985 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
@@ -1,112 +0,0 @@
|
||||
"""
|
||||
ldr.py
|
||||
Display analog data from Arduino using Python (matplotlib)
|
||||
Author: Mahesh Venkitachalam
|
||||
Website: electronut.in
|
||||
"""
|
||||
|
||||
import sys, serial, argparse
|
||||
import numpy as np
|
||||
from time import sleep
|
||||
from collections import deque
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.animation as animation
|
||||
|
||||
|
||||
# plot class
|
||||
class AnalogPlot:
|
||||
# constr
|
||||
def __init__(self, strPort, maxLen):
|
||||
# open serial port
|
||||
self.ser = serial.Serial(strPort, 9600)
|
||||
|
||||
self.ax = deque([0.0]*maxLen)
|
||||
self.ay = deque([0.0]*maxLen)
|
||||
self.maxLen = maxLen
|
||||
|
||||
# add to buffer
|
||||
def addToBuf(self, buf, val):
|
||||
if len(buf) < self.maxLen:
|
||||
buf.append(val)
|
||||
else:
|
||||
buf.pop()
|
||||
buf.appendleft(val)
|
||||
|
||||
# add data
|
||||
def add(self, data):
|
||||
assert(len(data) == 2)
|
||||
self.addToBuf(self.ax, data[0])
|
||||
self.addToBuf(self.ay, data[1])
|
||||
|
||||
# update plot
|
||||
def update(self, frameNum, a0, a1):
|
||||
try:
|
||||
line = self.ser.readline()
|
||||
data = [float(val) for val in line.split()]
|
||||
# print data
|
||||
if(len(data) == 2 and not pause):
|
||||
self.add(data)
|
||||
a0.set_data(range(self.maxLen), self.ax)
|
||||
a1.set_data(range(self.maxLen), 0)
|
||||
except KeyboardInterrupt:
|
||||
print('exiting')
|
||||
|
||||
if not pause:
|
||||
return a0,
|
||||
|
||||
# clean up
|
||||
def close(self):
|
||||
# close serial
|
||||
self.ser.flush()
|
||||
self.ser.close()
|
||||
|
||||
pause = False
|
||||
def onClick(event):
|
||||
global pause
|
||||
pause = not pause
|
||||
|
||||
# main() function
|
||||
def main():
|
||||
# create parser
|
||||
parser = argparse.ArgumentParser(description="LDR serial")
|
||||
# add expected arguments
|
||||
parser.add_argument('--port', dest='port', required=True)
|
||||
|
||||
# parse args
|
||||
args = parser.parse_args()
|
||||
|
||||
#strPort = '/dev/tty.usbserial-A7006Yqh'
|
||||
strPort = args.port
|
||||
|
||||
print('reading from serial port %s...' % strPort)
|
||||
|
||||
# plot parameters
|
||||
analogPlot = AnalogPlot(strPort, 300)
|
||||
|
||||
print('plotting data...')
|
||||
|
||||
# set up animation
|
||||
fig = plt.figure()
|
||||
|
||||
ax = plt.axes(xlim=(0, 300), ylim=(0, 1023))
|
||||
a0, = ax.plot([], [])
|
||||
a1, = ax.plot([], [])
|
||||
fig.canvas.mpl_connect('button_press_event', onClick)
|
||||
anim = animation.FuncAnimation(fig, analogPlot.update,
|
||||
fargs=(a0, a1),
|
||||
frames=None,
|
||||
interval=50)
|
||||
|
||||
# show plot
|
||||
plt.show()
|
||||
|
||||
# clean up
|
||||
analogPlot.close()
|
||||
|
||||
print('exiting.')
|
||||
|
||||
|
||||
# call main
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
// analog-plot
|
||||
//
|
||||
// Read analog values from A0 and A1 and print them to serial port.
|
||||
//
|
||||
// electronut.in
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
void setup()
|
||||
{
|
||||
// initialize serial comms
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// read A0
|
||||
int val1 = analogRead(0);
|
||||
// read A1
|
||||
int val2 = analogRead(1);
|
||||
// print to serial
|
||||
Serial.print(val1);
|
||||
Serial.print(" ");
|
||||
Serial.print(val2);
|
||||
Serial.print("\n");
|
||||
// wait
|
||||
delay(50);
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
\documentclass[titlepage]{scrartcl}
|
||||
\usepackage{enumitem}
|
||||
\usepackage[british]{babel}
|
||||
\usepackage[style=apa, backend=biber]{biblatex}
|
||||
\DeclareLanguageMapping{british}{british-apa}
|
||||
\usepackage{url}
|
||||
\usepackage{float}
|
||||
\usepackage[labelformat=empty]{caption}
|
||||
\restylefloat{table}
|
||||
\usepackage{perpage}
|
||||
\MakePerPage{footnote}
|
||||
\usepackage{abstract}
|
||||
\usepackage{graphicx}
|
||||
% Create hyperlinks in bibliography
|
||||
\usepackage{hyperref}
|
||||
\usepackage{amsmath}
|
||||
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage{blindtext}
|
||||
\setkomafont{disposition}{\normalfont\bfseries}
|
||||
|
||||
\graphicspath{
|
||||
{./resources/},
|
||||
}
|
||||
\addbibresource{~/Documents/library.bib}
|
||||
|
||||
\newsavebox{\abstractbox}
|
||||
\renewenvironment{abstract}
|
||||
{\begin{lrbox}{0}\begin{minipage}{\textwidth}
|
||||
\begin{center}\normalfont\sectfont\abstractname\end{center}\quotation}
|
||||
{\endquotation\end{minipage}\end{lrbox}%
|
||||
\global\setbox\abstractbox=\box0 }
|
||||
|
||||
\usepackage{etoolbox}
|
||||
\makeatletter
|
||||
\expandafter\patchcmd\csname\string\maketitle\endcsname
|
||||
{\vskip\z@\@plus3fill}
|
||||
{\vskip\z@\@plus2fill\box\abstractbox\vskip\z@\@plus1fill}
|
||||
{}{}
|
||||
\makeatother
|
||||
|
||||
\DeclareCiteCommand{\citeyearpar}
|
||||
{}
|
||||
{\mkbibparens{\bibhyperref{\printdate}}}
|
||||
{\multicitedelim}
|
||||
{}
|
||||
|
||||
\begin{document}
|
||||
\title{ECS742\\Interactive Digital Media Techniques\\Mini-Assignment 1: Arduino}
|
||||
\subtitle{\LARGE{Technical Report}}
|
||||
\author{Sam Perry\\Student Number: 160842984}
|
||||
\date{}
|
||||
\maketitle
|
||||
|
||||
\section{Connecting and reading the FSR}
|
||||
Initially, a circuit was created to demonstrate the reading of values from
|
||||
the FSR (Force Sensitive Resistor). A 5V supply was used to pass a current
|
||||
through the resistor, which was measured via analog input 0. A 10kohm
|
||||
pull-down resistor was connected to ground between the FSR and the input.
|
||||
This was necessary to avoid a direct connection between the 5V supply and
|
||||
ground at points when the FSR provides little to no resistance. This also
|
||||
creates a consistently low value to input when resistance from the FSR
|
||||
is high, avoiding unpredictable floating readings caused by a disconnected
|
||||
input.\\
|
||||
\begin{figure}[H]
|
||||
\makebox[\textwidth]{\includegraphics[width=0.35\textwidth]{Step1}}
|
||||
\end{figure}
|
||||
|
||||
Code was written to print values to the serial port. A Python script was
|
||||
used to record these values as shown:
|
||||
\begin{figure}[H]
|
||||
\caption{Value measured over time. A sharp increase in pressure followed by a gradual release is displayed.}
|
||||
\makebox[\textwidth]{\includegraphics[width=0.75\textwidth]{FSR_Linearity}}
|
||||
\end{figure}
|
||||
|
||||
From these readings it can be seen that there is a non-linear relationship
|
||||
between applied pressure and measurement. As the voltage measured is
|
||||
proportional to the inverse of the FSR resistance \parencite{ada2016},
|
||||
voltage increases at what appears to be an exponentially decreasing rate as
|
||||
resistance increase at the same rate.
|
||||
|
||||
\section{Using the FSR values to create a tone}
|
||||
Building on the circuit developed in step 1, a speaker was attached. The
|
||||
speaker was connected to digital output 8 and to ground. Code was written
|
||||
to read input from the FSR, scale values to fall between pre-determined
|
||||
high and low values, and output a tone of the frequency specified for 20ms.
|
||||
The result is an instrument that outputs rapid short tones that increase in
|
||||
pitch based on pressure applied.
|
||||
|
||||
\begin{figure}[H]
|
||||
\makebox[\textwidth]{\includegraphics[width=0.35\textwidth]{Step2}}
|
||||
\end{figure}
|
||||
|
||||
The speaker is capable of producing tones as low as around 100hz. Below
|
||||
this, the tone begins to lose it's tonal quality and the rhythmic
|
||||
characteristics become more prominent. The speaker can also produce tones
|
||||
as high as around 10Khz, however perceived loudness deteriorates beyond
|
||||
5-6Khz.\\
|
||||
The instruments is capable of producing interesting melodies and has a
|
||||
tactile response. However the lack of control over amplitude and the
|
||||
inaccuracy of the resistor result in difficulties when trying to perform a
|
||||
sequence of specific notes. This could be improved reducing the range of
|
||||
playable frequencies. This would allow for greater pitch accuracy at a cost
|
||||
of a lower range of possible tones.
|
||||
|
||||
\section{Using buttons to make a simple keyboard}
|
||||
Buttons were then added to the instrument. This allows a user to play 8
|
||||
tones in a chromatic scale. Each button was attached to the circuit in a
|
||||
similar fashion to that of the FSK. Pull down resistors were used and each
|
||||
button was assigned a digital input, allowing the arduino to determine the
|
||||
state of the button as being on (HIGH) or off (LOW). Although this method
|
||||
worked corectly, an alternative method using a "resistor ladder" is
|
||||
detailed in the arduino projects book~\parencite[p.79]{arduino2015}. This
|
||||
would allow for the same performance, whilst using only one analog input as
|
||||
opposed to the 8 digital inputs as used in this implementation. The
|
||||
arduino was then programmed to iterate across buttons until an active
|
||||
button was found. An array of note frequencies would then be accessed by
|
||||
index to determine the button's note frequency. This could then be played
|
||||
through the built in tone function using the speaker.\\
|
||||
|
||||
\begin{figure}[H]
|
||||
\makebox[\textwidth]{\includegraphics[width=0.35\textwidth]{Step3}}
|
||||
\end{figure}
|
||||
|
||||
The instrument is now able to play precise tones with far greater accuracy
|
||||
than was possible using the FSR. However, this comes at the cost of the
|
||||
tactile and expressive control offered by the FSR. The limit of available
|
||||
notes and lack of touch sensitivity make for an unintuitive playing
|
||||
experience.
|
||||
|
||||
\section{Adding vibrato using the FSR}
|
||||
Vibrato was added to the keyboard instrument by scaling the values from the
|
||||
FSR based on the output pitch. By calculating the output pitch +/- 5\%, the
|
||||
pitch could be modulated by scaling FSR values to within these upper and
|
||||
lower boundaries. This allows the user to vary the pitch with the
|
||||
expressivity of the FSR whilst maintaining a degree of accuracy from the
|
||||
button based input. A issue arises in the FSR resting at it's lowest value,
|
||||
forcing a player to modulate upwards from -5\% rather than beginning at the
|
||||
pitch specified by the button. This may cause issues for a performer with
|
||||
regards to staying in tune, as a performer would have to consistently apply
|
||||
pressure to stay at the centre frequency of any given note. An
|
||||
alternative would be to start at the desired frequency and bend up or down
|
||||
only, although this may alter the pitch too far from the initial pitch.
|
||||
Another alternative might be to have two FSRs, one for each direction.
|
||||
However, this would not allow for the same level of smoothness around the
|
||||
centre frequency due to the need to switch.
|
||||
|
||||
\section{Bonus - Melody Playback}
|
||||
Melody playback was implemented by iterating over an array of note indexes
|
||||
on each button press. Button state was stored in a variable to allow melody
|
||||
position to be incremented over repeated presses of the button. Melody
|
||||
position was reset to 0 at the end of each loop to allow for continuous
|
||||
looping of the melody.
|
||||
|
||||
\printbibliography
|
||||
\end{document}
|
||||
Reference in New Issue
Block a user