// // -- Caterpillar Controller v1.0 -- // // Using a Ramps 1.4 and a RepRap discount screen to precisely controll // the pulling motion needed to extrude a consistent filament. // // author: Van Alles Wat Ontwerp // more info: www.preciousplastic.com #include #include #include #include #include // PINS - For RAMPS 1.4 // OUTPUT - stepper #define CAT_STEP_PIN 54 #define CAT_DIR_PIN 55 #define CAT_ENABLE_PIN 38 #define SPOOL_STEP_PIN 60 #define SPOOL_DIR_PIN 61 #define SPOOL_ENABLE_PIN 56 // LCD (RepRapDiscount Smart Controller) #define LCD_PINS_RS 16 #define LCD_PINS_ENABLE 17 #define LCD_PINS_D4 23 #define LCD_PINS_D5 25 #define LCD_PINS_D6 27 #define LCD_PINS_D7 29 // OUTPUT - other #define FAN_PIN 9 #define LED_PIN 13 #define BEEPER_PIN 37 // INPUT - ENCODER #define BTN_EN1 31 #define BTN_EN2 33 #define BTN_ENC 35 //the clicking button // INPUT - OTHER #define BEEPER 37 #define KILL_PIN 41 // Stepper settings const float maxSpeed = 1000; // maximum steps per second const float startSpeed = 50; // speed at which the machine starts const float acceleration = 5; // steps/second/second to accelerate const float stepperBoost = 1000; const float reverseSpeed = 0; const float spoolMultiplier = 1.0; // LCD vars LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5, LCD_PINS_D6, LCD_PINS_D7); unsigned long clock = millis(); const int LCDrefreshrate = 500; float catterpillarDistance = 0; StopWatch sw_secs(StopWatch::SECONDS); // Stepper vars AccelStepper caterpillar(1, CAT_STEP_PIN, CAT_DIR_PIN); AccelStepper spool(1, SPOOL_STEP_PIN, SPOOL_DIR_PIN); float curSpeed = startSpeed; float memSpeed = 0; boolean motorOn = false; boolean boostStepper = false; boolean reverse = false; // Encoder vars ClickEncoder *encoder; int16_t last, value; // init void setup() { // set up the LCD's number of columns and rows: lcd.clear(); lcd.begin(20, 4); lcd.setCursor(0,0); lcd.print("Speed: mm/s"); lcd.setCursor(0,1); lcd.print("Distance: m"); lcd.setCursor(0,2); lcd.print("Time: "); // output pins pinMode(FAN_PIN , OUTPUT); pinMode(LED_PIN , OUTPUT); pinMode(BEEPER_PIN , OUTPUT); pinMode(CAT_ENABLE_PIN , OUTPUT); pinMode(SPOOL_ENABLE_PIN, OUTPUT); digitalWrite(CAT_ENABLE_PIN , LOW); digitalWrite(SPOOL_ENABLE_PIN , LOW); // initialise stepper and encoder iniStepper(); iniEncoder(); // ready to go digitalWrite(BEEPER_PIN , HIGH); delay(10); digitalWrite(BEEPER_PIN , LOW); } // loop void loop() { // check encoder for value changes and change motor settings accordingly checkEncoder(); // make the stepper run at a specific speed caterpillar.runSpeed(); spool.runSpeed(); if(millis() > clock){ // update the LCD updateLCD(); clock = millis() + LCDrefreshrate; } } void updateLCD() { // calculate speed in mm/s // stepper motor steps per second / number of steps it takes to complete 1 revolution (200 x 1/4 stepping = 800) // multiply with: // diameter of the roller times PI to get the circumference of the roller float catterpillarSpeed = ((float(caterpillar.speed()) / 800.0) * ( 44.0 * PI)); // display speed lcd.setCursor(11, 0); lcd.print(" "); lcd.setCursor(7, 0); lcd.print(catterpillarSpeed); // calculate distance catterpillarDistance = catterpillarDistance + (((catterpillarSpeed/1000) * (LCDrefreshrate ))) / 1000; // display distance lcd.setCursor(10,1); lcd.print(catterpillarDistance); // get time int time = sw_secs.elapsed(); int mins = time / 60; time = time % 60; int secs = time; // display time lcd.setCursor(6,2); lcd.print(mins); if(secs < 10){ lcd.print(":0"); } else{ lcd.print(":"); } lcd.print(secs); } // init stepper void iniStepper() { // initialise caterpillar stepper with settings caterpillar.setPinsInverted(false, false, true); caterpillar.setEnablePin(CAT_ENABLE_PIN); caterpillar.setMaxSpeed(maxSpeed); caterpillar.setAcceleration(acceleration); // initialise spool stepper with settings spool.setPinsInverted(false, false, true); spool.setEnablePin(SPOOL_ENABLE_PIN); spool.setMaxSpeed(maxSpeed); // start the stepper if the motor should be on if(motorOn) setMotorSpeed(curSpeed); else switchMotorOff(); } // init encoder void iniEncoder() { // create new encoder with correct pins encoder = new ClickEncoder(BTN_EN1, BTN_EN2, BTN_ENC); // create timer for checks Timer1.initialize(1000); Timer1.attachInterrupt(timerIsr); last = -1; } // check and update encoder void checkEncoder() { // read encoder turn value and reverse value value += (encoder->getValue() * -1); // if value is different from last known value, print out new value, set new motor speed if (value != last) { int difference = value - last; last = value; // if the motor should be running, change the speed if(!reverse) { // set motor speed based on encoder value curSpeed = startSpeed + value; setMotorSpeed(curSpeed); } else { memSpeed += difference; setMotorSpeed(memSpeed); } } // check click actions (click, doubleclick, hold, release) ClickEncoder::Button b = encoder->getButton(); if (b != ClickEncoder::Open) { switch (b) { case ClickEncoder::Held: // when button is held, boost the stepper if(!boostStepper) { boostStepper = true; memSpeed = caterpillar.speed(); if(caterpillar.speed() >= 0) setMotorSpeed(caterpillar.speed() + (stepperBoost + (caterpillar.speed() / 100))); else setMotorSpeed(caterpillar.speed() - (stepperBoost + (caterpillar.speed() / 100))); } break; case ClickEncoder::Released: // when button is released, return stepper speed to normal if(boostStepper) { boostStepper = false; setMotorSpeed(memSpeed); } break; case ClickEncoder::Clicked: // feedback sound digitalWrite(BEEPER_PIN , HIGH); delay(10); digitalWrite(BEEPER_PIN , LOW); // when button is clicked, switch motor on/off if(motorOn) { switchMotorOff(); } else { if(!reverse) switchMotorOn(curSpeed); else switchMotorOn(memSpeed); } break; case ClickEncoder::DoubleClicked: // feedback sound digitalWrite(BEEPER_PIN , HIGH); delay(10); digitalWrite(BEEPER_PIN , LOW); delay(50); digitalWrite(BEEPER_PIN , HIGH); delay(10); digitalWrite(BEEPER_PIN , LOW); //reset distance catterpillarDistance = 0; sw_secs.reset(); if(motorOn) sw_secs.start(); } } } void setMotorSpeed(int targetSpeed) { if(motorOn) { if(caterpillar.speed() == 0) caterpillar.enableOutputs(); if(spool.speed() == 0) spool.enableOutputs(); caterpillar.setSpeed(targetSpeed); spool.setSpeed(targetSpeed * spoolMultiplier); } } void switchMotorOn(int targetSpeed) { motorOn = true; sw_secs.start(); caterpillar.enableOutputs(); caterpillar.setSpeed(targetSpeed); spool.enableOutputs(); spool.setSpeed(targetSpeed * spoolMultiplier); } void switchMotorOff() { motorOn = false; sw_secs.stop(); caterpillar.setSpeed(0); caterpillar.disableOutputs(); spool.setSpeed(0); spool.disableOutputs(); } void timerIsr() { encoder->service(); }