# Lab5 - Super Mario Coin Bank

Submitted by chan on Tue, 03/05/2013 - 03:20

## Description

This Super Mario Coin Bank is a red plastic cup which makes coin sound of the Super Mario when you put a coin into it. While putting money into it, you can see the visualization of the dropping coin on a screen and automatically calculate the amount of money you put into it. This coin bank makes different sound per a dollar. The coin bank consists of 3 components: a photocell, leds, and a speaker. The photocell located below the hole detect when a coin is inserted and then, 3 LEDs will blink 3 times and a speaker makes sound.

Components Used

1- Arduino

1- Piezo speaker

1- Photocell

1- Diffuser Glass Bottle

1-10kΩ Resistors

3- 220Ω Resistors

3- LEDs

# Arduino code:

/*

* Super Mario Coin Bank
* Eungchan Kim
* 2013-03-05
* Reference for speaker:
*/

int phoPin = A0; //photocells
int ledPin[3] = {11,9,10};//RGB
int criteria = 400; // criteria for detecting if a coin is inserted
int insert_count = 0; // count the number of inserted coins
// speaker
int speakerOut = 7;
// period is in microsecond so P = 1/f * (1E6)
#define  g4    2551    // 392 Hz
#define  c5    1912    // 523 Hz
#define  e5    1517
#define  g5    1276
#define  f5    1433
#define  b5    1012
#define  e6    758
#define  c6    955
#define  g6    638
#define  R     0       // Define a special note, 'R', to represent a rest

//super mario theme
int dollar[] = {e6, e6, R, e6, R, c6, e6, R, g6, R, R, g5};
int beats[] = {16, 16, 4, 16, 4, 16, 16, 4, 16, 4, 4, 16};
//coin sound
int q_dollar[] = {b5, e6};
int q_beats[] = {8, 40};

int MAX_COUNT = sizeof(dollar) / 2; // Melody length, for looping.
int MAX_COUNT4 = sizeof(q_dollar) / 2; // Melody length, for looping.
// Set overall tempo
long tempo = 10000;
// Set length of pause between notes
int pause = 1;
// Loop variable to increase Rest length
int rest_count = 50; //<-BLETCHEROUS HACK; See NOTES
// Initialize core variables
int toneM = 0;
int beat = 0;
long duration = 0;

void setup()
{
Serial.begin(9600);
pinMode(speakerOut, OUTPUT);
for (int i=0;i<3;i++){
pinMode(ledPin[i], OUTPUT);  // declare the ledPin as an OUTPUT
}
}

void loop()
{
if (insert < criteria){
Serial.println(insert);
for(int i=0;i<3;i++){digitalWrite(ledPin[i],HIGH);}
delay(100);
for(int i=0;i<3;i++){digitalWrite(ledPin[i],LOW);}
delay(100);
}
insert_count++;

if (insert_count%4 ==0){
sound(dollar,beats,MAX_COUNT);
}
else{
sound(q_dollar,q_beats,MAX_COUNT4);
}
// Set up a counter to pull from melody[] and beats[]

}
}
void sound(int* m, int* b, int max_num)
{
for (int i=0; i<max_num; i++) {
toneM = m[i];
beat = b[i];
duration = beat * tempo; // Set up timing
playTone();
// A pause between notes...
delayMicroseconds(pause);
}
}
void playTone() {
long elapsed_time = 0;
if (toneM > 0) { // if this isn't a Rest beat, while the tone has
//  played less long than 'duration', pulse speaker HIGH and LOW
while (elapsed_time < duration) {
digitalWrite(speakerOut,HIGH);
delayMicroseconds(toneM / 2);
// DOWN
digitalWrite(speakerOut, LOW);
delayMicroseconds(toneM / 2);
// Keep track of how long we pulsed
elapsed_time += (toneM);
}
}
else { // Rest beat; loop times delay
for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
delayMicroseconds(duration);
}
}
}

Processing code:

/*

* Super Mario Coin Bank
* Eungchan Kim
* 2013-03-05
*
* Reference for visualization
* "Forces (Gravity and Fluid Resistence) with Vectors by Daniel Shiffman"
*/

import processing.serial.*;
Serial port;

// moving bodies
Mover[] movers = new Mover[100];
// initial setting
int num=0;
float trigger =0;
float serial_input = 0;
int draw_flag =0;
// Liquid
Liquid liquid;

void setup() {
port = new Serial(this, "COM3", 9600);
port.bufferUntil('\n');
frameRate(30);
size(800, 400);
smooth();
reset();
// Create liquid object
liquid = new Liquid(0, 0, width+10, height/5, 0.1);
}

void draw() {
background(247,153,175);
// Draw water
liquid.display();
for (int i = 0;i<num;i++) {
draw_mover(movers[i]);
}
if (draw_flag ==1) {
if (num < 98) {
num++;
}
else num =0;
draw_flag=0;
}
textSize(32);
fill(255);
text('\$',10,120);
text(nfc(num*0.25,2), 30, 120);
textSize(32);
fill(247,153,175);
text("Super Mario Piggy Bank", 10, 30);
}
void mousePressed() {
if (num < 98) {
num++;
}
else num =0;
}
void draw_mover(Mover m) {
// Is the Mover in the liquid?
if (liquid.contains(m)) {
// Calculate drag force
PVector drag = liquid.drag(m);
// Apply drag force to Mover
m.applyForce(drag);
}
// Gravity is scaled by mass here!
PVector gravity = new PVector(0, 0.1*m.mass);
// Apply gravity
m.applyForce(gravity);
// Update and display
m.update();
m.display();
m.checkEdges();
}

// Restart all the Mover objects randomly
void reset() {
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover(0, 0, 0);
}
}
movers[i] = new Mover(random(3, 5), random(1,800), 0);
}
void serialEvent(Serial port) {
draw_flag = 1;
println(trigger);
}
/**
* Forces (Gravity and Fluid Resistence) with Vectors
* by Daniel Shiffman.
*
* Demonstration of multiple force acting on bodies (Mover class)
* Bodies experience gravity continuously
* Bodies experience fluid resistance when in "water"
*/

// Liquid class
class Liquid {
// Liquid is a rectangle
float x,y,w,h;
// Coefficient of drag
float c;

Liquid(float x_, float y_, float w_, float h_, float c_) {
x = x_;
y = y_;
w = w_;
h = h_;
c = c_;
}

// Is the Mover in the Liquid?
boolean contains(Mover m) {
PVector l = m.location;
if (l.x > x && l.x < x + w && l.y > y && l.y < y + h) {
return true;
}
else {
return false;
}
}

// Calculate drag force
PVector drag(Mover m) {
// Magnitude is coefficient * speed squared
float speed = m.velocity.mag();
float dragMagnitude = c * speed * speed;

// Direction is inverse of velocity
PVector drag = m.velocity.get();
drag.mult(-1);

// Scale according to magnitude
drag.setMag(dragMagnitude);
return drag;
}

void display() {
noStroke();
fill(255);
rect(x,y,w,h);
}
}
/**
* Forces (Gravity and Fluid Resistence) with Vectors
* by Daniel Shiffman.
*
* Demonstration of multiple force acting on bodies (Mover class)
* Bodies experience gravity continuously
* Bodies experience fluid resistance when in "water"
*/
class Mover {
// location, velocity, and acceleration
PVector location;
PVector velocity;
PVector acceleration;

// Mass is tied to size
float mass;

Mover(float m, float x, float y) {
mass = m;
location = new PVector(x, y);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
}

// Newton's 2nd law: F = M * A
// or A = F / M
void applyForce(PVector force) {
// Divide by mass
PVector f = PVector.div(force, mass*0.5);
// Accumulate all forces in acceleration
}
void update() {
// Velocity changes according to acceleration
// Location changes by velocity
// We must clear acceleration each frame
acceleration.mult(0);
}

// Draw Mover
void display() {
stroke(177,172,49);
strokeWeight(2);
fill(255,248,50);
ellipse(location.x, location.y, mass*16, mass*16);
textSize(20);
fill(177,172,49);
text("\$",location.x-6, location.y+7);
}

// Bounce off bottom of window
void checkEdges() {
if (location.y > height) {
velocity.y *= -0.4;  // A little dampening when hitting the bottom
location.y = height;
}
}
}

## Demo

Drupal theme by Kiwi Themes.