<br>

Final project

Introduction and project goals

An issue that I have is that I have tons of coins.

Image

This is a plastic bag full of coins that I have at home (I have many other coins in my bedroom, purses..). I think I have at least 50 euros in this bag. The problem is that I never use the coins I have. The thought of having to sort and count them gives me a headache. I'm too lazy to do it. So, I thought of a smart piggy bank that would sort the coins automatically. Pennies with pennies, quarters with quarters...

This would also tell you how much money you have in total and also per category. It would tell you how many dollars you have with your quarters for example.

It would also be possible to withdraw money by saying how much you'd like to withdraw, specifying whether you'd prefer pennies, etc., depending on your needs.

I got the idea from thinking about the product I had come up with for an entrepreneurial course. It was a smart trash can that we called TrashScan that could recognize any kind of waste and sort it accordingly. Creating such a trash can would require an enormous amount of training in waste recognition. I tried to think of something else and it was with this automatic sorting system in mind that I came up with the idea of a smart piggy bank.

How to make it?

Here are some inspirations.

Image Image

For coin sorting, I want to do it mechanically, with a sort of ramp with different-sized holes for the coins to fall through. I want my piggy bank to be a box that's not completely closed. I want the coins to be visible, like in the photo above. For the couting part, I will need IR sensors and a LCD screen. I will first prototype it on cardboard and then use wood probably.

Bill of materials

Timeline


JULY 5

I started working on the final project. I had already been working on it at home but it was my first day using the lab.

At home, I first tried to design the box but I realised I would need to know how much space the sensors would take for example.

I started by making the ramp and then see if there were some IR sensors at the lab to start getting familiar with it.

To make the ramp, I first looked up the diameters of the various parts on the Internet.

Image

On my ramp, I've sorted the diameters from smallest to largest. First the 10-cent coins, then the 1-cent coins, the 5-cent coins, the 25-cent coins, the 1-dollar coins and the 50-cent coins. (Apparently, the 50 centimes are very rare, so for the moment I'm assuming they don't exist.This doesn't change anything to my ramp, since they're at the very end, so I don't need to make a hole like for the others. As for the circuit and coding, I'll add a sensor if necessary).UPDATE: Apparently, it's more of a collector's item and there aren't many of them in circulation so I won't be needing another sensor.

At first, I wanted to make rounds with a slightly larger diameter, but I figured rectangles would be safer for the pieces to fall into. I laser cut the ramp, and it was not really a success as the laser cutter cut too much so the coins weren't going were there were supposed to go. I've done some more tests, but I haven't found the perfect ramp yet. I am also not sure how much space I should leave between the holes because I don't know yet where my sensors will be or the size of each "mini piggy bank" depending on the sorting of the coins.

Image

Here is a video of my ramp so far. It still doesn't work very well, as the 1-cent coins fall into the dime hole. But I am working on it.

I really wanted to focus on the sensors so I tried different options. None of them really worked out. I first used a mini PIR sensor which was not precise at all. I then tried to create a DIY IR sensor with an IR transmitter and IR receiver.

Image

Here is the result that is not very conclusive. Sometimes it worked sometimes it didn't. I am not really happy with this solution.

I have found IR sensors online that I think would help me. I would need 6 sensors and with DIY ones I don't see how I can fit them in my piggy bank.

Image

I'm a bit disappointed with the day because things didn't go as well as I'd hoped. I feel like I'm still in the same place and I haven't made any progress. I'm afraid I'll never be able to make that piggy bank.

JULY 11 & 12

I continued to make prototypes of the ramp to sort the coins with the laser cutter to try and find the perfect size, knowing that the laser cutter always cuts a little more. I especially had a problem with the first hole. The 1-cent coin kept falling into it. Here are the measures I used that finally worked.

Image

I added an inclined plane on one side of the ramp to make sure that the pieces fall in the right place so I needed to 3D print my ramp. This is part of my week 5 assignment (details on this page).

Image

Today, we learnt about sensors so I have decided to try another type of sensors for my final project: piezo discs. I think this is a good idea and that this will work better than the DIY IR sensors.I started with one sensor and I coded on Arduino so that I would print "coin detected" if it "felt" something. It worked well even for the smallest coins.

Then, I added another piezo disc to my circuit and connected it to another pin on the Arduino board. I changed my code so that it would print "coin detected 1" when a coin fell on it and "coin detected 2" when a coin fell on the other one.Again, it worked really well. I even tried to simulate the fall from the sorting ramp.

Here is the material, the circuit and the codes I used.

Image Image
  
// Pin number for the piezoelectric disk
const int piezoPin = 8;

void setup() {
  Serial.begin(9600); // Initialize serial communication at 9600 baud

  pinMode(piezoPin, INPUT); // Configure the piezoelectric disk pin as input
}

void loop() {
  int piezoValue = digitalRead(piezoPin); // Read the state of the piezoelectric disk

  // If a coin is detected
  if (piezoValue == HIGH) {
    Serial.println("Coin detected");
    delay(500); // Wait for 500 milliseconds to avoid bouncing
  }
}

    
  
  
const int sensor1Pin = 3; // Digital pin of sensor 1
const int sensor2Pin = 4; // Digital pin of sensor 2

void setup() {
  Serial.begin(9600); // Initialize serial communication at 9600 baud

  pinMode(sensor1Pin, INPUT); // Configure sensor 1 pin as input
  pinMode(sensor2Pin, INPUT); // Configure sensor 2 pin as input
}

void loop() {
  int sensor1Value = digitalRead(sensor1Pin); // Read the state of sensor 1
  int sensor2Value = digitalRead(sensor2Pin); // Read the state of sensor 2

  if (sensor1Value == HIGH) {
    Serial.println("Coin detected 1");
    delay(500); // Wait for 500 milliseconds to avoid bouncing
  }

  if (sensor2Value == HIGH) {
    Serial.println("Coin detected 2");
    delay(500); // Wait for 500 milliseconds to avoid bouncing
  }
}

    
  

At the same time, I thought about the structure of my piggy bank. First of all, I'm going to need some ramps to make it easier for the coins to fall. The ramp will be less inclined at the beginning, and that's where the sensors will be placed. I've modeled this on Fusion 360. Now, I have several solutions. Either I print 6 ramps directly with 3D printing, which allows me to make 6 holes in the ramps and make them hollow so I can pass the disc wires through the holes and hide all the wires under the ramps. The problem with this solution is that it's going to take a long time to print. It also means that the ramps have to be bigger, so that there's enough room underneath. Alternatively, I use the laser cutter on cardboard or wood and glue several pieces together to create ramps. In this case, I won't make any holes, but instead I'll have 1 second box glued to the back of my piggy bank (in which I'll have made holes) where I'll put all the wires.

Here's the modeling I've done so far, and also a prototype I made using the laser cutter. I don't think there'll be enough room underneath for a whole circuit.

Image Image Image

I also thought of making funnels to make sure that the parts reached the sensors. I 3D printed a prototype.everything works fine with the funnel, ramp and sensors. Having said that, maybe I can improve the funnels so that they fit better around the part that's going to sort the money.

Image Image
Download my STL file
Download my gcode file
Image

I'm still working on how I'm going to make my piggy bank on the ramps, the funnels, where the parts will be, how to place my sensors and the circuit. Right now, I'm a bit anxious about it. I also need to think about walls to separate each compartment I think I'll make an explanatory diagram like I did for my kinetic sculpture.

As I'm REALLY PANICKED about this aspect I've decided to concentrate on getting the code to work for the 6 sensors for now.

JULY 13

As I mentioned, I want to concentrate on the code. So I spent several hours on the subject today. First, I went back to my codes from yesterday (see above), when I'd managed to code for 2 sensors that a coin was detected. So I did the same thing, but with 5 sensors this time.

It worked very well. The problem was that I realized that the circuit took up a lot of space. I'll see about that later.

Image
  
const int sensor1Pin = A4; // Sensor 1, A4 pin
const int sensor2Pin = A2; // Sensor 2, A2 pin
const int sensor3Pin = A0; // Sensor 3, A0 pin
const int sensor4Pin = A3; // Sensor 4, A3 pin
const int sensor5Pin = A5; // Sensor 5, A5 pin

void setup() {
  pinMode(sensor1Pin, INPUT); // Configure sensor1Pin as input
  pinMode(sensor2Pin, INPUT); // Configure sensor2Pin as input
  pinMode(sensor3Pin, INPUT); // Configure sensor3Pin as input
  pinMode(sensor4Pin, INPUT); // Configure sensor4Pin as input
  pinMode(sensor5Pin, INPUT); // Configure sensor5Pin as input
  
  Serial.begin(9600); // Initialize serial communication at 9600 baud
}

void loop() {
  if (digitalRead(sensor1Pin) == HIGH) {
    Serial.println("Coin detected: Sensor 1");
    delay(500); // Wait for 500 milliseconds to avoid bouncing
  }

  if (digitalRead(sensor2Pin) == HIGH) {
    Serial.println("Coin detected: Sensor 2");
    delay(500); // Wait for 500 milliseconds to avoid bouncing
  }

  if (digitalRead(sensor3Pin) == HIGH) {
    Serial.println("Coin detected: Sensor 3");
    delay(500); // Wait for 500 milliseconds to avoid bouncing
  }

  if (digitalRead(sensor4Pin) == HIGH) {
    Serial.println("Coin detected: Sensor 4");
    delay(500); // Wait for 500 milliseconds to avoid bouncing
  }

  if (digitalRead(sensor5Pin) == HIGH) {
    Serial.println("Coin detected: Sensor 5");
    delay(500); // Wait for 500 milliseconds to avoid bouncing
  }
}

    
  

I then moved on to counting. I started by associating one coin with one sensor. I did this in the order of my ramp:

I created a total that would print everytime a sensor is "on".I first tested for one sensor, then 2, then all 5. I'm not going to put the 3 codes each time since it's the same thing.

Here's the code for 2 sensors.

  
const int sensor1Pin = A4;    // Digital pin for sensor 1
const int sensor2Pin = A2;    // Digital pin for sensor 2
int cents = 0;               // Variable to count cents

void setup() {
  Serial.begin(9600);        // Initialize serial communication at 9600 baud

  pinMode(sensor1Pin, INPUT);// Configure sensor 1 pin as input
  pinMode(sensor2Pin, INPUT);// Configure sensor 2 pin as input
}

void loop() {
  int sensor1Value = digitalRead(sensor1Pin);  // Read the state of sensor 1
  int sensor2Value = digitalRead(sensor2Pin);  // Read the state of sensor 2

  if (sensor1Value == HIGH) {
    Serial.println("Coin detected 1");
    cents += 10;             // Add 10 cents for each sensor 1 detection
    Serial.print("Total: ");
    Serial.print(cents);
    Serial.println(" cents");
    delay(500);              // Wait for 500 milliseconds to debounce
  }

  if (sensor2Value == HIGH) {
    Serial.println("Coin detected 2");
    cents += 1;              // Add 1 cent for each sensor 2 detection
    Serial.print("Total: ");
    Serial.print(cents);
    Serial.println(" cents");
    delay(500);              // Wait for 500 milliseconds to debounce
  }
}

    
  

For the rest of the code, I just modified the if loops according to the sensor.At this stage, I hadn't yet coded the conversion to dollars once you pass 100 cents. For the if loop on the 1 dollar sensor I just put + 100 cents on each activation. So my total was only in cents.

Then, I wanted to add local totals for each sensor and have my conversion in dollars. That is, if I press sensor 3 for the 3rd time and I already have 1 dollar in my piggy bank, I see in the serial monitor:

I've also added the number of x cents coins inserted next to the local total.

Here is the code.

Important code

  
const int sensor1Pin = A4; // Sensor 1, A4 pin
const int sensor2Pin = A2; // Sensor 2, A2 pin
const int sensor3Pin = A0; // Sensor 3, A0 pin
const int sensor4Pin = A3; // Sensor 4, A3 pin
const int sensor5Pin = A5; // Sensor 5, A5 pin

int total1 = 0; // Total for Sensor 1 (10 cents)
int total2 = 0; // Total for Sensor 2 (1 cent)
int total3 = 0; // Total for Sensor 3 (5 cents)
int total4 = 0; // Total for Sensor 4 (25 cents)
int total5 = 0; // Total for Sensor 5 (1 dollar)
int totalGlobal = 0; // Overall total

void setup()
{
  Serial.begin(9600); // Initialize serial communication at 9600 baud

  pinMode(sensor1Pin, INPUT);
  pinMode(sensor2Pin, INPUT);
  pinMode(sensor3Pin, INPUT);
  pinMode(sensor4Pin, INPUT);
  pinMode(sensor5Pin, INPUT);
}

void loop()
{
  if (digitalRead(sensor1Pin) == HIGH)
  {
    total1 += 10;
    totalGlobal += 10;
    Serial.print("Total 1: ");
    printAmount(total1);
    Serial.print(" (");
    Serial.print(total1 / 10);
    Serial.println(" coins)");
    Serial.print("Global total: ");
    printAmount(totalGlobal);
    Serial.println();
    delay(500); 
  }

  if (digitalRead(sensor2Pin) == HIGH)
  {
    total2 += 1;
    totalGlobal += 1;
    Serial.print("Total 2: ");
    Serial.print(total2);
    Serial.print(" cents (");
    Serial.print(total2);
    Serial.println(" coins)");
    Serial.print("Global total: ");
    printAmount(totalGlobal);
    Serial.println();
    delay(500); 
  }

  if (digitalRead(sensor3Pin) == HIGH)
  {
    total3 += 5;
    totalGlobal += 5;
    Serial.print("Total 3: ");
    Serial.print(total3);
    Serial.print(" cents (");
    Serial.print(total3 / 5);
    Serial.println(" coins)");
    Serial.print("Global total: ");
    printAmount(totalGlobal);
    Serial.println();
    delay(500); 
  }

  if (digitalRead(sensor4Pin) == HIGH)
  {
    total4 += 25;
    totalGlobal += 25;
    Serial.print("Total 4: ");
    printAmount(total4);
    Serial.print(" (");
    Serial.print(total4 / 25);
    Serial.println(" coins)");
    Serial.print("Global total: ");
    printAmount(totalGlobal);
    Serial.println();
    delay(500); 
  }

  if (digitalRead(sensor5Pin) == HIGH)
  {
    total5 += 100;
    totalGlobal += 100;
    Serial.print("Total 5: ");
    printAmount(total5);
    Serial.print(" (");
    Serial.print(total5 / 100);
    Serial.println(" coins)");
    Serial.print("Global total: ");
    printAmount(totalGlobal);
    Serial.println();
    delay(500); 
  }
}

void printAmount(int amount)
{
  if (amount >= 100)
  {
    int dollars = amount / 100;
    int cents = amount % 100;
    if (dollars > 0)
    {
      Serial.print(dollars);
      Serial.print(" dollar");
      if (dollars > 1)
      {
        Serial.print("s");
      }
      if (cents > 0)
      {
        Serial.print(" and ");
      }
    }
    if (cents > 0)
    {
      Serial.print(cents);
      Serial.print(" cent");
      if (cents > 1)
      {
        Serial.print("s");
      }
    }
  }
  else
  {
    Serial.print(amount);
    Serial.print(" cent");
    if (amount != 1)
    {
      Serial.print("s");
    }
  }
}
    
  

I'm very happy with this code, now the next step is to succeed in using an output. I'll probably use an LCD screen.

JULY 13 part 2: LED discovery

Yesterday, in class, we learnt about output devices. During the lab, I tried to use OLED screens and then moved on to LCD screens. I wanted my piggy bank totals to be displayed on this screen.

I began by using the LCD on its own. Here's the wiring I followed:

Image

I then tried to print things on the LED screen. In particular, I tried printing 1c, 5c, 10c, 25c, $1 and a sigma on the first line, and zeros underneath on the second line. I wanted to see if everything I wanted to display would fit. The answer was no. A 16x2 LCD screen is too small.

  
#include "LiquidCrystal.h"

// initialize the library with the numbers of the interface pins

LiquidCrystal LCD(12, 11, 5, 4, 3, 2); /// REGISTER SELECT PIN,ENABLE PIN,D4 PIN,D5 PIN, D6 PIN, D7 PIN


void setup() {
   LCD.begin(16, 2); 

   LCD.setCursor(1, 0);
   LCD.print("HELLO");
  
   LCD.setCursor(8, 1);
   LCD.print("WORLD");
}
 
void loop() {

}
    
  
Image
  
#include "LiquidCrystal.h"

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{
  lcd.begin(16, 2);
    lcd.setCursor(0, 0); // Set the cursor to the top-left position

  // Display labels on the first line with appropriate spacing
  lcd.print("1c 5c 10c 25c 1$ Sigma");
  lcd.setCursor(1, 1); // Set the cursor to the bottom-left position

  // Display a zero aligned below each label, except for the numbers
  lcd.print("0  0   0   0  0   0");

  delay(1000); // 1-second delay

  lcd.clear(); // Clear the LCD screen
}

void loop() {

}

    
  
Image

Finally, I decided that for the time being I would only print the total amount.

JULY 14

After experimenting with the LCD screen yesterday, I wanted to try and get it to return the result of the Piezo discs counting code I made yesterday. I can only get it to return the global total at the moment, as there isn't enough space on the LCD screen otherwise.

Here is the circuit and the code.

Image

Important code

  
#include "LiquidCrystal.h"

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // LCD Screen

const int sensor1Pin = A0; // Sensor 1, A0 pin
const int sensor2Pin = A1; // Sensor 2, A1 pin
const int sensor3Pin = A2; // Sensor 3, A2 pin
const int sensor4Pin = A3; // Sensor 4, A3 pin
const int sensor5Pin = 9; // Sensor 5, 9 pin

int total1 = 0; // Total for Sensor 1 (10 cents)
int total2 = 0; // Total for Sensor 2 (1 cent)
int total3 = 0; // Total for Sensor 3 (5 cents)
int total4 = 0; // Total for Sensor 4 (25 cents)
int total5 = 0; // Total for Sensor 5 (1 dollar)
float totalGlobal = 0.0; // Overall total


void setup() {
  pinMode(sensor1Pin, INPUT); // Set sensor1Pin as input
  pinMode(sensor2Pin, INPUT); // Set sensor2Pin as input
  pinMode(sensor3Pin, INPUT); // Set sensor3Pin as input
  pinMode(sensor4Pin, INPUT); // Set sensor4Pin as input
  pinMode(sensor5Pin, INPUT); // Set sensor5Pin as input
  lcd.begin(16, 2);
  Serial.begin(9600); // Initialize serial communication at 9600 baud
}

void loop() {
  // Check if Sensor 1 is triggered
  if (digitalRead(sensor1Pin) == HIGH) {
    total1 += 10; // Increment total for Sensor 1 by 10 cents
    totalGlobal += 0.10; // Increment overall total by 10 cents
    Serial.print("Total 1: $");
    Serial.print(total1 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total1 / 10);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }

  // Check if Sensor 2 is triggered
  if (digitalRead(sensor2Pin) == HIGH) {
    total2 += 1; // Increment total for Sensor 2 by 1 cent
    totalGlobal += 0.01; // Increment overall total by 1 cent
    Serial.print("Total 2: $");
    Serial.print(total2 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total2);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }

  // Check if Sensor 3 is triggered
  if (digitalRead(sensor3Pin) == HIGH) {
    total3 += 5; // Increment total for Sensor 3 by 5 cents
    totalGlobal += 0.05; // Increment overall total by 5 cents
    Serial.print("Total 3: $");
    Serial.print(total3 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total3 / 5);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }

  // Check if Sensor 4 is triggered
  if (digitalRead(sensor4Pin) == HIGH) {
    total4 += 25; // Increment total for Sensor 4 by 25 cents
    totalGlobal += 0.25; // Increment overall total by 25 cents
    Serial.print("Total 4: $");
    Serial.print(total4 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total4 / 25);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }

  // Check if Sensor 5 is triggered
  if (digitalRead(sensor5Pin) == HIGH) {
    total5 += 100; // Increment total for Sensor 5 by 1 dollar
    totalGlobal += 1.0; // Increment overall total by 1 dollar
    Serial.print("Total 5: $");
    Serial.print(total5 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total5 / 100);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }
}

void updateLCD() {
  lcd.clear(); // Clear the LCD screen
  lcd.setCursor(5, 0); // Set the cursor position to column 5, row 0
  lcd.print("Total:");

  lcd.setCursor(4, 1); // Set the cursor position to column 4, row 1
  lcd.print("$");
  lcd.print(totalGlobal, 2); // Display the global total with 2 decimal places
}


    
  

JULY 15

Part1:Coding

Yesterday, I realised that it was possible to use I2C LCD screens which are much more easier to connect. This is the circuit. Image

First, I did what I did before to understand how an I2C LCD worked. I had to download the library and look at the different commands.To adjust contrast, you just need to use the potentiometer on the I2C with a screwdriver. A normal LCD and I2C screen don't initialize the same way for example.

I tried this code.

  
#include "Wire.h"
#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C LCD(0x27,16,2);

void setup() {
   LCD.init(); 
   LCD.backlight();
   
   LCD.setCursor(1, 0);
   LCD.print("HELLO");
  
   LCD.setCursor(8, 1);
   LCD.print("WORLD");
}

void loop() {
   LCD.noDisplay();
   delay(1000);
   LCD.display();
   delay(1000);
}
    
  

I've changed my previous code where the total was displayed on a normal LCD to display it on my new I2C LCD.

Important code

  
#include "Wire.h"
#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd(0x27, 16, 2); // Initialize the I2C LCD display with address 0x27, 16 columns, and 2 rows

const int sensor1Pin = A0; // Sensor 1, A0 pin
const int sensor2Pin = A1; // Sensor 2, A1 pin
const int sensor3Pin = A2; // Sensor 3, A2 pin
const int sensor4Pin = A3; // Sensor 4, A3 pin
const int sensor5Pin = 9; // Sensor 5, 9 pin

int total1 = 0; // Total for Sensor 1 (10 cents)
int total2 = 0; // Total for Sensor 2 (1 cent)
int total3 = 0; // Total for Sensor 3 (5 cents)
int total4 = 0; // Total for Sensor 4 (25 cents)
int total5 = 0; // Total for Sensor 5 (1 dollar)
float totalGlobal = 0.0; // Overall total

void setup() {
  pinMode(sensor1Pin, INPUT); // Set sensor1Pin as input
  pinMode(sensor2Pin, INPUT); // Set sensor2Pin as input
  pinMode(sensor3Pin, INPUT); // Set sensor3Pin as input
  pinMode(sensor4Pin, INPUT); // Set sensor4Pin as input
  pinMode(sensor5Pin, INPUT); // Set sensor5Pin as input

  lcd.init(); // Initialize the I2C LCD screen
  lcd.backlight(); // Turn on the I2C LCD backlight
  Serial.begin(9600); // Initialize serial communication at 9600 baud
}

void loop() {
  // Check if Sensor 1 is triggered
  if (digitalRead(sensor1Pin) == HIGH) {
    total1 += 10; // Increment total for Sensor 1 by 10 cents
    totalGlobal += 0.10; // Increment overall total by 10 cents
    Serial.print("Total 1: $");
    Serial.print(total1 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total1 / 10);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }

  // Check if Sensor 2 is triggered
  if (digitalRead(sensor2Pin) == HIGH) {
    total2 += 1; // Increment total for Sensor 2 by 1 cent
    totalGlobal += 0.01; // Increment overall total by 1 cent
    Serial.print("Total 2: $");
    Serial.print(total2 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total2);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }

  // Check if Sensor 3 is triggered
  if (digitalRead(sensor3Pin) == HIGH) {
    total3 += 5; // Increment total for Sensor 3 by 5 cents
    totalGlobal += 0.05; // Increment overall total by 5 cents
    Serial.print("Total 3: $");
    Serial.print(total3 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total3 / 5);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }

  // Check if Sensor 4 is triggered
  if (digitalRead(sensor4Pin) == HIGH) {
    total4 += 25; // Increment total for Sensor 4 by 25 cents
    totalGlobal += 0.25; // Increment overall total by 25 cents
    Serial.print("Total 4: $");
    Serial.print(total4 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total4 / 25);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }

  // Check if Sensor 5 is triggered
  if (digitalRead(sensor5Pin) == HIGH) {
    total5 += 100; // Increment total for Sensor 5 by 1 dollar
    totalGlobal += 1.0; // Increment overall total by 1 dollar
    Serial.print("Total 5: $");
    Serial.print(total5 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total5 / 100);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    updateLCD(); // Update the LCD display
    delay(500); // Wait for 500 milliseconds to debounce
  }
}

void updateLCD() {
  lcd.clear(); // Clear the LCD screen
  lcd.setCursor(5, 0); // Set the cursor position to column 5, row 0
  lcd.print("Total:");

  lcd.setCursor(4, 1); // Set the cursor position to column 4, row 1
  lcd.print("$");
  lcd.print(totalGlobal, 2); // Display the global total with 2 decimal places
}
    
  

I also I learnt that I could use multiple I2C LCDs at the same time which will be useful to display all the informations. In order to use multiple I2C LCD, it is necessary to change the I2C adress. Image

To check the address of an I2C, there's a function available in the Arduino examples. Before I changed my addresses, the 3 I2Cs had the address 0x27.

Kassia helped me with this task. (Thank you Kassia)

Image

Thanks to the I2C scanner function, I've obtained my new addresses: 0x26 (A0 bridged) and 0x23(A2 bridged).

Now it is possible to use all 3 at the same time.

Image

I checked if it worked with this code.

  
#include "Wire.h"
#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd1(0x27, 16, 2);  // LCD I2C display
LiquidCrystal_I2C lcd2(0x26, 16, 2);  // Second I2C LCD display
LiquidCrystal_I2C lcd3(0x23, 16, 2);  // Third I2C LCD display

void setup() {
  lcd1.init();
  lcd1.clear();         
  lcd1.backlight();      // Make sure the backlight is turned on
  
  lcd2.init();
  lcd2.clear();
  lcd2.backlight();
  
  lcd3.init();
  lcd3.clear();
  lcd3.backlight();

  lcd1.setCursor(2, 0);  // Move the cursor to position 2 of line 0 on the LCD I2C display
  lcd1.print("Hello World!");

  lcd2.setCursor(2, 0);  // Move the cursor to position 2 of line 0 on the I2C LCD display
  lcd2.print("Bonjour!");

  lcd3.setCursor(2, 0);  // Move the cursor to position 2 of line 0 on the I2C LCD display
  lcd3.print("Goodnight");
}

void loop() {
  // The program does nothing in the loop
}

    
  
Image

Part 2: Building

I printed my first toboggan prototype with the 3D printer after making it with a laser cutter and tested it to see if it worked.

Image

I tested with the code that displays the total on the LCD screen. It works very well.(Video below) However, I noted that I could make a few modifications to the slide, which I did in fusion 360. I then ran a 3D print again.

Image

I'll continue this " building " part next week.

JULY 16

Today, I continued to work on my code. I modified the function that displayed my total on an LCD screen to display it on my 3 screens. I had to modify my LCD update function and also change my set-ups.

  
#include "Wire.h"
#include "LiquidCrystal_I2C.h"

// Initialize three LCD displays with their respective addresses, 16 columns, and 2 rows
LiquidCrystal_I2C lcd1(0x27, 16, 2);
LiquidCrystal_I2C lcd2(0x26, 16, 2);
LiquidCrystal_I2C lcd3(0x23, 16, 2);

// Define analog input pins for five sensors and variables to hold their total counts
const int sensor1Pin = A0;
const int sensor2Pin = A1;
const int sensor3Pin = A2;
const int sensor4Pin = A3;
const int sensor5Pin = 9;

int total1 = 0;
int total2 = 0;
int total3 = 0;
int total4 = 0;
int total5 = 0;
float totalGlobal = 0.0; // Variable to hold the overall total

void setup() {
  // Set the sensor pins as inputs
  pinMode(sensor1Pin, INPUT);
  pinMode(sensor2Pin, INPUT);
  pinMode(sensor3Pin, INPUT);
  pinMode(sensor4Pin, INPUT);
  pinMode(sensor5Pin, INPUT);

  // Initialize and enable backlight for all three LCD displays
  lcd1.init();
  lcd1.backlight();
  lcd2.init();
  lcd2.backlight();
  lcd3.init();
  lcd3.backlight();

  // Start serial communication for debugging (baud rate: 9600)
  Serial.begin(9600);
}

void loop() {
  // Check if sensor1 is triggered
  if (digitalRead(sensor1Pin) == HIGH) {
    total1 += 10; // Increment total count for sensor1 by 10
    totalGlobal += 0.10; // Increment overall total by 0.10
    // Print sensor1's total count and overall total to the Serial Monitor
    Serial.print("Total 1: $");
    Serial.print(total1 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total1 / 10);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    // Update all three LCD displays with the latest values
    updateLCD();
    delay(500); // Delay to avoid rapid multiple counts for the same event
  }

  // Check if sensor2 is triggered
  if (digitalRead(sensor2Pin) == HIGH) {
    total2 += 1; // Increment total count for sensor2 by 1
    totalGlobal += 0.01; // Increment overall total by 0.01
    // Print sensor2's total count and overall total to the Serial Monitor
    Serial.print("Total 2: $");
    Serial.print(total2 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total2);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    // Update all three LCD displays with the latest values
    updateLCD();
    delay(500); // Delay to avoid rapid multiple counts for the same event
  }

  // Check if sensor3 is triggered
  if (digitalRead(sensor3Pin) == HIGH) {
    total3 += 5; // Increment total count for sensor3 by 5
    totalGlobal += 0.05; // Increment overall total by 0.05
    // Print sensor3's total count and overall total to the Serial Monitor
    Serial.print("Total 3: $");
    Serial.print(total3 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total3 / 5);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    // Update all three LCD displays with the latest values
    updateLCD();
    delay(500); // Delay to avoid rapid multiple counts for the same event
  }

  // Check if sensor4 is triggered
  if (digitalRead(sensor4Pin) == HIGH) {
    total4 += 25; // Increment total count for sensor4 by 25
    totalGlobal += 0.25; // Increment overall total by 0.25
    // Print sensor4's total count and overall total to the Serial Monitor
    Serial.print("Total 4: $");
    Serial.print(total4 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total4 / 25);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    // Update all three LCD displays with the latest values
    updateLCD();
    delay(500); // Delay to avoid rapid multiple counts for the same event
  }

  // Check if sensor5 is triggered
  if (digitalRead(sensor5Pin) == HIGH) {
    total5 += 100; // Increment total count for sensor5 by 100
    totalGlobal += 1.0; // Increment overall total by 1.0
    // Print sensor5's total count and overall total to the Serial Monitor
    Serial.print("Total 5: $");
    Serial.print(total5 / 100.0, 2);
    Serial.print(" (");
    Serial.print(total5 / 100);
    Serial.println(" coins)");
    Serial.print("Overall Total: $");
    Serial.println(totalGlobal, 2);
    // Update all three LCD displays with the latest values
    updateLCD();
    delay(500); // Delay to avoid rapid multiple counts for the same event
  }
}

// Function to update the content on all three LCD displays
void updateLCD() {
  lcd1.clear();
  lcd1.setCursor(5, 0);
  lcd1.print("Total:");

  lcd1.setCursor(4, 1); // Set the cursor position to column 4, row 1
  lcd1.print("$");
  lcd1.print(totalGlobal, 2); // Display the global total with 2 decimal places

  lcd2.clear();
  lcd2.setCursor(5, 0);
  lcd2.print("Total:");

 lcd2.setCursor(4, 1); // Set the cursor position to column 4, row 1
lcd2.print("$");
lcd2.print(totalGlobal, 2); // Display the global total with 2 decimal places

  lcd3.clear();
  lcd3.setCursor(5, 0);
  lcd3.print("Total:");

 lcd3.setCursor(4, 1); // Set the cursor position to column 4, row 1
  lcd3.print("$");
  lcd3.print(totalGlobal, 2); // Display the global total with 2 decimal places
}


    
  

Now, I will explain the vision that I have for my 3 LCDs. I want to display the same thing as my serial monitor. I.e. the total in dollars of 1 cent coins, 5 cent coins etc. as well as the number of coins that have been put in. Of course, I also want the total of all coins. Given that I want a lot of information displayed and that I have a limited number of slots, I need to use 3 LCD screens.

On each screen there will be 2 groups of information.

On the first screen there will be information related to 1 cent and 5 cents coins.

On the second screen, there will be information related to 10 cents and 25 cents coins.

Finally, on the last screen, there will be information related to 1-dollar coins and the total amount.

I want it to be displayed this way. On the first line, I want it to say 1c,5c etc., with the number of coins in the piggy bank in brackets next to it. On the second line, I want the corresponding dollar total.

For example, if 3 coins of 5 cents have fallen into the piggy bank, it must be marked on screen number 2 on the first line 5c(3) and on the second $0.15.

I hope it's clear, but in any case the pictures will speak for themselves.

Now, for the code, I first tested it on 2 screens: on the first, the information for the 1-cent and 5-cent coins, and on the second, the overall total.

Once that was done, I moved on to my final vision.

IMPORTANT CODE

  
#include "Wire.h"
#include "LiquidCrystal_I2C.h"

LiquidCrystal_I2C lcd1(0x27, 16, 2);  // First I2C LCD screen
LiquidCrystal_I2C lcd2(0x26, 16, 2);  // Second I2C LCD screen
LiquidCrystal_I2C lcd3(0x23, 16, 2);  // Third I2C LCD screen

const int sensor1Pin = A0; // Sensor 1, connected to A0 pin
const int sensor2Pin = A1; // Sensor 2, connected to A1 pin
const int sensor3Pin = A2; // Sensor 3, connected to A2 pin
const int sensor4Pin = A3; // Sensor 4, connected to A3 pin
const int sensor5Pin = 9;  // Sensor 5, connected to digital pin 9

int total1 = 0; // Total for sensor 1 (10 cents)
int total2 = 0; // Total for sensor 2 (1 cent)
int total3 = 0; // Total for sensor 3 (5 cents)
int total4 = 0; // Total for sensor 4 (25 cents)
int total5 = 0; // Total for sensor 5 (1 dollar)
float totalGlobal = 0.0; // Overall total

void setup() {
  pinMode(sensor1Pin, INPUT); // Set sensor1Pin as input
  pinMode(sensor2Pin, INPUT); // Set sensor2Pin as input
  pinMode(sensor3Pin, INPUT); // Set sensor3Pin as input
  pinMode(sensor4Pin, INPUT); // Set sensor4Pin as input
  pinMode(sensor5Pin, INPUT); // Set sensor5Pin as input

  lcd1.init(); // Initialize the first I2C LCD screen
  lcd1.backlight(); // Turn on the backlight of the first I2C LCD screen
  lcd2.init(); // Initialize the second I2C LCD screen
  lcd2.backlight(); // Turn on the backlight of the second I2C LCD screen
  lcd3.init(); // Initialize the third I2C LCD screen
  lcd3.backlight(); // Turn on the backlight of the third I2C LCD screen

  Serial.begin(9600); // Initialize serial communication at 9600 baud rate
}

void loop() {
  // Check if sensor 1 is triggered (10 cents)
  if (digitalRead(sensor1Pin) == HIGH) {
    total1++; // Increment the number of 10-cent coins
    totalGlobal += 0.10; // Add 0.10 to the overall total
    Serial.print("Total 1: $");
    Serial.print(total1 / 10.0, 2); // Print total amount in dollars (with 2 decimal places)
    Serial.print(" (");
    Serial.print(total1);
    Serial.print(" coins)");
    Serial.println();
    Serial.print("Overall Total: $");
    Serial.print(totalGlobal, 2); // Print overall total in dollars (with 2 decimal places)
    Serial.println();
    updateLCD(); // Update the LCD displays with new values
    delay(500); 
  }

  // Check if sensor 2 is triggered (1 cent)
  if (digitalRead(sensor2Pin) == HIGH) {
    total2++; // Increment the number of 1-cent coins
    totalGlobal += 0.01; // Add 0.01 to the overall total
    Serial.print("Total 2: $");
    Serial.print(total2 / 100.0, 2); // Print total amount in dollars (with 2 decimal places)
    Serial.print(" (");
    Serial.print(total2);
    Serial.print(" coins)");
    Serial.println();
    Serial.print("Overall Total: $");
    Serial.print(totalGlobal, 2); // Print overall total in dollars (with 2 decimal places)
    Serial.println();
    updateLCD(); // Update the LCD displays with new values
    delay(500); 
  }

  // Check if sensor 3 is triggered (5 cents)
  if (digitalRead(sensor3Pin) == HIGH) {
    total3++; // Increment the number of 5-cent coins
    totalGlobal += 0.05; // Add 0.05 to the overall total
    Serial.print("Total 3: $");
    Serial.print(total3 / 100.0, 2); // Print total amount in dollars (with 2 decimal places)
    Serial.print(" (");
    Serial.print(total3);
    Serial.print(" coins)");
    Serial.println();
    Serial.print("Overall Total: $");
    Serial.print(totalGlobal, 2); // Print overall total in dollars (with 2 decimal places)
    Serial.println();
    updateLCD(); // Update the LCD displays with new values
    delay(500); 
  }

  // Check if sensor 4 is triggered (25 cents)
  if (digitalRead(sensor4Pin) == HIGH) {
    total4++; // Increment the number of 25-cent coins
    totalGlobal += 0.25; // Add 0.25 to the overall total
    Serial.print("Total 4: $");
    Serial.print(total4 / 100.0, 2); // Print total amount in dollars (with 2 decimal places)
    Serial.print(" (");
    Serial.print(total4);
    Serial.print(" coins)");
    Serial.println();
    Serial.print("Overall Total: $");
    Serial.print(totalGlobal, 2); // Print overall total in dollars (with 2 decimal places)
    Serial.println();
    updateLCD(); // Update the LCD displays with new values
    delay(500); 
  }

  // Check if sensor 5 is triggered (1 dollar)
  if (digitalRead(sensor5Pin) == HIGH) {
    total5++; // Increment the number of 1-dollar coins
    totalGlobal += 1.0; // Add 1.0 to the overall total
    Serial.print("Total 5: $");
    Serial.print(total5); // Print total amount in dollars (integer value for 1-dollar coins)
    Serial.print(" (");
    Serial.print(total5);
    Serial.print(" coins)");
    Serial.println();
    Serial.print("Overall Total: $");
    Serial.print(totalGlobal, 2); // Print overall total in dollars (with 2 decimal places)
    Serial.println();
    updateLCD(); // Update the LCD displays with new values
    delay(500); 
  }
}


void updateLCD() {
  lcd1.clear(); // Clear the first I2C LCD screen
  lcd1.setCursor(0, 0); // Set the cursor to column 0, row 0
  lcd1.print("1c(");
  lcd1.print(total2);
  lcd1.print(")  5c(");
  lcd1.print(total3);
  lcd1.print(")");

  lcd1.setCursor(0, 1); // Set the cursor to column 0, row 1
  lcd1.print("$");
  lcd1.print(total2 * 0.01, 2);
  lcd1.print("  $");
  lcd1.print(total3 * 0.05, 2);
  
  lcd2.clear(); // Clear the second I2C LCD screen
  lcd2.setCursor(0, 0); // Set the cursor to column 0, row 0
  lcd2.print("10c(");
  lcd2.print(total1);
  lcd2.print(") 25c(");
  lcd2.print(total4);
  lcd2.print(")");

  lcd2.setCursor(0, 1); // Set the cursor to column 0, row 1
  lcd2.print("$");
  lcd2.print(total1 * 0.10, 2);
  lcd2.print("  $");
  lcd2.print(total4 * 0.25, 2);
  
  lcd3.clear(); // Clear the third I2C LCD screen
  lcd3.setCursor(0, 0); // Set the cursor to column 0, row 0
  lcd3.print("$1(");
  lcd3.print(total5);
  lcd3.print(")  Total");

  lcd3.setCursor(0, 1); // Set the cursor to column 0, row 1
  lcd3.print("$");
  lcd3.print(total5 * 1.0, 2);
  lcd3.print("  $");
  lcd3.print(totalGlobal, 2);
}

    
  

JULY 17 & 18

Part 1: Coding

I am very happy with all the programming I did but now I have to do OOP.

I could have coded directly with classes and no delay but this is really something I hate. I learnt Java in my engineering school and I hated it, I am much more comfortable with Python. I guess I wanted to save the worst part for the end.:))

For my week 7 assigment, I had to work on making a clean code. I didn't work on my final code but on the one that allowed me to display the total amount in the piggy bank on one LCD screen.

Here is the new code.

  
#include "LiquidCrystal_I2C.h" // Include the library for I2C LCD

LiquidCrystal_I2C lcd(0x27, 16, 2); // Create an instance of the LiquidCrystal_I2C class

enum SensorPin {
  CAPTEUR_1 = A0, // Analog pin A0
  CAPTEUR_2 = A1, // Analog pin A1
  CAPTEUR_3 = A2, // Analog pin A2
  CAPTEUR_4 = A3, // Analog pin A3
  CAPTEUR_5 = 9   // Digital pin 9
};

void updateLCD(); // Function declaration

class CoinCounter {
private:
  SensorPin pin; // Sensor pin
  int value;     // Number of coins detected
  int total;     // Total value in cents
  static float totalGlobal; // Total value globally in dollars

public:
  CoinCounter(SensorPin pin) : pin(pin), value(0), total(0) {} // Constructor

  void init() {
    pinMode(pin, INPUT); // Set the pin mode as INPUT
  }

  void update() {
    static unsigned long lastDebounceTime = 0; // Last debounce time
    unsigned long currentTime = millis();      // Current time
    const unsigned long debounceDelay = 500;    // Debounce delay in milliseconds

    // Check if the pin is HIGH and debounce time has passed
    if (digitalRead(pin) == HIGH && (currentTime - lastDebounceTime) >= debounceDelay) {
      value++; // Increment the number of coins detected
      total += getValueInCents();         // Add the value of the coin in cents to the total
      totalGlobal += getValueInDollars(); // Add the value of the coin in dollars to the global total
      printTotal(); // Print the current and overall totals
      updateLCD();  // Update the LCD display
      lastDebounceTime = currentTime; // Update the last debounce time
    }
  }

  int getValue() const {
    return value; // Return the number of coins detected
  }

  int getTotal() const {
    return total; // Return the total value in cents
  }

  static float getTotalGlobal() {
    return totalGlobal; // Return the global total value in dollars
  }

private:
  int getValueInCents() const {
    // Return the value of the coin in cents based on the sensor pin
    switch (pin) {
      case CAPTEUR_1:
        return 10;
      case CAPTEUR_2:
        return 1;
      case CAPTEUR_3:
        return 5;
      case CAPTEUR_4:
        return 25;
      case CAPTEUR_5:
        return 100;
      default:
        return 0;
    }
  }

  float getValueInDollars() const {
    return getValueInCents() / 100.0; // Return the value of the coin in dollars
  }

  void printTotal() const {
    // Print the current total for the sensor pin and the overall total
    Serial.print("Total ");
    Serial.print(pinToSensorName(pin));
    Serial.print(": $");
    Serial.print(total / 100.0, 2); // Print the total value in dollars with 2 decimal places
    Serial.print(" (");
    Serial.print(value);
    Serial.print(" coins)");
    Serial.println();
    Serial.print("Overall Total: $");
    Serial.print(totalGlobal, 2); // Print the overall total value in dollars with 2 decimal places
    Serial.println();
  }

  String pinToSensorName(SensorPin pin) const {
    // Convert the sensor pin to a corresponding sensor name
    switch (pin) {
      case CAPTEUR_1:
        return "1";
      case CAPTEUR_2:
        return "2";
      case CAPTEUR_3:
        return "3";
      case CAPTEUR_4:
        return "4";
      case CAPTEUR_5:
        return "5";
      default:
        return "";
    }
  }
};

float CoinCounter::totalGlobal = 0.0; // Initialize the static member variable

CoinCounter sensors[] = {
  CoinCounter(CAPTEUR_1), // Create instances of CoinCounter for each sensor pin
  CoinCounter(CAPTEUR_2),
  CoinCounter(CAPTEUR_3),
  CoinCounter(CAPTEUR_4),
  CoinCounter(CAPTEUR_5)
};

void setup() {
  lcd.init();       // Initialize the LCD
  lcd.backlight();  // Turn on the LCD backlight
  Serial.begin(9600); // Initialize the Serial communication
  for (int i = 0; i < 5; i++) {
    sensors[i].init(); // Initialize each CoinCounter instance
  }
}

void loop() {
  for (int i = 0; i < 5; i++) {
    sensors[i].update(); // Update each CoinCounter instance
  }
}

void updateLCD() {
  lcd.clear();            // Clear the LCD display
  lcd.setCursor(5, 0);    // Set the cursor position
  lcd.print("Total:");    // Print "Total:" on the first line

  lcd.setCursor(4, 1);    // Set the cursor position
  lcd.print("$");         // Print "$" on the second line
  lcd.print(CoinCounter::getTotalGlobal(), 2); // Print the overall total value in dollars with 2 decimal places
}

    
  

Next step is to work on making a cleaner final code.. Can't wait!

Part 2: Building

With my final code and my new 3D printed slides, I prototyped my piggy bank.

It worked perfectly so now I need to 3D print the rest of my slides. I am not sure that I will be needing funnels.

JULY 19

I 3D printed all of my slides. There were a few printing defects, but nothing serious.

Image
Download my STL file
Download my gcode file

JULY 20

Today, I printed out the walls that will separate each slide and compartment. I modeled them after the slide sketch.

I also spent a good part of the day working to make the code cleaner with classes. I also had a new idea to add a new sensor to act as a reset button. It resets everything to 0 when you empty the piggy bank.

Important code

  
#include "Wire.h"
#include "LiquidCrystal_I2C.h"

const int sensor1Pin = A0; // Sensor 1, connected to A0 pin (10 cents)
const int sensor2Pin = A1; // Sensor 2, connected to A1 pin (1 cent)
const int sensor3Pin = A2; // Sensor 3, connected to A2 pin (5 cents)
const int sensor4Pin = A3; // Sensor 4, connected to A3 pin (25 cents)
const int sensor5Pin = 9;  // Sensor 5, connected to digital pin 9 (1 dollar)
const int sensor6Pin = 3;  // Sensor 6, connected to digital pin 3 (for reset)

LiquidCrystal_I2C lcd1(0x27, 16, 2);  // First I2C LCD screen (1 cent and 5 cents)
LiquidCrystal_I2C lcd2(0x23, 16, 2);  // Second I2C LCD screen (10 cents and 25 cents)
LiquidCrystal_I2C lcd3(0x26, 16, 2);  // Third I2C LCD screen (1 dollar)

class CoinSensor {
private:
  int pin;
  int coinValue;
  int totalCoins;
  unsigned long lastDebounceTime;
  const unsigned long debounceDelay = 500;

public:
  CoinSensor(int sensorPin, int value) : pin(sensorPin), coinValue(value), totalCoins(0), lastDebounceTime(0) {}

  void init() {
    pinMode(pin, INPUT);
  }

  void update() {
    unsigned long currentTime = millis();
    if (digitalRead(pin) == HIGH && (currentTime - lastDebounceTime) >= debounceDelay) {
      totalCoins++;
      lastDebounceTime = currentTime;
    }
  }

  int getTotalCoins() const {
    return totalCoins;
  }

  int getCoinValue() const {
    return coinValue;
  }

  void resetTotalCoins() {
    totalCoins = 0;
  }
};

CoinSensor sensors[] = {
  CoinSensor(sensor2Pin, 1), // 1 cent
  CoinSensor(sensor3Pin, 5), // 5 cents
  CoinSensor(sensor1Pin, 10), // 10 cents
  CoinSensor(sensor4Pin, 25), // 25 cents
  CoinSensor(sensor5Pin, 100), // 1 dollar
  CoinSensor(sensor6Pin, 0)  // New sensor for reset (initial value 0, it can be updated based on its actual value)
};

// Variables to store previous values for LCD update
int prevSensor1Coins = 0;
int prevSensor2Coins = 0;
int prevSensor3Coins = 0;
int prevSensor4Coins = 0;
int prevSensor5Coins = 0;
int prevSensor6Coins = 0; // New variable for the additional sensor
float prevTotalGlobal = 0.0;

void setup() {
  lcd1.init();
  lcd1.backlight();
  lcd1.clear();
  lcd1.setCursor(0, 0);
  lcd1.print("1c(0) 5c(0)");
  lcd1.setCursor(0, 1);
  lcd1.print("$0.00  $0.00");

  lcd2.init();
  lcd2.backlight();
  lcd2.clear();
  lcd2.setCursor(0, 0);
  lcd2.print("10c(0) 25c(0)");
  lcd2.setCursor(0, 1);
  lcd2.print("$0.00  $0.00");

  lcd3.init();
  lcd3.backlight();
  lcd3.clear();
  lcd3.setCursor(0, 0);
  lcd3.print("$1(0)  Total");
  lcd3.setCursor(0, 1);
  lcd3.print("$0.00  $0.00");

  Serial.begin(9600);
}

void loop() {
  for (int i = 0; i < 5; i++) {
    sensors[i].update();
  }
  sensors[5].update(); // Update the reset sensor

  updateLCD(); // Update the LCD screens
}

void updateLCD() {
  // Check if the content has changed before updating
  if (prevSensor2Coins != sensors[0].getTotalCoins() || prevSensor3Coins != sensors[1].getTotalCoins()) {
    lcd1.clear();
    lcd1.setCursor(0, 0);
    lcd1.print("1c(");
    lcd1.print(sensors[0].getTotalCoins());
    lcd1.print(") 5c(");
    lcd1.print(sensors[1].getTotalCoins());
    lcd1.print(")");

    lcd1.setCursor(0, 1);
    lcd1.print("$");
    lcd1.print(sensors[0].getTotalCoins() * 0.01, 2);
    lcd1.print("  $");
    lcd1.print(sensors[1].getTotalCoins() * 0.05, 2);

    // Update previous values
    prevSensor2Coins = sensors[0].getTotalCoins();
    prevSensor3Coins = sensors[1].getTotalCoins();
  }

  if (prevSensor1Coins != sensors[2].getTotalCoins() || prevSensor4Coins != sensors[3].getTotalCoins()) {
    lcd2.clear();
    lcd2.setCursor(0, 0);
    lcd2.print("10c(");
    lcd2.print(sensors[2].getTotalCoins());
    lcd2.print(") 25c(");
    lcd2.print(sensors[3].getTotalCoins());
    lcd2.print(")");

    lcd2.setCursor(0, 1);
    lcd2.print("$");
    lcd2.print(sensors[2].getTotalCoins() * 0.10, 2);
    lcd2.print("  $");
    lcd2.print(sensors[3].getTotalCoins() * 0.25, 2);

    // Update previous values
    prevSensor1Coins = sensors[2].getTotalCoins();
    prevSensor4Coins = sensors[3].getTotalCoins();
  }

  if (prevSensor5Coins != sensors[4].getTotalCoins() || prevTotalGlobal != getTotalGlobal()) {
    lcd3.clear();
    lcd3.setCursor(0, 0);
    lcd3.print("$1(");
    lcd3.print(sensors[4].getTotalCoins());
    lcd3.print(")  Total");

    lcd3.setCursor(0, 1);
    lcd3.print("$");
    lcd3.print(sensors[4].getTotalCoins() * 1.0, 2);
    lcd3.print("  $");
    lcd3.print(getTotalGlobal(), 2);

    // Update previous values
    prevSensor5Coins = sensors[4].getTotalCoins();
    prevTotalGlobal = getTotalGlobal();
  }

  // Check if the reset sensor (sensor6) is active
  if (sensors[5].getTotalCoins() > 0) {
    // Reset the total global
    prevTotalGlobal = 0;

    // Reset the previous values for all sensors
    prevSensor1Coins = 0;
    prevSensor2Coins = 0;
    prevSensor3Coins = 0;
    prevSensor4Coins = 0;
    prevSensor5Coins = 0;

    // Reset the total coins for all sensors
    for (int i = 0; i < 5; i++) {
      sensors[i].resetTotalCoins();
    }

    // Reset the reset sensor
    sensors[5].resetTotalCoins();

    // Clear and update the LCD screens to display zeros
    lcd1.clear();
    lcd1.setCursor(0, 0);
    lcd1.print("1c(0) 5c(0)");
    lcd1.setCursor(0, 1);
    lcd1.print("$0.00  $0.00");

    lcd2.clear();
    lcd2.setCursor(0, 0);
    lcd2.print("10c(0) 25c(0)");
    lcd2.setCursor(0, 1);
    lcd2.print("$0.00  $0.00");

    lcd3.clear();
    lcd3.setCursor(0, 0);
    lcd3.print("$1(0)  Total");
    lcd3.setCursor(0, 1);
    lcd3.print("$0.00  $0.00");
  }

  // Update the reset sensor debounce
  sensors[5].update();
}

float getTotalGlobal() {
  float total = 0.0;
  total += sensors[0].getTotalCoins() * 0.01;
  total += sensors[1].getTotalCoins() * 0.05;
  total += sensors[2].getTotalCoins() * 0.10;
  total += sensors[3].getTotalCoins() * 0.25;
  total += sensors[4].getTotalCoins() * 1.0;
  return total;
}

void resetTotals() {
  // Reset the total global
  prevTotalGlobal = 0;

  // Reset the previous values for all sensors
  prevSensor1Coins = 0;
  prevSensor2Coins = 0;
  prevSensor3Coins = 0;
  prevSensor4Coins = 0;
  prevSensor5Coins = 0;
  prevSensor6Coins = 0; // Reset the additional sensor too

  // Reset the total coins for all sensors
  for (int i = 0; i < 5; i++) {
    sensors[i].resetTotalCoins();
  }
}



    
  

There's a video below showing everything in action.

JULY 21

Now that I've printed out everything I need and have my circuit with working code, I wanted to move on to assembling the piggy bank.

The first thing I did was screw the walls to my slides.

Image

I then wanted to move on to the box. But first I wanted to check that the circuit would fit under the slides, and I also wanted to see how much space the breadboard and arduino would take up in my piggy bank.

It took me a lot longer than expected because the piezo disks kept breaking and the soldering didn't hold.

After a while, I managed to prototype the inside of my piggy bank.

Image

I then took measurements to find out how big my box should be.

Here's a drawing of my piggy bank with dimensions.

Image

JULY 23

Today, I continued assembling my piggy bank. I started printing the box. I used the Makercase website. Download my piggy bank (DXF file) I also screwed my sorting ramp to the box and started attaching the slides.

JULY 24

I worked on the piggy bank assembly again today. I screwed on all the slides and printed the left side of the box, remembering to add a slot for the coins. I also took the opportunity to retest my code to make sure everything was working properly.

Image Image

JULY 25 & 26

Between yesterday and today, I laser cut the front of my piggy bank with holes for LCD screens. I screwed my "screens" to my piggy bank. I also screwed my arduino board to the inside right-hand side of my piggy bank.

I printed a little pig in 3D.

Download my STL file
Download my gcode file

I also realized that there was a problem with my compartment walls: they don't all touch the floor of the piggy bank, so the coins get mixed up and they don't reach the end of the piggy bank. There's about 1cm between the end of the "walls" and the end of the piggy bank.

To alleviate this problem, I decided to print some sort of clamps with the 3D printer.I took measurements of the thickness, height and length of my "walls" to make my clamp.

Image Image
Download my STL file
Download my gcode file
Image

This photo already gives a good idea of what the piggy bank will look like. The piece of wood I've put at the bottom right of the compartments will actually be where the reset button will be.

JULY 27

I painted my pig pink. In my vision of things, I want to screw it to the lid of the piggy bank and use it as a handle.

Well, I only have a photo of the first layer. The pig was more red than pink.

Image

I also wanted to screw my "clamps" to the piggy bank. Unfortunately, the drill bit was too short, so the drill couldn't get between the compartments to make the holes. Instead, I used wood glue.

Image

JULY 28

Today, I finally finished my project. My piggy bank is set up.

I first checked that the piggy bank worked before gluing the front with the LCD screens. Once I'd glued the front, I laser cut the lid of my piggy bank and screwed my beautiful pig onto it.

Then I switched to my reset button. I took measurements before modeling on Fusion360. I decided that I would engrave an inscription in the wood "Reset by knocking here".

Image

I attached a piezo disc or "reset button" to my part and stuck it on with wood glue.

My piggy bank was finished. There were just a few details left. I tried covering it with pink canson to see what it looked like, but in the end I preferred to keep it in wood.

I added an arrow with an inscription to locate the coin slot, which is almost invisible.

Image Image

To finish, I added a piece of wood to the left of the compartments and glued it in place with wood glue. As you can see from the picture, there was a gap of nothing between the piggy bank wall and the 10-cent compartment.

Image

And Voilà!

Image Image

Now all I have to do is make the demo video.

There will be nicer photos/videos of the finished product on the "Final project: Final product" page.