Lab 3: Sensors and Physical Interface Design

The goal of this lab is to control Faust synthesizers with sensors connected to the Teensy. Various mapping strategies are also introduced.

Electronic Basics

Sensors and Teensy Basics


void setup() {
  Serial.begin(9600); // initializing serial port
}

void loop() {
  int sensorValue = analogRead(A0); // retrieving sensor value on Analog pin 0
  Serial.println(sensorValue);
  delay(30); // wait for 30ms
}
#include <Audio.h>
#include "FaustSawtooth.h"

FaustSawtooth faustSawtooth;
AudioOutputI2S out;
AudioControlSGTL5000 audioShield;
AudioConnection patchCord0(faustSawtooth,0,out,0);
AudioConnection patchCord1(faustSawtooth,0,out,1);

void setup() {
  AudioMemory(2);
  audioShield.enable();
  audioShield.volume(0.1);
}

void loop() {
  int sensorValue = analogRead(A0);
  float frequency = sensorValue + 50;
  faustSawtooth.setParamValue("freq",frequency);
}

Exercise: Controlling Multiple Synth Parameters

g = hslider("amplitude",0.5,0,1,0.01)^2; 

Discrete Events

Looping Through Notes

The goal of this section is to make an instrument with the following behavior:

First, add a button to your circuit. The buttons provided in your kits have 4 pins (2 sets of 2 pins connected to each other). Place the button as follows on the breadboard:

Then connect one of the 2 pins to power and the other pin to the digital input 0 of your Teensy. You should add a pull-down resistor to this pin too. Note that an analog input could have been used as in the previous examples, but since we’re retrieving a discrete signal it doesn’t really make sense.

import("stdfaust.lib");
freq = hslider("pitch",60,0,127,1) : ba.midikey2hz;
gate = button("gate");
process = os.sawtooth(freq)*gate;
#include <Audio.h>
#include "FaustSawtooth.h"

FaustSawtooth faustSawtooth;
AudioOutputI2S out;
AudioControlSGTL5000 audioShield;
AudioConnection patchCord0(faustSawtooth,0,out,0);
AudioConnection patchCord1(faustSawtooth,0,out,1);

int notes[] = {60,60,60,62,64,62,60,64,62,62,60}; // the melody
int cnt = 0; // index to loop through the notes
bool change = true; // did the note status changed?
bool on = false; // what is the note status?

void setup() {
  pinMode(0, INPUT); // configuring digital pin 0 as an input
  AudioMemory(2);
  audioShield.enable();
  audioShield.volume(0.1);
}

void loop() {
  if (digitalRead(0)) { // button is pressed
    if(!on) change = true; // did the status of the button changed
    on = true;
  } 
  else {
    if(on) change = true; // did the status of the button change?
    on = false;
  }

  if(change){ // if the status of the button changed
    if(on){ // if the button is pressed
      faustSawtooth.setParamValue("gate",1);
      faustSawtooth.setParamValue("pitch",notes[cnt%11]);
      cnt++; // next note
    }
    else{
      faustSawtooth.setParamValue("gate",0);
    }
    change = false; // status changed
  }
}

Notes are saved in an integer array as MIDI note numbers. When digital pin 0 receives a signal, the on variable is set to true and vice versa. The change variable is used to make sure that we only send messages when necessary.

Exercise

Continuous parameters can be controlled in parallel of this button/looping mechanism. Add a lowpass filter to your sawtooth oscillator, e.g.,:

process = os.sawtooth(freq)*gate : fi.resonlp(ctFreq,5,0.5);

and control the value of the cutoff frequency with the photoresistor or FSR on your circuit. Spend some time thinking about the mapping of the cutoff frequency: what works best in this context?

Hint:

The min and max functions are often useful when mapping a sound synthesis parameter to a sensor. For instance, you probably noticed that the photoresistor doesn’t “fully exploit” the 0-1023 range offered by the 10bits converter. A common practice is to normalize the sensor output so that you can fully take advantage of its range. For example, say that you see that the output range of your sensor is 500-900, you could normalize its output with something like:

normSens = min(1023,max(0,sens - 550)*3.3);

Here subtracting 550 to the raw sensor output (sens) and then comparing that to 0 with max will make sure that the lowest value of the sensor is 0. Multiplying the result of this operation by 3.3 and comparing the result to 1023 with min will ensure that the highest value of the sensor is 1023.

Using the Other Sensors of Your Kit

You don’t have to do this section right away and you can jump directly to the assignment section at the bottom of this page if you wish. This section is meant to be used as a resource for your assignment and/or final project. If you have time, feel free to read through it though.

The other sensors in your kit require additional work to be used (e.g., soldering, use of specific libraries, etc.). Here, we provide you with some guidelines on how to use these sensors. These are just suggestions: this section doesn’t provide exhaustive information. Keep in mind that people in this field spend a lot of time finding tutorials on the web (Google is your friend). Also keep in mind that you might want to reuse these sensors: make sure that whatever you do here can be repurposed.

More generally, feel free to buy any sensor on the web for your projects. Sensors can be analog or digital, can work as resistors or not, etc. You’ll usually always be able to find a tutorial on how to use them with your Teensy. Remember that your Teensy works the same way as an Arduino so in some cases in might more judicious to do a search on the web for “thisSensor Arduino” instead of “thisSensor Teensy”, etc.

HC-SR04 Ultrasonic Distance Sensor

Your kit comes with an Ultrasonic Distance Sensor which measures the distance between the sensor and an object placed in front of it by emitting ultrasounds. Four wires need to be connected to this sensor: 2 for power and ground and 2 for controlling it/acquiring data. To use it with your Teensy, we suggest you to follow this tutorial: http://little-scale.blogspot.com/2020/06/teensy-36-with-hc-sr04-distance-sensor.html. It implies the use of a library: https://www.arduinolibraries.info/libraries/hcsr04 and of a couple of 10k resistors (part of your kit).

WARNING: this sensor operates at 5V (not 3.3V). It means that you’ll have to use the “Vin” pin of your Teensy to power it. Be extremely careful when doing so since you could fry your Teensy by plugging this pin directly to any other pin on the Teensy! The 10k resistors are used as a voltage divider here to make sure that the current sent to the Teensy from the sensor doesn’t exceed 3.3V.

Here is a wiring suggestion (following the tutorial above):


and some piece of code from the tutorial:

#include <HCSR04.h>

float data;

UltraSonicDistanceSensor distanceSensor(0,1);

void setup (){
  Serial.begin(9600);
}

void loop () {
  data = distanceSensor.measureDistanceCm();
  Serial.println(data);
  delay(100);
}

Potentiometer

Your kit comes with a set of linear rotary potentiometers. The leftmost and rightmost pin of pentiometers are for power (3.3V) and ground (flipping them will change the orientation of the potentiometer) and the center pin should be connected to an analog input of your Teensy. The pots in your kit can be mounted directly on a breadboard for prototyping:

If you want to use this type of sensor for your final project, you’ll probably have to solder wires to the pins, etc.

Accelerometer

The accelerometer in your kit is a three axis analog accelerometer. Some soldering is required to use it. Try to find male headers in the MaxLab and solder them to the accelerometer as shown on this picture:

This should allow you to mount the accelerometer on your breadboard:

The X, Y, and Z pins should be connected to individual analog inputs of your Teensy. VCC should go to the 3.3v pin of the Teensy and GND to the ground…

Alternatively, you could solder wires directly to the different pins of the accelerometer. The other end of each wire could connect to the breadboard.

Assignment (Due on Feb. 2, 2022)

Submissions

  • Carlino Cuono
  • Champ Darabundit
  • Dominic DeMarco
  • Reid Devereaux
  • Estelle He
  • Aaron Hodges
  • Kimia Koochakzadeh-Yazdi
  • Giancarlo Ricci
  • Olga Saadi
  • Vardaan Shah
  • Donald Swen
  • Kathleen Yuan
  • Andrew Lee Zhu