Project in progress

Digital 3D printer filament counter using PS/2 mouse © CC BY-NC-SA

Ever wonder how much filament you actually used for a project or have an old mechanical ball mouse laying around to be recycled?

  • 6,725 views
  • 3 comments
  • 22 respects

Components and supplies

Apps and online services

About this project

Ever wonder how much filament did you actually use for a project? Have an old mechanical ball mouse laying around waiting for recycling? Let's convert it into a filament counter with simple Arduino and 3D printed parts. The mechanical PS/2 mouse contains fairly high-resolution encoder wheels and a simple serial interface as well as electronics to process the quadrature input signals from the encoder wheels. There are Arduino libraries written to talk to the mouse and get the direction of the distance of rotation of the encoder wheels. By connecting the encoder wheel to a filament roller, we can track the actual usage of the filament for each project by using the Arduino and display the results in millimeter on a LCD display. Since the mouse outputs the relative position to its original position in both directions, the counter is able to accurately measure and actual usage of the filament even when the filament direction is reversed occasionally due to retraction.

Step 1: What you need

Here is a list of all the materials you need. The Dell M-SAW34 PS/2 ball mouse is made by Logitech which can be easily found online cheaply. Additionally you'll need some wires and screws, as well as access to a 3D printer (I assume you already do if you're interested in making a filament counter), and a soldering iron. Also I recommend to buy a bottle of rosin based liquid soldering flux which is also used as a coating to the filament idler wheel to increase friction.

1×PS/2 Mouse Dell Logitech 2-Button PS/2 Ball Mouse M-SAW34

1×Arduino UNO

1×Serial LCD 1602 16x2 Module With IIC/I2C Adapter Blue or green

1×12x12x7.3mm Momentary Tactile Push Button Switch with key cap

1×625zz 5x16x5 Shielded Miniature Ball Bearing

Dupont jumper wires or 16-18 AWG stranded wires, several

Step 2: Print the sensor body and the box

I printed all the parts use PLA with 25% infill. The STL files are attached, and are also available here

Step 3: Assembly of the sensor unit

Take the mouse apart, what we need is the circuit board and one of the encoder wheels. The mouse has two encoder wheels for X and Y axis respectively, we only use one of the wheel on the X-axis.

1. Cut the encoder to half near the small rims in the middle.

2. Prepare the idler wheel. Use a 2mm drill to clear out the mounting hole. Coat the idler wheel with the liquid lux. Once dry, the rosin residual will help to increase the surface friction.

3. Insert the printed idler wheel into the 625zz bearing, apply small amount of the Teflon spray lubricant then insert the bearing into the printed sensor body. Use epoxy if needed, make sure the bearing and the idler wheel assembly is perpendicular to the sensor body.

3. Insert the mouse encoder wheel to the other end of the idler wheel, again make sure the encoder wheel is perpendicular with minimum wobbling.

4. Mount the mouse printed circuit board, use a tweezer to adjust the location of the IR emitter and receiver so the encoder wheel is in the middle and cover at leat 1/2 of the receiver.

Step 4: Electronics

Wiring the rest of the circuit according to the wiring schematic. You can use either Dupont jumper wires or solder the wires directly to the pin headers.

Step 5: Programming

1. Add the ps2 library to your Arduino IDE

2. Connect your Arduino to the computer and install the sketch.

Step 6: How to use

The display has two rows. "U" is the current filament usage in millimeters. "T" is the total filament usage from the beginning. There is one RESET button. A short click will reset the "U" counter to zero, which is useful for each new project. A double click will reset the "T" to zero which s useful when replace the filament rolls. Additionally, when the unit powered up, the user is able to choose the direction of the filament movement, i.e. forward or backward depending on the mounting position of the sensor unit by pressing the Reset button.

Custom parts and enclosures

Thingiverse
http://www.thingiverse.com/thing:1946445

Schematics

Schematic 1
Ptwucgjfpukb3ieojxki
Schematic 2
Ifn76tlawjfteocxmn51
Schematic 3
Jlfjkhleuteg71hdrglm

Code

FPK8QVDIWE4HGET.inoArduino
#include <Wire.h>  // Comes with Arduino IDE
#include <ps2.h>
#include <LiquidCrystal_I2C.h>
/*
 * this is a modification to the original ps2 mouse sketch, it requires ps2 library,
 * can be found on arduino website.
 * Modified by Bin Sun.
 * Feel free to use or modify.
 * an arduino sketch to interface with a   mouse ( optical, ball, ps2 and some usb).
 * it measures the distance the mouse travels.
 * a button on pin 7 is used to zero the reading.
 * one side of the button is connected to pin 7 other to ground. 
 * it writes the results to a serial display.
 */

/*
 * Pin 5 is the mouse data pin, pin 6 is the clock pin
 * Feel free to use whatever pins are convenient.
 */
PS2 mouse(6, 5);
int val = 0 ;// variable for reading the pin
long newmx=0;
long newmy=0;
long total=0;
const int zeroPin=7; // set zeroPin pin number
boolean direct = true;

int buttonState;
unsigned long timePress = 0;
unsigned long timePressLimit = 0;
int clicks = 0;

float cal=2.5; //calibratino factor to conver mouse movement to milemeter

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
 
/*
 * initialize the mouse. Reset it, and place it into remote
 * mode, so we can get the encoder data on demand.
 */
void mouse_init()
{
  mouse.write(0xff);  // reset
  mouse.read();  // ack byte
  mouse.read();  // blank */
  mouse.read();  // blank */
  mouse.write(0xf0);  // remote mode
  mouse.read();  // ack
  delayMicroseconds(100);
}

void setup()
{
  pinMode(zeroPin, INPUT_PULLUP);
  Serial.begin(9600);
//  Serial.begin(115200);
 // lcd.init();
  lcd.backlight();
  lcd.begin(16,2);  // set up the LCD's number of columns and rows: 

 // Print a message to the LCD. 
  Serial.println("Filament Counter");
  lcd.setCursor(0,0);
  lcd.print("Filament Counter");
  lcd.setCursor(5,1);
  lcd.print("Bin Sun");
  delay(2000);
  
  lcd.clear();
  checkDir();
  mouse_init();
}

void checkDir(){
  lcd.setCursor(0,0);
  lcd.print("Change Direction?");
  lcd.setCursor(0,1);
  lcd.print("Hold RESET 4 YES");
  delay(2000);
  lcd.setCursor(0,1);
  lcd.print("                ");
  boolean resetPressed = false;
  int countdown = 3;
  while (!resetPressed && countdown >= 0){
    val = digitalRead(zeroPin);
    if(val == LOW){
      lcd.clear();
      lcd.setCursor(0,1);
      lcd.print("Direct. Changed");
      delay(1000);
      resetPressed = true;
      direct=false;
      lcd.clear();
    }
    lcd.setCursor(0,2);
    lcd.print("Countdown:   ");
    lcd.setCursor(0,2);
    lcd.print("Countdown: ");
    lcd.print(countdown);
    countdown--;
    if(countdown <0){
      lcd.clear();
      lcd.setCursor(0,0);
    }
    if(resetPressed){
      lcd.clear();
      lcd.setCursor(0,0);
    }
    delay(1000);
  }
}


/*
* get a reading from the mouse and report it back to the
* host via the serial line.
*/
void loop()
{
  char mstat;
  char mx;
  char my;
 
  /* get a reading from the mouse */
  mouse.write(0xeb);  // give me data!
  mouse.read();      // ignore ack
  mstat = mouse.read();
  mx = mouse.read();
  my = mouse.read();

//reverse direction
//  mx = mx*direct;
if(direct){
  mx = mx*-1;
}

  total =  total + mx; //calculate total
  newmx=newmx+ mx;

  buttonState = digitalRead(zeroPin);

  if (buttonState == LOW){
    delay(200);
//    Serial.println("Button Pressed");
    
    if (clicks == 0) {
    timePress = millis();
    timePressLimit = timePress + 500;    
    clicks = 1;
    }

    else if (clicks == 1 && millis() < timePressLimit){
//      Serial.println("Button Pressed twice");
      newmx = 0;
      total = 0;
      timePress = 0;
      timePressLimit = 0;
      clicks = 0;      
    }    
  

 if (clicks == 1 && timePressLimit != 0 && millis() > timePressLimit){
//     Serial.println("Button Pressed Once");
     timePress = 0;
     timePressLimit = 0;
     clicks = 0;
          
     newmx=0;


  }
  }
         
//  if ( digitalRead(zeroPin) == LOW)
//   {
//     newmy=0;
//     newmx=0;
//   }
//   else {
//     newmx=newmx+ mx;
//     newmy=newmy+my;
//   }

//while(digitalRead(zeroPin) == LOW){}
//  delay(1000);
//    if(digitalRead(zeroPin) == LOW){
//     total=0;
//      }
//    else{
//    newmx = 0;
//    }  
        
//  Serial.print(mstat, BIN);
//  Serial.println();
//  Serial.print("\tX=");
 // Serial.print(mx, DEC);// gives mm reading for my mouse
//  Serial.print("\t");
//  Serial.print(newmx/(cal));// gives mm reading for my mouse
//  Serial.print("\tY=");
//  Serial.print(my, DEC);//  gives mm reading for my mouse
//  Serial.print("\t");
//  Serial.print(newmy/(cal));//  gives mm reading for my mouse
//  Serial.println();
  
  lcd.setCursor(0,0);
  lcd.print("                ");
  lcd.setCursor(0,0);
  lcd.print("U~");
  lcd.print(newmx/(cal));
  lcd.print(" mm");
  lcd.setCursor(0,1);
  lcd.print("                ");
  lcd.setCursor(0,1);
  lcd.print("T~");
  lcd.print(total/(cal));
  lcd.print(" mm");
  
  
  delay(100);

  
   }

   

Comments

Similar projects you might like

Direction Indicators for Bikes

Project tutorial by Rosaliew

  • 233 views
  • 0 comments
  • 6 respects

Starry Night Prom

Project showcase by Maddy

  • 1,907 views
  • 12 comments
  • 16 respects

The Trump Button

Project tutorial by Aurelien Lequertier and Louis Moreau

  • 952 views
  • 4 comments
  • 7 respects

Third Eye for The Blind

Project tutorial by Muhammed Azhar

  • 855 views
  • 4 comments
  • 12 respects

ArduRadio AlarmClock

Project tutorial by Tittiamo

  • 1,908 views
  • 4 comments
  • 2 respects
Add projectSign up / Login