amamitof7
Published © GPL3+

Convince Them It's Clean

An Arduino, display, and accelerometer are attached to a cleaning bottle. The display shows the number of minutes since it was last used.

IntermediateFull instructions provided5 hours372
Convince Them It's Clean

Things used in this project

Hardware components

LTC-5623G-01
This part is a four-digit seven-segment common-anode LED display. Numbers are in green, but other colors are available. I used LTC-5653G-01 instead because I had it available, but that part is only available in bulk at Digikey. As far as I can tell, the only difference between the parts is that the 5653G has pin seven next to pin six while the 5623G has pin seven next to pin eight. I drew the circuit diagram for the 5653G, but it can easily be altered for the 5623G.
×1
Adafruit Metro Mini
You can use any Arduino, but the Metro Mini is small and easily mounted on a perf board. You will also need a USB cable to program it. The pinout for the Metro Mini and the Uno are the same. If you are using the Uno instead, you will need a different style of USB cable for programming, and you will not need the socket listed below.
×1
Socket, 28 pin
This is 28 DIP socket with 0.6" row spacing, and it fits the Metro Mini Arduino.
×1
Adafruit Accelerometer, Invensense 6050 on a breakout board
The Invensense 6050 is a surface mount chip which contains a three-axis accelerometer, a three-axis gyroscope, and a temperature sensor. It communicates by I2C. In this project, only the accelerometer is used. This part is a breakout board containing the 6050, which makes soldering much easier. I used a different brand breakout board containing the 6050, which I had available, so the layout of the pins in the circuit diagram may be a bit different than for this part.
×1
Perf Board
×1
9V to Barrel Jack
This device can be powered many ways. One option is to usea 9V battery, this connector, and the barrel jack listed below. Another option is to use a 6V wall wart such as Digikey part 237-2321-ND along with the barrel jack listed below. A third option is to connect a USB cable to the Arduino, in which case you do not need either this part, the barrel jack, or the switch.
×1
Barrel Jack
×1
Resistor 560 Ohm
I used 560 Ohm 0.5 Watt resistors, but the constraints on the resistors are not strict. If all you have are 1000 Ohm 0.25 Watt resistors, they will work fine. If you use a resistance slightly higher, the LEDs will be a bit dimmer, and if you use a resistance slightly lower, the LEDs will be a bit brighter.
×7
Switch
This is optional. Alternatively, you can just unplug it to turn it off.
×1
Breadboard (generic)
Breadboard (generic)
This is recommended for testing but not needed for the final product.
×1
Elastic
A small piece of elastic, with width around 1/4", attaches the circuit to the cleaning bottle.
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
You will also need some solder and basic soldering tools like a wire cutter.

Story

Read more

Schematics

Circuit Diagram

Perf Board Layout

Code

ledSevenSeg1.ino

Arduino
An Arduino, display, and accelerometer are attached to a cleaning bottle. The display shows the number of minutes since it was last moved.
/*
 *  Convince Them Its Clean 
 *  
 *  An Arduino, display, and accelerometer are attached to a cleaning bottle.
 *  The display shows the number of minutes since it was last moved.
 *  
 *  For full instructions and the accompanying circuit, see the 
 *  project entitled "Convince Them It's Clean" on hackster.io by amamitof7.
 * 
 * 
 * 
 * 
 *  Copyright (C) 2020 Andrea Mitofsky
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  A copy of the GNU General Public License is available at <https://www.gnu.org/licenses></https:>.
 * 
 * 
 */


#include<Wire.h>

//Define Pin Names
     #define cathodeE_pin 9
     #define cathodeD_pin 8
     #define cathodeC_pin 7
     #define cathodeG_pin 6
     #define anode4_pin 5
     #define cathodeB_pin 4
     #define anode3_pin 2
     #define anode2_pin 3
     #define cathodeF_pin 12
     #define cathodeA_pin 11
     #define anode1_pin 10


//Define Global Variables

//Tol represents the tolerance of the accelerometer. If the numbers reset when they should not, try raising tol. 
//If the numbers do not reset unless the accelerometer moves significantly, try lowering tol.
int tol=800; 

//timeMax represents the minutes until the message "USE ME" is displayed.
int timeMax=480; 

//timeDiff represents the milliseconds needed to increment the display. To inccrement each minute, set this to 60000. 
unsigned long timeDiff=60000;

const int MPU6050_addr=0x68;
unsigned long zeroTime=0;
unsigned long updateTime=0;
unsigned long msgTime=0;
int minSinceUse=0;
int16_t origX, origY, origZ;
int msg=1; //0=use and 1=me


/*The setup function sets up the output pins and accelerometer.*/
void setup() {
     // Set up the IO pins
     pinMode(cathodeA_pin, OUTPUT);
     pinMode(cathodeB_pin, OUTPUT);
     pinMode(cathodeC_pin, OUTPUT);
     pinMode(cathodeD_pin, OUTPUT);
     pinMode(cathodeE_pin, OUTPUT);
     pinMode(cathodeF_pin, OUTPUT);
     pinMode(cathodeG_pin, OUTPUT);
     pinMode(anode1_pin,OUTPUT);
     pinMode(anode2_pin, OUTPUT);
     pinMode(anode3_pin,OUTPUT);
     pinMode(anode4_pin, OUTPUT);

    //Set up the accelerometer
    Wire.begin();
    Wire.beginTransmission(MPU6050_addr);
    Wire.write(0x6B);
    Wire.write(0);
    Wire.endTransmission(true);
 


    //Set up variables for timing and for the accelerometer
    zeroTime=millis(); 
    updateTime=zeroTime;
    minSinceUse=0;
    Wire.beginTransmission(MPU6050_addr);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU6050_addr,14,true);
    origX=Wire.read()<<8|Wire.read();
    origY=Wire.read()<<8|Wire.read();
    origZ=Wire.read()<<8|Wire.read();
    
}


/* The function Loop runs repeatedly.*/
void loop() {
    unsigned long currentTime;

    //Check the accelerometer, and reset time if needed.
     hasItMoved();
   
    //Check the time, and update the display.
    currentTime=millis();
    if((currentTime-updateTime)>timeDiff)
        {
         minSinceUse++;
         updateTime=currentTime;
        }
      
    displayNumber(minSinceUse);
  
 }


/* The function displayNumber accepts an integer, picks off the digits, and calls the displayDigit function 
 *  to display it. If the number is bigger than timeMax, "USE ME" is displayed.
 */
void displayNumber(int inNum)
{
    int dig1, dig2, dig3, dig4;

    if((inNum>timeMax)||(inNum<0))
    {
        useMe();
    }
    else
    {
        //Pick off each digit and display it
        dig4=inNum%10;
        dig3=((inNum-dig4)%100)/10;
        dig2=((inNum-dig3-dig4)%1000)/100;
        dig1=((inNum-dig2-dig3-dig4)%10000)/1000;

        //Display the digits
        displayDigit(dig1);
        digitalWrite(anode1_pin,HIGH);
        digitalWrite(anode2_pin, LOW);
        digitalWrite(anode3_pin, LOW);
        digitalWrite(anode4_pin, LOW);
        delay(5);
 
        displayDigit(dig2);
        digitalWrite(anode1_pin, LOW);
        digitalWrite(anode2_pin, HIGH);
        digitalWrite(anode3_pin, LOW);
        digitalWrite(anode4_pin, LOW);
        delay(5);
        
        displayDigit(dig3);
        digitalWrite(anode1_pin, LOW);
        digitalWrite(anode2_pin, LOW);
        digitalWrite(anode3_pin, HIGH);
        digitalWrite(anode4_pin, LOW);
        delay(5);
      
        displayDigit(dig4);
        digitalWrite(anode1_pin, LOW);
        digitalWrite(anode2_pin, LOW);
        digitalWrite(anode3_pin, LOW);
        digitalWrite(anode4_pin, HIGH);
        delay(5);

    }
}

/* The function hasItMoved checks the accelerometer. If it has moved, the variable minSinceUse is reset and other variables are set.
 * The following site was used as a reference for code for the accelerometer:
 * https://www.electronicshub.org/getting-started-arduino-mpu6050/
 *
*/
int hasItMoved()
{
    int16_t AccX,AccY,AccZ;
 
    //Check the accelerometer
    Wire.beginTransmission(MPU6050_addr);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU6050_addr,14,true);
    AccX=Wire.read()<<8|Wire.read();
    AccY=Wire.read()<<8|Wire.read();
    AccZ=Wire.read()<<8|Wire.read();

    //If the device moved, reset time to zero
    if((abs(AccX-origX)>tol)||(abs(AccY-origY)>tol)||(abs(AccZ-origZ)>tol))
    {
         minSinceUse=0;
         zeroTime=millis();
         updateTime=zeroTime;
    }
  
    return 0;
}

/* The function useMe displays the message "USE ME".*/
void useMe()
{

    unsigned long myTime;
    myTime=millis();
    if(abs(myTime-msgTime)>3000)
       {
        msgTime=myTime;
        //switch the message
        if(msg==0)
           {msg=1;}
        else 
            {msg=0;}
       }
    
    if(msg==0)
    {    
       //Display U
       digitalWrite(cathodeA_pin, HIGH);
       digitalWrite(cathodeB_pin, LOW);
       digitalWrite(cathodeC_pin, LOW);
       digitalWrite(cathodeD_pin, LOW);
       digitalWrite(cathodeE_pin, LOW);
       digitalWrite(cathodeF_pin, LOW);
       digitalWrite(cathodeG_pin, HIGH);
       digitalWrite(anode1_pin, HIGH);
       digitalWrite(anode2_pin, LOW);
       digitalWrite(anode3_pin, LOW);
       digitalWrite(anode4_pin, LOW);
       delay(5);

       //Display S
       digitalWrite(cathodeA_pin, LOW);
       digitalWrite(cathodeB_pin, HIGH);
       digitalWrite(cathodeC_pin, LOW);
       digitalWrite(cathodeD_pin, LOW);
       digitalWrite(cathodeE_pin, HIGH);
       digitalWrite(cathodeF_pin, LOW);
       digitalWrite(cathodeG_pin, LOW);
       digitalWrite(anode1_pin, LOW);
       digitalWrite(anode2_pin, HIGH);
       digitalWrite(anode3_pin, LOW);
       digitalWrite(anode4_pin, LOW);
       delay(5);

       //Display E
       digitalWrite(cathodeA_pin, LOW);
       digitalWrite(cathodeB_pin, HIGH);
       digitalWrite(cathodeC_pin, HIGH);
       digitalWrite(cathodeD_pin, LOW);
       digitalWrite(cathodeE_pin, LOW);
       digitalWrite(cathodeF_pin, LOW);
       digitalWrite(cathodeG_pin, LOW);
       digitalWrite(anode1_pin, LOW);
       digitalWrite(anode2_pin, LOW);
       digitalWrite(anode3_pin, HIGH);
       digitalWrite(anode4_pin, LOW);
       delay(5);

       //Last letter Blank 
       digitalWrite(cathodeA_pin, LOW);
       digitalWrite(cathodeB_pin, LOW);
       digitalWrite(cathodeC_pin, LOW);
       digitalWrite(cathodeD_pin, LOW);
       digitalWrite(cathodeE_pin, LOW);
       digitalWrite(cathodeF_pin, LOW);
       digitalWrite(cathodeG_pin, LOW);
       digitalWrite(anode1_pin, LOW);
       digitalWrite(anode2_pin, LOW);
       digitalWrite(anode3_pin, LOW);
       digitalWrite(anode4_pin, LOW);
       delay(5);
    }

    else
    { 
       //Display Half of M
       digitalWrite(cathodeA_pin, LOW);
       digitalWrite(cathodeB_pin, LOW);
       digitalWrite(cathodeC_pin, HIGH);
       digitalWrite(cathodeD_pin, HIGH);
       digitalWrite(cathodeE_pin, LOW);
       digitalWrite(cathodeF_pin, LOW);
       digitalWrite(cathodeG_pin, HIGH);
       digitalWrite(anode1_pin, HIGH);
       digitalWrite(anode2_pin, LOW);
       digitalWrite(anode3_pin, LOW);
       digitalWrite(anode4_pin, LOW);
       delay(5);

       //Display Half of M
       digitalWrite(cathodeA_pin, LOW);
       digitalWrite(cathodeB_pin, LOW);
       digitalWrite(cathodeC_pin, LOW);
       digitalWrite(cathodeD_pin, HIGH);
       digitalWrite(cathodeE_pin, HIGH);
       digitalWrite(cathodeF_pin, LOW);
       digitalWrite(cathodeG_pin, HIGH);
       digitalWrite(anode1_pin, LOW);
       digitalWrite(anode2_pin, HIGH);
       digitalWrite(anode3_pin, LOW);
       digitalWrite(anode4_pin, LOW);
       delay(5);
  
       //Display E
       digitalWrite(cathodeA_pin, LOW);
       digitalWrite(cathodeB_pin, HIGH);
       digitalWrite(cathodeC_pin, HIGH);
       digitalWrite(cathodeD_pin, LOW);
       digitalWrite(cathodeE_pin, LOW);
       digitalWrite(cathodeF_pin, LOW);
       digitalWrite(cathodeG_pin, LOW);
       digitalWrite(anode1_pin, LOW);
       digitalWrite(anode2_pin, LOW);
       digitalWrite(anode3_pin, HIGH);
       digitalWrite(anode4_pin, LOW);
       delay(5);

       //Last letter Blank
       digitalWrite(cathodeA_pin, LOW);
       digitalWrite(cathodeB_pin, LOW);
       digitalWrite(cathodeC_pin, LOW);
       digitalWrite(cathodeD_pin, LOW);
       digitalWrite(cathodeE_pin, LOW);
       digitalWrite(cathodeF_pin, LOW);
       digitalWrite(cathodeG_pin, LOW);
       digitalWrite(anode1_pin, LOW);
       digitalWrite(anode2_pin, LOW);
       digitalWrite(anode3_pin, LOW);
       digitalWrite(anode4_pin, LOW);
    }
    
}



/* The function displayDigit takes a digit as an input and lights up the corresponding pins of the display. */
void displayDigit(int inDigit)
{
    switch(inDigit)
     {
      case 1:
        {
          digitalWrite(cathodeA_pin, HIGH);
          digitalWrite(cathodeB_pin, LOW);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin,HIGH);
          digitalWrite(cathodeE_pin, HIGH);
          digitalWrite(cathodeF_pin, HIGH);
          digitalWrite(cathodeG_pin, HIGH);
          break; 
        }
      case 2:
        {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeB_pin, LOW);
          digitalWrite(cathodeC_pin, HIGH);
          digitalWrite(cathodeD_pin, LOW);
          digitalWrite(cathodeE_pin, LOW);
          digitalWrite(cathodeF_pin, HIGH);
          digitalWrite(cathodeG_pin, LOW);
          break; 
        }
      case 3:
        {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeB_pin, LOW);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin, LOW);
          digitalWrite(cathodeE_pin, HIGH);
          digitalWrite(cathodeF_pin, HIGH);
          digitalWrite(cathodeG_pin, LOW);
          break; 
        }
      case 4:
        {
          digitalWrite(cathodeA_pin, HIGH);
          digitalWrite(cathodeB_pin, LOW);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin, HIGH);
          digitalWrite(cathodeE_pin, HIGH);
          digitalWrite(cathodeF_pin, LOW);
          digitalWrite(cathodeG_pin, LOW);
          break; 
        }
      case 5:
        {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeB_pin, HIGH);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin, LOW);
          digitalWrite(cathodeE_pin, HIGH);
          digitalWrite(cathodeF_pin, LOW);
          digitalWrite(cathodeG_pin, LOW);
          break; 
        }
      case 6:
        {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeB_pin, HIGH);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin, LOW);
          digitalWrite(cathodeE_pin, LOW);
          digitalWrite(cathodeF_pin, LOW);
          digitalWrite(cathodeG_pin, LOW);
          break; 
        }
      case 7:
        {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeB_pin, LOW);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin, HIGH);
          digitalWrite(cathodeE_pin, HIGH);
          digitalWrite(cathodeF_pin, HIGH);
          digitalWrite(cathodeG_pin, HIGH);
          break; 
        }
      case 8:
        {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeB_pin, LOW);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin, LOW);
          digitalWrite(cathodeE_pin, LOW);
          digitalWrite(cathodeF_pin, LOW);
          digitalWrite(cathodeG_pin, LOW);
          break; 
        }
      case 9:
        {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeB_pin, LOW);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin, HIGH);
          digitalWrite(cathodeE_pin, HIGH);
          digitalWrite(cathodeF_pin, LOW);
          digitalWrite(cathodeG_pin, LOW);
          break; 
        }
      case 0:
        {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeB_pin, LOW);
          digitalWrite(cathodeC_pin, LOW);
          digitalWrite(cathodeD_pin, LOW);
          digitalWrite(cathodeE_pin, LOW);
          digitalWrite(cathodeF_pin, LOW);
          digitalWrite(cathodeG_pin, HIGH);
          break; 
        }
      default:
       {
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeA_pin, LOW);
          digitalWrite(cathodeA_pin, HIGH);
          break; 
        }
     }
}

Credits

amamitof7

amamitof7

2 projects • 1 follower

Comments