Motorized Arduino Piggy Bank That Can Recognize Currency and Be a Money Counter.
26 Views, 1 Favorites, 0 Comments
Motorized Arduino Piggy Bank That Can Recognize Currency and Be a Money Counter.
For my Design Thinking class this semester, we were tasked with creating something that could tackle a specific problem that we had at the beginning of the semester. My problem was that I was so broke and I really wanted to save money. So then I tried to problem-solve that by making an EPIC motorized piggy-bank. My main idea was for it to give auditory feedback when I put money in. If it's less than 10000 won, It'll make fun of me, but if it's over 10000, then I'll be greeted with a compliment. Then, I decided to add a money counter on the side as well. Lastly, I decided to put the circuit inside a cardboard casing of a Minecraft pig, just to add some personality to it. In the future, I'd like to further develop the case into possibly making a 3D-printed case so it looks more realistic. Also, I'd fix the inner of the case to make the money storage mechanism better, but for now, this is what I have!
Downloads
Supplies
- Arduino Uno
- TCS3200 Color Sensor
- Servo Motor SG90 (Jailbroken to spin full 360)
- DFPlayer Mini (with an SD card)
- 8Ohm Speaker
- The Display: LCD 16x2 I2C
- Light Dependent Resistor (LDR/Light Sensor)
- Miscellaneous: Jumper wires, a breadboard, and a sturdy cardboard box.
Wiring
Make sure not to tangle the wires! I personally braided some of them hehe
All GND -> GND and all VCC/Power -> 5V
Component:
Arduino Pin
LCD Screen (I2C)
SDA -> A4, SCL -> A5
Servo Motor
Signal (Yellow/Orange) -> Pin 7
Color Sensor
S0->2, S1->3, S2->4, S3->5, OUT->6
DFPlayer Mini
TX->10, RX->11, SPK1 -> 8Ohm Speaker, SPK2 -> 8Ohm Speaker
Light Sensor
Analog Pin A1
An analog sensor needs a "bridge" to give the Arduino a clear signal.
So on your breadboard:
- Connect one leg of the sensor to 5V.
- Connect the other leg to Analog Pin A1.
- Connect a 10k ohm resistor from that same A1 pin to GND.
Snatch Mechanism
Forget expensive parts—you can build a professional-grade bill-grabbing mechanism using just cardboard, a chopstick, and rubber bands! This is a friction-feed roller, the same technology used in real-world currency counters.
How it works: The servo motor acts as the "muscle." When it spins, the rubber bands on the cardboard tube provide the traction (friction) needed to grab the edge of the banknote and pull it instantly into the box.
Build Instructions:
- The Roller: Slide a wooden chopstick through a small cardboard tube.
- The Grip: Wrap 2-4 rubber bands around the tube. These are your "tires." The more rubber, the better the grip on the bill.
- The Guide: You need a "gap" between your active roller and the top of the box slot. Place your roller so that it barely touches the top ceiling of your box slot. If the gap is too wide, the bill won't move; if it's too tight, the bill will jam.
- The Connection: Connect the other end of the chopstick directly to your servo horn. A little hot glue or tape creates a secure, non-slip connection.
Pro-Tip for Success:
- Test the "Bite": Before mounting the servo permanently, manually spin the chopstick with your fingers. You should feel the rubber bands "bite" into any paper you slide through the slot.
- Troubleshooting: If the bank struggles to pull the money in, try increasing the number of rubber bands to add more grip, or check that your servo is spinning in the direction that pulls the bill in (not pushing it out!).
Color Data Gathering
Before we can sort the money, we need to know what the sensor "sees" when you insert a bill. Upload this simple code to your Arduino and open your Serial Monitor (set to 9600 baud).
// SENSOR TEST CODE
const int s0=2, s1=3, s2=4, s3=5, out=6;
void setup() {
Serial.begin(9600);
pinMode(s0,OUTPUT); pinMode(s1,OUTPUT); pinMode(s2,OUTPUT); pinMode(s3,OUTPUT); pinMode(out,INPUT);
digitalWrite(s0,HIGH); digitalWrite(s1,LOW);
}
void loop() {
digitalWrite(s2,LOW); digitalWrite(s3,LOW); Serial.print("R: "); Serial.print(pulseIn(out, LOW));
digitalWrite(s2,HIGH); digitalWrite(s3,HIGH); Serial.print(" G: "); Serial.print(pulseIn(out, LOW));
digitalWrite(s2,LOW); digitalWrite(s3,HIGH); Serial.print(" B: "); Serial.println(pulseIn(out, LOW));
delay(500);
}
Light Threshold Data Gathering
Now, let's calibrate your "Sentry." We need the bank to stay asleep until it detects the shadow of a bill.
Upload this code:
const int lightSensorPin = A1;
void setup() { Serial.begin(9600); }
void loop() {
Serial.print("Current Light Level: ");
Serial.println(analogRead(lightSensorPin));
delay(500);
}
MASTER CODE!!
Now, take your values from the previous steps and plug them into this code.
How to customize this code:
- boxR, boxG, boxB: Set these to the "Empty Box" values you see when you run the code in Step 3.
- lightThreshold: Use the middle value you found in Step 4.
#include <Servo.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo snatchServo;
const int servoPin = 7;
// --- CONFIGURATION SECTION ---
const int boxR = 218; // Change these to your "Empty Box" RGB readings
const int boxG = 219;
const int boxB = 177;
const int lightThreshold = 730; // Change this to your Step 4 value
const int minConfidence = 40;
// -----------------------------
SoftwareSerial mySoftwareSerial(10, 11);
DFRobotDFPlayerMini myDFPlayer;
const int s0 = 2, s1 = 3, s2 = 4, s3 = 5, out = 6;
const int lightSensorPin = A1;
long totalSavings = 0;
void setup() {
Serial.begin(9600); mySoftwareSerial.begin(9600); randomSeed(analogRead(0));
lcd.init(); lcd.backlight();
updateLCD("Piggy Bank", "Waking up...");
delay(3000);
if (!myDFPlayer.begin(mySoftwareSerial)) { Serial.println("DFPlayer handshake skipped."); }
myDFPlayer.volume(25);
snatchServo.attach(servoPin); snatchServo.write(90); delay(100); snatchServo.detach();
pinMode(s0, OUTPUT); pinMode(s1, OUTPUT); pinMode(s2, OUTPUT); pinMode(s3, OUTPUT); pinMode(out, INPUT);
digitalWrite(s0, HIGH); digitalWrite(s1, LOW);
updateLCD("Piggy Bank", "Total: 0 KRW");
}
void loop() {
int lightLevel = analogRead(lightSensorPin);
if (lightLevel < lightThreshold) {
updateLCD("Scanning...", "Please wait.");
snatchServo.attach(servoPin); snatchServo.write(180); delay(2400); snatchServo.write(90); snatchServo.detach();
int redValue = max(0, boxR - readColorChannel(LOW, LOW));
int greenValue = max(0, boxG - readColorChannel(HIGH, HIGH));
int blueValue = max(0, boxB - readColorChannel(LOW, HIGH));
int totalSignal = redValue + greenValue + blueValue;
long currentDeposit = 0;
String billName = "Counterfeit!";
if (totalSignal > minConfidence) {
// Logic check: If you find bills are sorted wrong, just swap these values!
if (greenValue > redValue && greenValue > blueValue) {
currentDeposit = 10000; billName = "+ 10,000 KRW";
} else if (redValue > 150 || greenValue > 150) {
currentDeposit = 5000; billName = "+ 5,000 KRW";
}
}
if (currentDeposit > 0) {
totalSavings += currentDeposit;
updateLCD(billName, "Total: " + String(totalSavings));
delay(500);
myDFPlayer.play(currentDeposit < 10000 ? random(1, 3) : random(3, 5));
} else { updateLCD("Rejected!", "Try again."); }
delay(6000); // Wait for user to remove hand/bill
updateLCD("Piggy Bank", "Total: " + String(totalSavings) + " KRW");
}
}
int readColorChannel(int s2State, int s3State) {
digitalWrite(s2, s2State); digitalWrite(s3, s3State);
return pulseIn(out, LOW);
}
void updateLCD(String line1, String line2) {
lcd.clear(); lcd.setCursor(0, 0); lcd.print(line1); lcd.setCursor(0, 1); lcd.print(line2);
}
Assemble.
Put your Arduino and breadboard inside your box, cut a slot for the bills, and you're done! You've built a robot that helps you save money. Test it out, watch your total grow, and enjoy your smart piggy bank!