Project tutorial
Chatty Coasters

Chatty Coasters

Bringing interesting conversations back to the kitchen! 

  • 2,465 views
  • 1 comment
  • 4 respects

Components and supplies

15 x 60 inch General Soft Wood Board
×1
15 x 60 inch Clear Cast Acrylic
×1
15 x 60 inch Copier Paper
×1
15 x 60 inch Sheet White Vinyl
×1
4 inch diameter Steel Tube
×1
3/4" acrylic hemispheres
×3
Thin Plastic Circuit board
×1
Color-changing LEDs
×4
Microphone from Arduino Inventor Kit
×1
Speaker from Aduino Inventor Kit
×1
Amplifier
×1
A000053 iso both1
Arduino Micro & Genuino Micro
×1
Photo Sensor
×1
4415447 jg5sklyzsj
Resistor 220 ohm
×10
Tens70
9V battery (generic)
×1
LM7805 Series Transistor
×1
BM-700 Microphone
×1
KENYX 302 USB Recording Equipment
×1

About this project

Chatty Coasters

Chatty Coasters are interactive coasters that listen for silences and insert provocative conversation starters into them. 

Chatty Coasters are interactive drink holders that listen for silences in conversation and insert provocative questions into them.

In order to encourage healthy, thought-provoking conversation in kitchens, Chatty Coaster waits for drinkers to rest their cup on it and breaks prolonged silences with a clever, absurd or heartfelt question from a bank of programmed, voice recorded questions. Chatty Coaster can help bring strangers in a shared kitchen become friends, family members unwind and reconnect after a long day or at the very least, foster a meaningful, memorable conversation with your fellow drinkers.

Inspired by the many laughs and surprising thoughts from card games like Taboo & Table Topics and the rich history of coffee houses being the source of radical discourse, Chatty Coaster keeps up a good conversation while keeping your table clean.

Observational Documentation

After observing the social and functional interactions in a variety of kitchens (friends' and our own apartments, co-ops & International House), we observed the often awkward small talk that was exchanged among people who lived together but weren't acquainted with each other ("Where are you from?" "What do you study?" "What are you drinking?") as well as the listless conversation that old roommates had at the end of tiresome days ("How was your day?" "Okay. You?" "Alright.").

Most of the kitchens we observed had spaces to either sit and drink tea/coffee or stand around with other drinkers (like by the microwave on the counter.)

Brainstorming & Sketches

Brainstorming and lots of post-its produced a wide variety of ideas for devices that could provide a solution to our targeted problem and had the potential to enhance conversation in the kitchen space without being obtrusive or mundane.

Some notable ones: A coaster that identified the drinker to avoid cup mix-ups in conversations, a table that provides topics for dinner conversation

Chatty Coaster evolved as a hybrid from the best of these features.

Sketches

Initial ideas for Chatty Coaster

Prototypes

Directions How to make an interactive coaster:

Materials Used:

15 x 60 inch General Soft Wood Board

15 x 60 inch Clear Cast Acrylic

15 x 60 inch Copier Paper

15 x 60 inch Sheet White Vinyl

4 inch diameter Steel Tube

Thin Plastic pinhole board (??) (what is it called)

4 color-changing LEDs

Microphone from Arduino Inventor Kit

Speaker from Aduino Inventor Kit

Amplifier

Arduino Micro

Photo Sensor

10 220-ohm resistors

9V battery

LM7805 Series Transistor

Materials Used:

BM-700 Microphone

KENYX 302 USB Recording Equipment

Other tools: Lasercutter, Laptop, Adobe Illustrator, Machine Shop 

Part I- Casing

  1. Side: For the side of our coaster, we utilized an aluminum tube with a diameter of 4”. Using a lathe, we cut the tube to make a 35mm tall cylinder. Depending on how large your battery is, you can go shorter or taller. We also cut an inset into the top of the tube so that the lid would settle into the coaster without any protrusions.

  2. Lid: To create the lid and bottom, we cut a circle out of clear acrylic. The diameter of your circle depends on the diameter of the side you have chosen to use. In our case, the lid was 3.8” in diameter. Buff one side of the acrylic with a rotary sander to allow the LEDs to diffuse nicely in the final product.

  3. Bottom: To create the bottom of the lid, we cut a circle out of soft wood. We also cut a circle out of this circle for the speaker to poke out of. This allows the speaker to resonate off of the table surface and the volume is louder. We also utilized small plastic balls to hold the coaster off the ground.

Part II- Electronics

Cut the proto-board to fit inside the coaster. Wire up the audio and arduino micro up as shown in the diagram below.

Part III- Audio

Record audio snippets onto the computer. Save as wav files. Load onto SparkFun Audio-sound breakout-WTV020SD.

Design Process

The design process for Chatty Coaster began with a brainstorming of ideas to satisfy the prompt of "kitchen device" that employs sound. These ideas ranged from singing toasters to antagonistic chairs, but after much debate we narrowed our thinking to two possibilities: a table that picks up slack in conversations, and a coaster that records data about the objects placed on it. We combined these ideas to create Chatty Coaster: a physically unobtrusive drink-holding apparatus that carries not only your beverages but your conversations as well.

The greatest design challenge for Chatty Coaster was to keep it small while yet allowing it enough room inside to house all of the components it needed to both listen for and produce sound. These components included a speaker, a microphone, an amplifier, three LEDs, and an arduino with power source that would run all of these components. In order to arrive at our smallest model we slowly scaled down our casing, from a 6" diameter device made out of acrylic disks, to a 5" 3D-printed shell, to our final 4" device made out of milled aluminum, before scaling down the inside components to meet our new space requirements. We switched out our standard-sized arduino for an arduino mini, chose a thin speaker over a bulkier model, and soldered all of our components together on a stripboard, thinner than the breadboard we had originally planned on using.

After we had a device that was suitably small we cut a hole in its base so that the sound from the speaker could be heard more clearly, and added feet to the bottom to lift the whole device off the table such that the table's natural sound-reflecting properties would aid in the device's volume.

Videos

All code created for the project. The final code is combinedCode.ino, shown below.
ChattyCoaster Arduino Code
Untitled file

Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).

/* Simple test of the functionality of the photo resistor

Connect the photoresistor one leg to pin 0, and pin to +5V
Connect a resistor (around 10k is a good value, higher
values gives higher readings) from pin 0 to GND. (see appendix of arduino notebook page 37 for schematics).

----------------------------------------------------

           PhotoR     10K
 +5    o---/\/\/--.--/\/\/---o GND
                  |
 Pin 0 o-----------

----------------------------------------------------
*/

#include <Wtv020sd16p.h>

int resetPin = 2;  // The pin number of the reset pin.
int clockPin = 3;  // The pin number of the clock pin.
int dataPin = 4;  // The pin number of the data pin.
int busyPin = 5;  // The pin number of the busy pin.

/*
Create an instance of the Wtv020sd16p class.
 1st parameter: Reset pin number.
 2nd parameter: Clock pin number.
 3rd parameter: Data pin number.
 4th parameter: Busy pin number.
 */
Wtv020sd16p wtv020sd16p(resetPin,clockPin,dataPin,busyPin);

int sensorPin = 1;  //define a pin for Photo resistor
int ledRed = 13;

/* Discretize audio input to one sample every SAMPLE_WINDOW mS:
 * e.g. 50mS = 20Hz sample rate. */
const int sampleWindow = 50; 

/* After TIME_THRESH sampleWindows below VOL_THRESH, trigger event
 * 20Hz * 5S wait time = 100 */
const int timeThresh = 100;
int timeThreshCount;

/* Threshold for counting sample voltage as true noise. WARNING: need
 * to adjust based on audio input's hardware. */
const float volThresh = 0.5f;

/* Function pointer to a function to activate after silence threshold
 * is achieved. */
void (*threshFunc)(void) = NULL;

/* Threshold function declarations */
void blinkLed();
void printThresh();

/* Do not speak again for COOLDOWN milliseconds after speaking. */
int cooldown;
const int cooldownTime = 3000;

unsigned int sample;
unsigned int proceed = 0;

const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;

int DISPLAY_TIME = 10;  // In milliseconds

int color = 0;
int currColorVal;
unsigned int currAudio;
const unsigned int maxAudioFile = 15; 

void setup()
{
	currAudio = 0;
    wtv020sd16p.reset();
    Serial.begin(9600);  //Begin serial communcation
    pinMode( ledRed, OUTPUT);
    pinMode(RED_PIN, OUTPUT);
    pinMode(GREEN_PIN, OUTPUT);
    pinMode(BLUE_PIN, OUTPUT);
    timeThreshCount = 0;
    threshFunc = &playSong;
	currAudio = 0;
}

void loop()
{
    Serial.println(analogRead(sensorPin)); //Write the value of the photoresistor to the serial monitor.
    int light = analogRead(sensorPin);
    if (light < 600) {
      proceed = 1;
	  if (currColorVal < 768){
        showRGB(currColorVal);  
        currColorVal += 2;  
      } else {
        currColorVal = 0;
        showRGB(currColorVal);
      }
    }
    else{
      proceed = 0;
	  lightsOff();
    }
    
    delay(DISPLAY_TIME);
	Serial.print("currColorVal: ");
	Serial.println(currColorVal);

   if (proceed) {
      unsigned long startMillis= millis();  // Start of sample window
      unsigned int peakToPeak = 0;   // peak-to-peak level
  
      unsigned int signalMax = 0;
      unsigned int signalMin = 1024;
  	
      double volts = audioSample(startMillis);
      Serial.print("Volts: ");
      Serial.print(volts);
      Serial.print(". Cooldown: ");
      Serial.println(cooldown);
  
      if (volts <= volThresh) {
          timeThreshCount++;
      } else {
          timeThreshCount = 0;
      }
  
  	if (cooldown > 0) {
  		cooldown -= sampleWindow;
  	}
  
      if (timeThreshCount >= timeThresh && cooldown <= 0) {
          threshFunc();
  	  cooldown = cooldownTime;
          timeThreshCount = 0;
      }
   }
}

double audioSample(unsigned long startMillis) {
    unsigned int peakToPeak = 0;   // peak-to-peak level
    unsigned int signalMax = 0;
    unsigned int signalMin = 1024;

    // collect data for 50 mS
    while (millis() - startMillis < sampleWindow)
    {
        sample = analogRead(0);
        if (sample < 1024)  // toss out spurious readings
        {
            if (sample > signalMax)
            {
                signalMax = sample;  // save just the max levels
            }
            else if (sample < signalMin)
            {
                signalMin = sample;  // save just the min levels
            }
        }
    }
    peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
	return (peakToPeak * 3.3) /1024; // convert to volts
}

void blinkLed() {
    /* Intentionally block thread, do not listen during blocking */
    digitalWrite(ledRed, HIGH);
    delay(2000);
    digitalWrite(ledRed, LOW);
}

void showRGB(int color)
{

if (color <= 255)          // zone 1
{
	digitalWrite(RED_PIN, HIGH);
	digitalWrite(BLUE_PIN, LOW);
	digitalWrite(GREEN_PIN, LOW);
}
else if (color <= 511)     // zone 2
{
	digitalWrite(RED_PIN, LOW);
	digitalWrite(BLUE_PIN, HIGH);
	digitalWrite(GREEN_PIN, LOW);
}
else // color >= 512       // zone 3
{
	digitalWrite(RED_PIN, LOW);
	digitalWrite(BLUE_PIN, LOW);
	digitalWrite(GREEN_PIN, HIGH);
}
}

void lightsOff() {
	digitalWrite(RED_PIN, LOW);
	digitalWrite(BLUE_PIN, LOW);
	digitalWrite(GREEN_PIN, LOW);
}

void playSong()
{
	wtv020sd16p.asyncPlayVoice(currAudio);
	if (++currAudio >= maxAudioFile) {
		currAudio = 0;
	}
}

void playSongClipped()
{
  wtv020sd16p.asyncPlayVoice(0);
  delay(2000);
  wtv020sd16p.pauseVoice();
}

Future Iterations:

  • Coaster sets with themes - for people to buy coasters with a specific theme of conversation.
  • Sealing one face of the speaker to improve audio quality.
  • Detachable, customisable lids - good for washing and personality.
  • Look into making the coaster more compact by flattening electronics possibly with PCB boards.

Code

combinedCode.inoC/C++
ChattyCoaster Arduino Code
/* Simple test of the functionality of the photo resistor

Connect the photoresistor one leg to pin 0, and pin to +5V
Connect a resistor (around 10k is a good value, higher
values gives higher readings) from pin 0 to GND. (see appendix of arduino notebook page 37 for schematics).

----------------------------------------------------

           PhotoR     10K
 +5    o---/\/\/--.--/\/\/---o GND
                  |
 Pin 0 o-----------

----------------------------------------------------
*/

#include <Wtv020sd16p.h>

int resetPin = 2;  // The pin number of the reset pin.
int clockPin = 3;  // The pin number of the clock pin.
int dataPin = 4;  // The pin number of the data pin.
int busyPin = 5;  // The pin number of the busy pin.

/*
Create an instance of the Wtv020sd16p class.
 1st parameter: Reset pin number.
 2nd parameter: Clock pin number.
 3rd parameter: Data pin number.
 4th parameter: Busy pin number.
 */
Wtv020sd16p wtv020sd16p(resetPin,clockPin,dataPin,busyPin);

int sensorPin = 1;  //define a pin for Photo resistor
int ledRed = 13;

/* Discretize audio input to one sample every SAMPLE_WINDOW mS:
 * e.g. 50mS = 20Hz sample rate. */
const int sampleWindow = 50; 

/* After TIME_THRESH sampleWindows below VOL_THRESH, trigger event
 * 20Hz * 5S wait time = 100 */
const int timeThresh = 100;
int timeThreshCount;

/* Threshold for counting sample voltage as true noise. WARNING: need
 * to adjust based on audio input's hardware. */
const float volThresh = 0.5f;

/* Function pointer to a function to activate after silence threshold
 * is achieved. */
void (*threshFunc)(void) = NULL;

/* Threshold function declarations */
void blinkLed();
void printThresh();

/* Do not speak again for COOLDOWN milliseconds after speaking. */
int cooldown;
const int cooldownTime = 3000;

unsigned int sample;
unsigned int proceed = 0;

const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;

int DISPLAY_TIME = 10;  // In milliseconds

int color = 0;
int currColorVal;
unsigned int currAudio;
const unsigned int maxAudioFile = 15; 

void setup()
{
	currAudio = 0;
    wtv020sd16p.reset();
    Serial.begin(9600);  //Begin serial communcation
    pinMode( ledRed, OUTPUT);
    pinMode(RED_PIN, OUTPUT);
    pinMode(GREEN_PIN, OUTPUT);
    pinMode(BLUE_PIN, OUTPUT);
    timeThreshCount = 0;
    threshFunc = &playSong;
	currAudio = 0;
}

void loop()
{
    Serial.println(analogRead(sensorPin)); //Write the value of the photoresistor to the serial monitor.
    int light = analogRead(sensorPin);
    if (light < 600) {
      proceed = 1;
	  if (currColorVal < 768){
        showRGB(currColorVal);  
        currColorVal += 2;  
      } else {
        currColorVal = 0;
        showRGB(currColorVal);
      }
    }
    else{
      proceed = 0;
	  lightsOff();
    }
    
    delay(DISPLAY_TIME);
	Serial.print("currColorVal: ");
	Serial.println(currColorVal);

   if (proceed) {
      unsigned long startMillis= millis();  // Start of sample window
      unsigned int peakToPeak = 0;   // peak-to-peak level
  
      unsigned int signalMax = 0;
      unsigned int signalMin = 1024;
  	
      double volts = audioSample(startMillis);
      Serial.print("Volts: ");
      Serial.print(volts);
      Serial.print(". Cooldown: ");
      Serial.println(cooldown);
  
      if (volts <= volThresh) {
          timeThreshCount++;
      } else {
          timeThreshCount = 0;
      }
  
  	if (cooldown > 0) {
  		cooldown -= sampleWindow;
  	}
  
      if (timeThreshCount >= timeThresh && cooldown <= 0) {
          threshFunc();
  	  cooldown = cooldownTime;
          timeThreshCount = 0;
      }
   }
}

double audioSample(unsigned long startMillis) {
    unsigned int peakToPeak = 0;   // peak-to-peak level
    unsigned int signalMax = 0;
    unsigned int signalMin = 1024;

    // collect data for 50 mS
    while (millis() - startMillis < sampleWindow)
    {
        sample = analogRead(0);
        if (sample < 1024)  // toss out spurious readings
        {
            if (sample > signalMax)
            {
                signalMax = sample;  // save just the max levels
            }
            else if (sample < signalMin)
            {
                signalMin = sample;  // save just the min levels
            }
        }
    }
    peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
	return (peakToPeak * 3.3) /1024; // convert to volts
}

void blinkLed() {
    /* Intentionally block thread, do not listen during blocking */
    digitalWrite(ledRed, HIGH);
    delay(2000);
    digitalWrite(ledRed, LOW);
}

void showRGB(int color)
{

if (color <= 255)          // zone 1
{
	digitalWrite(RED_PIN, HIGH);
	digitalWrite(BLUE_PIN, LOW);
	digitalWrite(GREEN_PIN, LOW);
}
else if (color <= 511)     // zone 2
{
	digitalWrite(RED_PIN, LOW);
	digitalWrite(BLUE_PIN, HIGH);
	digitalWrite(GREEN_PIN, LOW);
}
else // color >= 512       // zone 3
{
	digitalWrite(RED_PIN, LOW);
	digitalWrite(BLUE_PIN, LOW);
	digitalWrite(GREEN_PIN, HIGH);
}
}

void lightsOff() {
	digitalWrite(RED_PIN, LOW);
	digitalWrite(BLUE_PIN, LOW);
	digitalWrite(GREEN_PIN, LOW);
}

void playSong()
{
	wtv020sd16p.asyncPlayVoice(currAudio);
	if (++currAudio >= maxAudioFile) {
		currAudio = 0;
	}
}

void playSongClipped()
{
  wtv020sd16p.asyncPlayVoice(0);
  delay(2000);
  wtv020sd16p.pauseVoice();
}
Github
All code created for the project. The final code is combinedCode.ino, shown below.

Comments

Similar projects you might like

Habitatt

Project tutorial by 5 developers

  • 11,643 views
  • 3 comments
  • 36 respects

Arduino Ethernet Rfid card reader

Project tutorial by David Smerkous

  • 30,697 views
  • 15 comments
  • 50 respects

LED Blink Pattern

Project tutorial by Matt Arnold

  • 30,329 views
  • 14 comments
  • 84 respects

Useless Box

Project tutorial by Adrienne Jan

  • 16,553 views
  • 2 comments
  • 7 respects

Two Mode Robot Controlling through Android and Windowsphone8

Project tutorial by Anas Siddiqui

  • 16,314 views
  • 9 comments
  • 48 respects

Indoor NeoPixel Thermometer 

Project tutorial by Jonathan Eskow

  • 4,304 views
  • 2 comments
  • 11 respects
Add projectSign up / Login