////////////////////////////////////////////// ////////////////////// ///////////////////////////////////////////////// ///////////////////////////// //// //// Gear_Cutting_Machine.ino //// //// Drives a stepper motor used for a dividing head //// //// Also controls the linear carriage movement //// //// Copyright 2005,2014 A, Theberge //// //// //// //// //// //// UP - DOWN pushbuttons choose the gear size //// //// SELECT start the gear cutting process //// //// LEFT is the emergency stop //// //// RIGHT moves the carrige backwards //// //// //// //// Stepper is connected on pins D4 - D7 //// //// Geared motor is connected to D2, D3 and D9 //// //// Linear_motion_switch (input) is pin D8 //// //// //// //// October 6th 2005: Microchip PIC version by Andre Theberge //// //// Ported to Arduino on Sept 9th, 2014 by Andre Theberge //// //// //// ////////////////////////////////////////////// ////////////////////// ///////////////////////////////////////////////// ///////////////////////////// //// // include the Adafruit library code: #include
#include #include Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield( Adafruit_RGBLCDShield(); ); // These #define sets the backlight color #define WHITE 0x7 //--------------Functions //--------------Functi ons and variables declared here----------------long divider, tooth, n_steps, m_steps; int stepper_delay, i, j, buttons; boolean stopped_by_user; long const reduction_multiplier = 95L * 400L; steps per revolution
// 95 teeth meccano gear * 400 //
%%% Adjust the # of steps
depending on the motor chosen %%% #def #defin ine e Gear Geared ed_M _Mot otor or_A _A #defin #define e Geared Geared_Mo _Motor tor_B _B
2 3
// Outp Output uts, s, gear geared ed moto motor r
#define Linear_motion_top_swit Linear_motion_top_switch ch 8 // Input, limit switch to change motor dire ction #define Linear_motion_bottom_s Linear_motion_bottom_switch witch 9 // Input, limit switch to change motor d irection byte const POSITIONS[4] = {B01010000, // B10010000, B10100000, B01100000}; #define #define Stepper_Mo Stepper_Motor_E tor_Enable nableA A 10 #define #define Stepper_Mo Stepper_Motor_E tor_Enable nableB B 11
Phases for stepper motor
//
Controls stepper stepper motor, sends a series of pulses at a given speed
void drive_stepper(int stepper_delay, char dir, long steps) { static int stepper_state = 0; long i; digitalWrite(Stepper_Motor_EnableA, digitalWrite(Stepper_Mo tor_EnableA, HIGH); // Enable L293 chip (drivers are ON) digitalWrite(Stepper_Motor_EnableB, digitalWrite(Stepper_Mo tor_EnableB, HIGH); for(i=0; i
Remove any voltage voltage on stepper motor coils coils
void release_stepper(void) { DDRD = DDRD | B11110000; //Digital pins 4-7 are connected to stepper motor PORTD = (PORTD & B00001111) ; // Put all the stepper pins to 0 digitalWrite(Stepper_Motor_EnableA, digitalWrite(Stepper_Moto r_EnableA, LOW); // Disable L293 chip (drivers O FF) digitalWrite(Stepper_Motor_EnableB, digitalWrite(Stepper_Moto r_EnableB, LOW); } // Move carriage backwards until bottom limit switch switch is hit, then forward to it s original position. void carriage_Back_and_forth() { // Move carriage backwards (cutting phase) digitalWrite(Geared_Motor_A, digitalWrite(Geared_Mo tor_A, LOW); digitalWrite(Geared_Motor_B, digitalWrite(Geared_Mo tor_B, HIGH); for (i=0; i<5000; i++) { // Timed delay until we reached the bottom switch %%% Adjust this delay if necessary %%% buttons = lcd.readButtons(); // Monitor pushbuttons if (buttons & BUTTON_LEFT) break; // Exit if LEFT pushbutton pressed (em ergency exit) if (digitalRead(Linear_motio (digitalRead(Linear_motion_bottom_switch)==LOW) n_bottom_switch)==LOW) break; // Exit also if we hit limit switch (normal operation) } if (buttons & BUTTON_LEFT) { stop_motor_and_alert_user(); goto EMERGENCY_EXIT; // Exit if LEFT pushbutton pressed (emergency exit) } digitalWrite(Geared_Motor_A, digitalWrite(Geared_Mo tor_A, LOW); // Stop motor for a bit before changing direction digitalWrite(Geared_Motor_B, digitalWrite(Geared_Mo tor_B, LOW);
delay(200);
//
Pause a bit
// Move carriage forward digitalWrite(Geared_Motor_A, digitalWrite(Geared_Mo tor_A, HIGH); digitalWrite(Geared_Motor_B, digitalWrite(Geared_Mo tor_B, LOW); for (i=0; i<5000; i++) { // Restart the motor in the opposite direction with a delay %%% Adjust this delay delay if necessary %%% %%% buttons = lcd.readButtons(); // Monitor pushbuttons if (buttons & BUTTON_LEFT) break; // Exit if LEFT pushbutton pressed (em ergency exit) if (digitalRead(Linear_motio (digitalRead(Linear_motion_top_switch)==LOW) n_top_switch)==LOW) break; // Exit also if we hit limit switch (normal operation) } if (buttons & BUTTON_LEFT) { stop_motor_and_alert_user(); goto EMERGENCY_EXIT; // Exit if LEFT pushbutton pressed (emergency exit) } digitalWrite(Geared_Motor_A, digitalWrite(Geared_Mo tor_A, LOW); // Geared motor off digitalWrite(Geared_Motor_B, digitalWrite(Geared_Mo tor_B, LOW); EMERGENCY_EXIT: delay(100); }
//
Wait for motors to completely stop
void stop_motor_and_alert_user() { // Stop motor digitalWrite(Geared_Motor_A, digitalWrite(Geared_Mo tor_A, LOW); // Geared motor off digitalWrite(Geared_Motor_B, digitalWrite(Geared_Mo tor_B, LOW); // Tell user and set flag lcd.setCursor(0,1); lcd.print("STOPPED by user "); // Update display stopped_by_user = true; } void print_gear_size() { lcd.setCursor(0,0); lcd.print("Gear size = "); // Update display lcd.print(divider); lcd.print("t "); // Pad extra spaces delay(100); // A bit of delay if the button is held down } //--------------------Setup //-------------------Setup routine--------------routine-------------------------------------void setup() {
// %%% Serial link used for debugging output only %%% Serial.begin(9600);
// set up the LCD's number of columns and rows: lcd.begin(16, 2); lcd.setBacklight(WHITE);
tooth=0; divider=19; stopped_by_user = false;
// Initialise variables
pinMode(Geared_Motor_A, OUTPUT);
//
Geared motor
pinMode(Geared_Motor_B, OUTPUT); digitalWrite(Geared_Motor_A, digitalWrite(Geared_Mot or_A, LOW); digitalWrite(Geared_Motor_B, digitalWrite(Geared_Mot or_B, LOW);
// Geared motor off
pinMode(Linear_motion_top_switch, pinMode(Linear_motion_t op_switch, INPUT_PULLUP); // Set Set pull-up pull-up on switches (active low) pinMode(Linear_motion_bottom_switch, pinMode(Linear_motion_b ottom_switch, INPUT_PULLUP); pinMode(Stepper_Motor_EnableA, OUTPUT); // pinMode(Stepper_Motor_EnableA, pinMode(Stepper_Motor_EnableB, pinMode(Stepper_Motor_E nableB, OUTPUT); release_stepper(); // Stepper motor off
Stepper motor
lcd.setCursor(0, 0); // Print initialisation message on the LCD screen lcd.print(" Gear Cutter"); lcd.setCursor(0, 1); lcd.print("(c) A. Theberge");
delay(1000); // Delay so so user can read message lcd.clear(); print_gear_size(); // Print default gear size
} //--------------------Loop routine---------------//--------------------Loop routine------------------------------------void loop() { buttons = lcd.readButtons(); if (buttons) {
// Read pushbuttons
// If one pressed....
if (buttons (buttons & BUTTON_DOWN) { // Set gear size size if (divider > 12) divider = divider -1; // Allow divider values as low as 12 print_gear_size(); // Update display } if (buttons & BUTTON_UP) { // Set gear size if (divider < 76) divider = divider +1; // as 76 print_gear_size(); // Update display }
Allow divider values as high
if (buttons & BUTTON_RIGHT) { // Move carriage forward if (digitalRead(Linear_moti (digitalRead(Linear_motion_top_switch)==HIGH) on_top_switch)==HIGH) { // If not at the top o f its course digitalWrite(Geared_Motor_A, digitalWrite(Geared_Motor _A, HIGH); // Move the carriage by increm ents of 1/10th of a second digitalWrite(Geared_Motor_B, digitalWrite(Geared_Motor _B, LOW); delay(100); // digitalWrite(Geared_Motor_A, digitalWrite(Geared_Motor _A, LOW); } else { lcd.setCursor(0,1); lcd.print("Reached the top "); // Update display } }
if (buttons & BUTTON_SELECT) { // Perform the automated cutting process lcd.setCursor(0,1); lcd.print("Cut Gear Teeth "); // Update display delay(1500); // 1.5 second delay before process start )s
o user can read previous message) stepper_delay=3; stopped_by_user = false; ng cutting process.
// Maximum rotation speed // Set 'true' if user press LEFT button duri
for(j=tooth; j
// FOR loop to cut all the teeth
lcd.setCursor(0,1); lcd.print("Cutting # "); // Which tooth we are durrently cutting lcd.print(tooth+1); lcd.print(" "); // Extra spaces to fill complete line // Do a back and from motion of the carriage carriage_Back_and_forth(); if (stopped_by_user) break; // In case of emergency stop, exit loop
// Now turn dividing head to cut next tooth tooth=tooth+1; lcd.setCursor(0,1); if (tooth < divider) { lcd.print("Set-up for # "); // Which tooth we are currently cutting lcd.print(tooth+1); lcd.print(" "); // Extra spaces to fill complete line
//
} else { lcd.print("Return to origin "); // Only after the last cut } m_steps=((tooth-1)*reduction_multiplier)/divider; Serial.println(m_steps); // %%% For debug purpose only
//
n_steps=((tooth*reduction_multiplier)/divider) n_steps=((tooth*reductio n_multiplier)/divider) - m_steps; Serial.println(n_steps); // %%% For debug purpose only
drive_stepper(stepper_delay,'F',n_steps); drive_stepper(stepper_de lay,'F',n_steps); //rotate the shaft the width of a tooth if (tooth>=divider) tooth=0; // go a maximum of "divider" }
// of FOR
release_stepper(); if (!stopped_by_user) { lcd.setCursor(0,1); lcd.print("Job complete "); // Only after the last cut } } // of IF statement; statement; Enter Enter button button is pressed } // of any button pressed
} // of loop()