diff --git a/code/Barrier.cpp b/code/Barrier.cpp index bf5ce20..4f6b283 100644 --- a/code/Barrier.cpp +++ b/code/Barrier.cpp @@ -21,6 +21,8 @@ class Barrier { void configure_pins(){ this->servo.attach(pin); + this->servo.write(90); + this->state = CLOSED; } void open(){ diff --git a/code/ButtonController.cpp b/code/ButtonController.cpp new file mode 100644 index 0000000..87ee7da --- /dev/null +++ b/code/ButtonController.cpp @@ -0,0 +1,40 @@ +#include + +class ButtonController { + + private: + int pin; + int new_value; + int old_value = HIGH; + + public: + ButtonController(int pin){ + this->set_pin(pin); + }; + + void configure_pins(){ + pinMode(this->pin, INPUT_PULLUP); + } + + void set_pin(int pin){ + this->pin = pin; + } + + void read(){ + this->new_value = digitalRead(this->pin); + } + + bool value_changed(){ + return (this->new_value != this->old_value); + } + + bool is_pressed(){ + if(this->value_changed()){ + bool is_pressed = (this->new_value == LOW); + this->old_value = this->new_value; + return is_pressed; + } + return this->new_value == LOW; + } + +}; \ No newline at end of file diff --git a/code/CarSpotController.cpp b/code/CarSpotController.cpp new file mode 100644 index 0000000..85e919d --- /dev/null +++ b/code/CarSpotController.cpp @@ -0,0 +1,51 @@ +class CarSpotController { + + private: + int total_spots; + int occupied_spots; + + public: + CarSpotController(int default_total_spots) { + this->set_total_spots(default_total_spots); + } + + int get_total_spots() { + return this->total_spots; + } + + void set_total_spots(int total_spots) { + this->total_spots = total_spots; + } + + int get_occupied_spots() { + return this->occupied_spots; + } + + void set_occupied_spots(int occupied_spots) { + this->occupied_spots = occupied_spots; + } + + void increment_occupied_spots () { + this->occupied_spots++; + } + + void increment_total_spots () { + this->total_spots++; + } + + void decrement_total_spots () { + this->total_spots--; + } + + void decrement_occupied_spots () { + this->occupied_spots--; + } + + bool is_full() { + return this->occupied_spots == this->total_spots; + } + + bool is_empty() { + return this->occupied_spots == 0; + } +}; \ No newline at end of file diff --git a/code/DistSensor.cpp b/code/DistSensor.cpp index abe839b..1fdaa39 100644 --- a/code/DistSensor.cpp +++ b/code/DistSensor.cpp @@ -9,7 +9,7 @@ class DistSensor { void make_measurement(){ digitalWrite(this->trig_pin, HIGH); - delayMicroseconds(10); + //delayMicroseconds(10); digitalWrite(this->trig_pin, LOW); } diff --git a/code/EncoderController.cpp b/code/EncoderController.cpp new file mode 100644 index 0000000..4ce0598 --- /dev/null +++ b/code/EncoderController.cpp @@ -0,0 +1,90 @@ +#include + +enum EncoderDirection { + COUNTERCLOCKWISE = 2, + STOPPED = 0, + CLOCKWISE = 1, +}; + +enum ButtonState { + PRESSED = 0, + RELEASED = 1, +}; + +class EncoderController { + + private: + int pin_clk; + int pin_dt; + int last_clk = HIGH; + int new_clk; + int dt_value; + EncoderDirection current_direction; + int pin_btn; + int button; + bool last_button_state = HIGH; // começa como solto + bool button_click_registered = false; + + public: + EncoderController(int pin_dt, int pin_clk, int pin_btn) { + this->pin_dt = pin_dt; + this->pin_clk = pin_clk; + this->pin_btn = pin_btn; + } + + void configure_pins() { + pinMode(this->pin_dt, INPUT_PULLUP); + pinMode(this->pin_clk, INPUT_PULLUP); + pinMode(this->pin_btn, INPUT_PULLUP); + } + + bool clk_pin_changed(){ + this->new_clk = digitalRead(this->pin_clk); + return this->new_clk != this->last_clk; + } + + void read(){ + if (this->clk_pin_changed()) { + this->last_clk = this->new_clk; + this->dt_value = digitalRead(this->pin_dt); + if (this->new_clk == LOW && this->dt_value == HIGH) { + + this->current_direction = CLOCKWISE; + } + if (this->new_clk == LOW && this->dt_value == LOW) { + + this->current_direction = COUNTERCLOCKWISE; + } + } + + int current_state = digitalRead(this->pin_btn); + if (this->last_button_state == HIGH && current_state == LOW) { + this->button_click_registered = true; + } + this->last_button_state = current_state; + } + + bool rotated_clockwise(){ + if(this->current_direction == CLOCKWISE){ + this->current_direction = STOPPED; + return true; + } + return false; + } + + bool rotated_counterclockwise(){ + if(this->current_direction == COUNTERCLOCKWISE){ + this->current_direction = STOPPED; + return true; + } + return false; + } + + bool button_pressed(){ + if (this->button_click_registered) { + this->button_click_registered = false; + return true; + } + return false; + } +}; \ No newline at end of file diff --git a/code/JoyStickController.cpp b/code/JoyStickController.cpp new file mode 100644 index 0000000..5ece73c --- /dev/null +++ b/code/JoyStickController.cpp @@ -0,0 +1,69 @@ +#import "Arduino.h" + +class JoystickController { + + private: + int pin_x; + int pin_y; + int x = 1024 / 2; + int y = 1024 / 2; + + public: + JoystickController(int pin_x, int pin_y) { + this->set_pin_x(pin_x); + this->set_pin_y(pin_y); + } + + void configure_pins() { + pinMode(this->pin_x, INPUT); + pinMode(this->pin_y, INPUT); + } + + int get_x() { + return this->x; + } + + int get_y() { + return this->y; + } + + void set_x(int x) { + this->x = x; + } + + void set_y(int y) { + this->y = y; + } + + int get_pin_x() { + return this->pin_x; + } + + void set_pin_x(int pin_x) { + this->pin_x = pin_x; + } + + int get_pin_y() { + return this->pin_y; + } + + void set_pin_y(int pin_y) { + this->pin_y = pin_y; + } + + void read(){ + this->set_y(analogRead(this->pin_y)); + this->set_x(analogRead(this->pin_x)); + } + + bool is_moving_right(){ + this->read(); + return this->get_x() < 512; + } + + bool is_moving_left(){ + this->read(); + return this->get_x() > 512; + } + +}; \ No newline at end of file diff --git a/code/LCDScreen.cpp b/code/LCDScreen.cpp index e9e2f64..6eb2ce3 100644 --- a/code/LCDScreen.cpp +++ b/code/LCDScreen.cpp @@ -2,19 +2,26 @@ #include enum LCDScreenState { - DISPLAY_DEFAULT_MESSAGE, + DISPLAY_DEFAULT_MESSAGE = 0, DISPLAY_TEMPERATURE, - DISPLAY_PARKING_SPOTS + DISPLAY_PARKING_SPOTS, + CONFIGURATION_SCREEN }; class LCDScreen { private: LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27,20,4); - LCDScreenState state; + LCDScreenState current_state = 0; String default_message = "Bem vindo!"; public: + LCDScreenState ordered_states[3] = { + DISPLAY_DEFAULT_MESSAGE, + DISPLAY_TEMPERATURE, + DISPLAY_PARKING_SPOTS + }; + LCDScreen(String default_message = ""){ if (default_message != ""){ this->default_message = default_message; @@ -32,10 +39,7 @@ class LCDScreen { } void display_temperature(float temp){ - if (this->state != DISPLAY_TEMPERATURE){ - this->clear(); - this->state = DISPLAY_TEMPERATURE; - } + lcd.setCursor(0, 0); lcd.print("Temp: "); lcd.print(temp,1); @@ -43,12 +47,72 @@ class LCDScreen { } void display_default_message(){ - if (this->state != DISPLAY_DEFAULT_MESSAGE){ - this->clear(); - this->state = DISPLAY_DEFAULT_MESSAGE; - } + lcd.setCursor(0, 0); lcd.print(this->default_message); } -}; \ No newline at end of file + void display_parking_spots(int total_spots, int occupied_spots){ + + int free_spots = total_spots - occupied_spots; + lcd.setCursor(0, 0); + lcd.print("Occupied: "); + lcd.print(occupied_spots); + lcd.print(" / "); + lcd.print(total_spots); + lcd.setCursor(0, 1); + lcd.print("Free: "); + lcd.print(free_spots); + } + + void display_configuration_screen(int total_spots){ + if (this->current_state != CONFIGURATION_SCREEN){ + this->current_state = CONFIGURATION_SCREEN; + this->clear(); + lcd.setCursor(0, 0); + lcd.print("Conf. Mode"); + } + lcd.setCursor(0, 1); + lcd.print("Total Spots = "); + if (total_spots < 10){ + lcd.print("0"); + lcd.print(total_spots); + }else { + lcd.print(total_spots); + } + } + + LCDScreenState get_next_state(){ + if (this->current_state == 2){ + return this->ordered_states[0]; + } + return this->ordered_states[this->current_state + 1]; + } + + LCDScreenState get_previous_state(){ + if (this->current_state == 0){ + return this->ordered_states[2]; + } + return this->ordered_states[this->current_state - 1]; + } + + void set_state(LCDScreenState state){ + this->clear(); + this->current_state = state; + } + + void display(float temperature_in_c, int total_spots, int occupied_spots){ + switch(this->current_state){ + case DISPLAY_DEFAULT_MESSAGE: + this->display_default_message(); + break; + case DISPLAY_TEMPERATURE: + this->display_temperature(temperature_in_c); + break; + case DISPLAY_PARKING_SPOTS: + this->display_parking_spots(total_spots, occupied_spots); + break; + } + } + +}; diff --git a/code/code.ino b/code/code.ino index 0e4d921..a22e73e 100644 --- a/code/code.ino +++ b/code/code.ino @@ -1,56 +1,167 @@ #include #include #include +#include #include "Barrier.cpp"; #include "DistSensor.cpp"; #include "LCDScreen.cpp"; +#include "CarSpotController.cpp"; +#include "JoyStickController.cpp"; +#include "ButtonController.cpp"; +#include "EncoderController.cpp"; #define ULTRASONIC_SENSOR_PIN_TRIG 11 #define ULTRASONIC_SENSOR_PIN_ECHO 12 #define SERVO_PIN 10 #define TEMP_SENSOR_PIN 9 +#define JOYSTICK_X_PIN A1 +#define JOYSTICK_Y_PIN A0 +#define BUZZER_PIN 3 +#define BUTTON_PIN 8 +#define STEPPER_B_MINUS_PIN 6 +#define STEPPER_B_PLUS_PIN 5 +#define STEPPER_A_PLUS_PIN 4 +#define STEPPER_A_MINUS_PIN 2 +#define ENCODER_CLK_PIN 7 +#define ENCODER_DT_PIN A2 +#define ENCODER_SW_PIN A3 + +#define PARK_SLOTS 3 +#define STEP_MOTOR_STEPS 200 + +enum ProgramState { + CONFIG_MODE, + APP_MODE +}; OneWire oneWire(TEMP_SENSOR_PIN); DallasTemperature temperature_sensors(&oneWire); DistSensor dist_sensor = DistSensor(ULTRASONIC_SENSOR_PIN_TRIG, ULTRASONIC_SENSOR_PIN_ECHO, 25.0); -Barrier barrier = Barrier(SERVO_PIN, 4); +Barrier barrier = Barrier(SERVO_PIN, 2); LCDScreen screen = LCDScreen(); +CarSpotController car_spot_controller = CarSpotController(PARK_SLOTS); +JoystickController joystick = JoystickController(JOYSTICK_X_PIN, JOYSTICK_Y_PIN); +ButtonController button = ButtonController(BUTTON_PIN); +Stepper stepper(STEP_MOTOR_STEPS, STEPPER_B_MINUS_PIN, STEPPER_B_PLUS_PIN, STEPPER_A_PLUS_PIN, STEPPER_A_MINUS_PIN); +EncoderController encoder = EncoderController(ENCODER_DT_PIN, ENCODER_CLK_PIN,ENCODER_SW_PIN); -unsigned long current_time, sensor_last_time_activated, temperature_last_time_measured; +unsigned long current_time, sensor_last_time_readed, barrier_last_time_opened, temperature_last_time_measured, joystick_last_time_activated, joystick_last_time_readed, screen_last_time_updated, encoder_last_time_readed; float temperature_in_c = 0; +ProgramState program_state = CONFIG_MODE; + void setup() { - Serial.begin(9600); + Serial.begin(115200); dist_sensor.configure_pins(); barrier.configure_pins(); temperature_sensors.begin(); + joystick.configure_pins(); + button.configure_pins(); + stepper.setSpeed(60); + encoder.configure_pins(); screen.init(); - } void loop() { current_time = millis(); + + switch (program_state){ + case CONFIG_MODE: + run_config_mode(); + break; + case APP_MODE: + run_program(); + break; + } +} - if (dist_sensor.is_in_range()){ - sensor_last_time_activated = current_time; - if(barrier.is_closed()){ - barrier.open(); +void run_config_mode (){ + static bool is_first_time = true; + if (is_first_time){ + screen.display_configuration_screen(car_spot_controller.get_total_spots()); + is_first_time = false; + } + encoder.read(); + if (encoder.rotated_clockwise()){ + if (car_spot_controller.get_total_spots() < 15){ + car_spot_controller.increment_total_spots(); + screen.display_configuration_screen(car_spot_controller.get_total_spots()); } - } else if (!dist_sensor.is_in_range() && barrier.is_open()){ - if (current_time - sensor_last_time_activated >= barrier.open_time_seconds * 1000){ - barrier.close(); + } + if (encoder.rotated_counterclockwise()){ + if (car_spot_controller.get_total_spots() > 1 && car_spot_controller.get_occupied_spots() < car_spot_controller.get_total_spots()){ + car_spot_controller.decrement_total_spots(); + screen.display_configuration_screen(car_spot_controller.get_total_spots()); + } + } + if (encoder.button_pressed()){ + program_state = APP_MODE; + screen.set_state(0); + return; + } +} + +void run_program(){ + + button.read(); + if (button.is_pressed()){ + barrier_last_time_opened = current_time; + if (!car_spot_controller.is_empty() && barrier.is_closed()){ + barrier.open(); + stepper.step(STEP_MOTOR_STEPS); + car_spot_controller.decrement_occupied_spots(); + } + } + + if (current_time - sensor_last_time_readed >= 1000){ + if (dist_sensor.is_in_range()){ + barrier_last_time_opened = current_time; + if(barrier.is_closed()){ + if (!car_spot_controller.is_full()){ + barrier.open(); + car_spot_controller.increment_occupied_spots(); + stepper.step(STEP_MOTOR_STEPS); + }else{ + tone(BUZZER_PIN, 262, 500); + } + } + } else if (!dist_sensor.is_in_range() && barrier.is_open()){ + if (current_time - barrier_last_time_opened >= barrier.open_time_seconds * 1000 && !button.is_pressed()){ + barrier.close(); + stepper.step(-STEP_MOTOR_STEPS); + } } } if (current_time - temperature_last_time_measured >= 1000){ temperature_last_time_measured = current_time; + temperature_sensors.setWaitForConversion(false); temperature_sensors.requestTemperatures(); temperature_in_c = temperature_sensors.getTempCByIndex(0); } - screen.display_temperature(temperature_in_c); -} + if (joystick.is_moving_right() && current_time - joystick_last_time_activated >= 450){ + joystick_last_time_activated = current_time; + screen.set_state((screen.get_next_state())); + } + if (joystick.is_moving_left() && current_time - joystick_last_time_activated >= 450){ + joystick_last_time_activated = current_time; + screen.set_state(screen.get_previous_state()); + } + + if (current_time - screen_last_time_updated >= 500){ + screen_last_time_updated = current_time; + screen.display(temperature_in_c,car_spot_controller.get_total_spots(), car_spot_controller.get_occupied_spots()); + } + + encoder.read(); + if (encoder.button_pressed()){ + program_state = CONFIG_MODE; + screen.display_configuration_screen(car_spot_controller.get_total_spots()); + return; + } +} \ No newline at end of file diff --git a/diagram.json b/diagram.json index 4553d45..065d6f3 100644 --- a/diagram.json +++ b/diagram.json @@ -34,9 +34,8 @@ { "type": "wokwi-analog-joystick", "id": "joystick1", - "top": -99.1, - "left": -62.9, - "rotate": 90, + "top": -115.8, + "left": -90.6, "attrs": {} }, { @@ -53,6 +52,14 @@ "left": 18.65, "rotate": 90, "attrs": { "value": "4700" } + }, + { + "type": "wokwi-stepper-motor", + "id": "stepper1", + "top": -387.25, + "left": -376.54, + "rotate": 90, + "attrs": { "size": "14" } } ], "connections": [ @@ -80,10 +87,10 @@ [ "bb1:tp.9", "servo1:V+", "red", [ "v-94.1", "h7.6", "v-105.7" ] ], [ "bb1:tn.10", "servo1:GND", "black", [ "v0" ] ], [ "servo1:PWM", "uno:10", "orange", [ "h-124.8", "v-19", "h-58.3" ] ], - [ "joystick1:GND", "bb1:tn.36", "black", [ "h0" ] ], - [ "joystick1:VCC", "bb1:tp.35", "red", [ "h0" ] ], - [ "joystick1:VERT", "bb1:42t.a", "green", [ "h0" ] ], - [ "joystick1:HORZ", "bb1:44t.a", "blue", [ "h0" ] ], + [ "joystick1:GND", "bb1:tn.36", "black", [ "v57.6", "h-55.6" ] ], + [ "joystick1:VCC", "bb1:tp.35", "red", [ "v48", "h-36.4" ] ], + [ "joystick1:VERT", "bb1:42t.a", "green", [ "v67.2", "h-56.4" ] ], + [ "joystick1:HORZ", "bb1:44t.a", "blue", [ "v67.2", "h-46.8" ] ], [ "bb1:42t.b", "uno:A0", "green", [ "v1.6", "h-327.6", "v-86.4", "h-51.8" ] ], [ "bb1:44t.c", "uno:A1", "blue", [ "v1.6", "h-337.2", "v-105.6", "h-51.9" ] ], [ "lcd1:GND", "bb1:tn.28", "black", [ "h0" ] ], @@ -94,16 +101,20 @@ [ "bb1:57b.f", "bb1:57t.e", "black", [ "v0" ] ], [ "uno:9", "bb1:58t.d", "blue", [ "v480", "h519.2", "v-136" ] ], [ "bb1:58b.f", "bb1:58t.e", "violet", [ "v0" ] ], - [ "btn1:1.l", "bb1:4t.c", "", [ "$bb" ] ], - [ "btn1:2.l", "bb1:2t.c", "", [ "$bb" ] ], - [ "btn1:1.r", "bb1:4b.h", "", [ "$bb" ] ], - [ "btn1:2.r", "bb1:2b.h", "", [ "$bb" ] ], + [ "uno:A4", "bb1:37b.g", "gray", [ "v0" ] ], + [ "uno:A5", "bb1:38b.h", "purple", [ "v0" ] ], + [ "stepper1:A-", "uno:2", "green", [ "h0" ] ], + [ "stepper1:A+", "uno:4", "green", [ "h0" ] ], + [ "stepper1:B+", "uno:5", "green", [ "h0" ] ], + [ "stepper1:B-", "uno:6", "green", [ "h0" ] ], [ "r1:1", "bb1:58b.g", "", [ "$bb" ] ], [ "temp1:GND", "bb1:57t.c", "", [ "$bb" ] ], [ "temp1:DQ", "bb1:58t.c", "", [ "$bb" ] ], [ "temp1:VCC", "bb1:59t.c", "", [ "$bb" ] ], - [ "uno:A4", "bb1:37b.g", "gray", [ "v0" ] ], - [ "uno:A5", "bb1:38b.h", "purple", [ "v0" ] ] + [ "btn1:1.l", "bb1:4t.c", "", [ "$bb" ] ], + [ "btn1:2.l", "bb1:2t.c", "", [ "$bb" ] ], + [ "btn1:1.r", "bb1:4b.h", "", [ "$bb" ] ], + [ "btn1:2.r", "bb1:2b.h", "", [ "$bb" ] ] ], "dependencies": {} } \ No newline at end of file diff --git a/libs/Stepper/README.adoc b/libs/Stepper/README.adoc new file mode 100644 index 0000000..9d4d052 --- /dev/null +++ b/libs/Stepper/README.adoc @@ -0,0 +1,26 @@ += Stepper Library for Arduino = + +This library allows you to control unipolar or bipolar stepper motors. To use it you will need a stepper motor, and the appropriate hardware to control it. + +For more information about this library please visit us at +http://www.arduino.cc/en/Reference/Stepper + +== License == + +Copyright (c) Arduino LLC. All right reserved. +Copyright (c) Sebastian Gassner. All right reserved. +Copyright (c) Noah Shibley. All right reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libs/Stepper/examples/MotorKnob/MotorKnob.ino b/libs/Stepper/examples/MotorKnob/MotorKnob.ino new file mode 100644 index 0000000..5cf12ec --- /dev/null +++ b/libs/Stepper/examples/MotorKnob/MotorKnob.ino @@ -0,0 +1,39 @@ +/* + * MotorKnob + * + * A stepper motor follows the turns of a potentiometer + * (or other sensor) on analog input 0. + * + * http://www.arduino.cc/en/Reference/Stepper + * This example code is in the public domain. + */ + +#include + +// change this to the number of steps on your motor +#define STEPS 100 + +// create an instance of the stepper class, specifying +// the number of steps of the motor and the pins it's +// attached to +Stepper stepper(STEPS, 8, 9, 10, 11); + +// the previous reading from the analog input +int previous = 0; + +void setup() { + // set the speed of the motor to 30 RPMs + stepper.setSpeed(30); +} + +void loop() { + // get the sensor value + int val = analogRead(0); + + // move a number of steps equal to the change in the + // sensor reading + stepper.step(val - previous); + + // remember the previous value of the sensor + previous = val; +} \ No newline at end of file diff --git a/libs/Stepper/examples/stepper_oneRevolution/stepper_oneRevolution.ino b/libs/Stepper/examples/stepper_oneRevolution/stepper_oneRevolution.ino new file mode 100644 index 0000000..373eb60 --- /dev/null +++ b/libs/Stepper/examples/stepper_oneRevolution/stepper_oneRevolution.ino @@ -0,0 +1,44 @@ + +/* + Stepper Motor Control - one revolution + + This program drives a unipolar or bipolar stepper motor. + The motor is attached to digital pins 8 - 11 of the Arduino. + + The motor should revolve one revolution in one direction, then + one revolution in the other direction. + + + Created 11 Mar. 2007 + Modified 30 Nov. 2009 + by Tom Igoe + + */ + +#include + +const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution +// for your motor + +// initialize the stepper library on pins 8 through 11: +Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11); + +void setup() { + // set the speed at 60 rpm: + myStepper.setSpeed(60); + // initialize the serial port: + Serial.begin(9600); +} + +void loop() { + // step one revolution in one direction: + Serial.println("clockwise"); + myStepper.step(stepsPerRevolution); + delay(500); + + // step one revolution in the other direction: + Serial.println("counterclockwise"); + myStepper.step(-stepsPerRevolution); + delay(500); +} + diff --git a/libs/Stepper/examples/stepper_oneStepAtATime/stepper_oneStepAtATime.ino b/libs/Stepper/examples/stepper_oneStepAtATime/stepper_oneStepAtATime.ino new file mode 100644 index 0000000..e6c141f --- /dev/null +++ b/libs/Stepper/examples/stepper_oneStepAtATime/stepper_oneStepAtATime.ino @@ -0,0 +1,44 @@ + +/* + Stepper Motor Control - one step at a time + + This program drives a unipolar or bipolar stepper motor. + The motor is attached to digital pins 8 - 11 of the Arduino. + + The motor will step one step at a time, very slowly. You can use this to + test that you've got the four wires of your stepper wired to the correct + pins. If wired correctly, all steps should be in the same direction. + + Use this also to count the number of steps per revolution of your motor, + if you don't know it. Then plug that number into the oneRevolution + example to see if you got it right. + + Created 30 Nov. 2009 + by Tom Igoe + + */ + +#include + +const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution +// for your motor + +// initialize the stepper library on pins 8 through 11: +Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11); + +int stepCount = 0; // number of steps the motor has taken + +void setup() { + // initialize the serial port: + Serial.begin(9600); +} + +void loop() { + // step one step: + myStepper.step(1); + Serial.print("steps:"); + Serial.println(stepCount); + stepCount++; + delay(500); +} + diff --git a/libs/Stepper/examples/stepper_speedControl/stepper_speedControl.ino b/libs/Stepper/examples/stepper_speedControl/stepper_speedControl.ino new file mode 100644 index 0000000..5eb4f6a --- /dev/null +++ b/libs/Stepper/examples/stepper_speedControl/stepper_speedControl.ino @@ -0,0 +1,48 @@ + +/* + Stepper Motor Control - speed control + + This program drives a unipolar or bipolar stepper motor. + The motor is attached to digital pins 8 - 11 of the Arduino. + A potentiometer is connected to analog input 0. + + The motor will rotate in a clockwise direction. The higher the potentiometer value, + the faster the motor speed. Because setSpeed() sets the delay between steps, + you may notice the motor is less responsive to changes in the sensor value at + low speeds. + + Created 30 Nov. 2009 + Modified 28 Oct 2010 + by Tom Igoe + + */ + +#include + +const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution +// for your motor + + +// initialize the stepper library on pins 8 through 11: +Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11); + +int stepCount = 0; // number of steps the motor has taken + +void setup() { + // nothing to do inside the setup +} + +void loop() { + // read the sensor value: + int sensorReading = analogRead(A0); + // map it to a range from 0 to 100: + int motorSpeed = map(sensorReading, 0, 1023, 0, 100); + // set the motor speed: + if (motorSpeed > 0) { + myStepper.setSpeed(motorSpeed); + // step 1/100 of a revolution: + myStepper.step(stepsPerRevolution / 100); + } +} + + diff --git a/libs/Stepper/keywords.txt b/libs/Stepper/keywords.txt new file mode 100644 index 0000000..5e58a66 --- /dev/null +++ b/libs/Stepper/keywords.txt @@ -0,0 +1,28 @@ +####################################### +# Syntax Coloring Map For Test +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Stepper KEYWORD1 Stepper + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +step KEYWORD2 +setSpeed KEYWORD2 +version KEYWORD2 + +###################################### +# Instances (KEYWORD2) +####################################### +direction KEYWORD2 +speed KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libs/Stepper/library.properties b/libs/Stepper/library.properties new file mode 100644 index 0000000..875067a --- /dev/null +++ b/libs/Stepper/library.properties @@ -0,0 +1,9 @@ +name=Stepper +version=1.1.3 +author=Arduino +maintainer=Arduino +sentence=Allows Arduino boards to control a variety of stepper motors. +paragraph=This library allows you to control unipolar or bipolar stepper motors. To use it you will need a stepper motor, and the appropriate hardware to control it. +category=Device Control +url=http://www.arduino.cc/en/Reference/Stepper +architectures=* diff --git a/libs/Stepper/src/Stepper.cpp b/libs/Stepper/src/Stepper.cpp new file mode 100644 index 0000000..1f76295 --- /dev/null +++ b/libs/Stepper/src/Stepper.cpp @@ -0,0 +1,365 @@ +/* + * Stepper.cpp - Stepper library for Wiring/Arduino - Version 1.1.0 + * + * Original library (0.1) by Tom Igoe. + * Two-wire modifications (0.2) by Sebastian Gassner + * Combination version (0.3) by Tom Igoe and David Mellis + * Bug fix for four-wire (0.4) by Tom Igoe, bug fix from Noah Shibley + * High-speed stepping mod by Eugene Kozlenko + * Timer rollover fix by Eugene Kozlenko + * Five phase five wire (1.1.0) by Ryan Orendorff + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * + * Drives a unipolar, bipolar, or five phase stepper motor. + * + * When wiring multiple stepper motors to a microcontroller, you quickly run + * out of output pins, with each motor requiring 4 connections. + * + * By making use of the fact that at any time two of the four motor coils are + * the inverse of the other two, the number of control connections can be + * reduced from 4 to 2 for the unipolar and bipolar motors. + * + * A slightly modified circuit around a Darlington transistor array or an + * L293 H-bridge connects to only 2 microcontroler pins, inverts the signals + * received, and delivers the 4 (2 plus 2 inverted ones) output signals + * required for driving a stepper motor. Similarly the Arduino motor shields + * 2 direction pins may be used. + * + * The sequence of control signals for 5 phase, 5 control wires is as follows: + * + * Step C0 C1 C2 C3 C4 + * 1 0 1 1 0 1 + * 2 0 1 0 0 1 + * 3 0 1 0 1 1 + * 4 0 1 0 1 0 + * 5 1 1 0 1 0 + * 6 1 0 0 1 0 + * 7 1 0 1 1 0 + * 8 1 0 1 0 0 + * 9 1 0 1 0 1 + * 10 0 0 1 0 1 + * + * The sequence of control signals for 4 control wires is as follows: + * + * Step C0 C1 C2 C3 + * 1 1 0 1 0 + * 2 0 1 1 0 + * 3 0 1 0 1 + * 4 1 0 0 1 + * + * The sequence of controls signals for 2 control wires is as follows + * (columns C1 and C2 from above): + * + * Step C0 C1 + * 1 0 1 + * 2 1 1 + * 3 1 0 + * 4 0 0 + * + * The circuits can be found at + * + * http://www.arduino.cc/en/Tutorial/Stepper + */ + +#include "Arduino.h" +#include "Stepper.h" + +/* + * two-wire constructor. + * Sets which wires should control the motor. + */ +Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2) +{ + this->step_number = 0; // which step the motor is on + this->direction = 0; // motor direction + this->last_step_time = 0; // time stamp in us of the last step taken + this->number_of_steps = number_of_steps; // total number of steps for this motor + + // Arduino pins for the motor control connection: + this->motor_pin_1 = motor_pin_1; + this->motor_pin_2 = motor_pin_2; + + // setup the pins on the microcontroller: + pinMode(this->motor_pin_1, OUTPUT); + pinMode(this->motor_pin_2, OUTPUT); + + // When there are only 2 pins, set the others to 0: + this->motor_pin_3 = 0; + this->motor_pin_4 = 0; + this->motor_pin_5 = 0; + + // pin_count is used by the stepMotor() method: + this->pin_count = 2; +} + + +/* + * constructor for four-pin version + * Sets which wires should control the motor. + */ +Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, + int motor_pin_3, int motor_pin_4) +{ + this->step_number = 0; // which step the motor is on + this->direction = 0; // motor direction + this->last_step_time = 0; // time stamp in us of the last step taken + this->number_of_steps = number_of_steps; // total number of steps for this motor + + // Arduino pins for the motor control connection: + this->motor_pin_1 = motor_pin_1; + this->motor_pin_2 = motor_pin_2; + this->motor_pin_3 = motor_pin_3; + this->motor_pin_4 = motor_pin_4; + + // setup the pins on the microcontroller: + pinMode(this->motor_pin_1, OUTPUT); + pinMode(this->motor_pin_2, OUTPUT); + pinMode(this->motor_pin_3, OUTPUT); + pinMode(this->motor_pin_4, OUTPUT); + + // When there are 4 pins, set the others to 0: + this->motor_pin_5 = 0; + + // pin_count is used by the stepMotor() method: + this->pin_count = 4; +} + +/* + * constructor for five phase motor with five wires + * Sets which wires should control the motor. + */ +Stepper::Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, + int motor_pin_3, int motor_pin_4, + int motor_pin_5) +{ + this->step_number = 0; // which step the motor is on + this->direction = 0; // motor direction + this->last_step_time = 0; // time stamp in us of the last step taken + this->number_of_steps = number_of_steps; // total number of steps for this motor + + // Arduino pins for the motor control connection: + this->motor_pin_1 = motor_pin_1; + this->motor_pin_2 = motor_pin_2; + this->motor_pin_3 = motor_pin_3; + this->motor_pin_4 = motor_pin_4; + this->motor_pin_5 = motor_pin_5; + + // setup the pins on the microcontroller: + pinMode(this->motor_pin_1, OUTPUT); + pinMode(this->motor_pin_2, OUTPUT); + pinMode(this->motor_pin_3, OUTPUT); + pinMode(this->motor_pin_4, OUTPUT); + pinMode(this->motor_pin_5, OUTPUT); + + // pin_count is used by the stepMotor() method: + this->pin_count = 5; +} + +/* + * Sets the speed in revs per minute + */ +void Stepper::setSpeed(long whatSpeed) +{ + this->step_delay = 60L * 1000L * 1000L / this->number_of_steps / whatSpeed; +} + +/* + * Moves the motor steps_to_move steps. If the number is negative, + * the motor moves in the reverse direction. + */ +void Stepper::step(int steps_to_move) +{ + int steps_left = abs(steps_to_move); // how many steps to take + + // determine direction based on whether steps_to_mode is + or -: + if (steps_to_move > 0) { this->direction = 1; } + if (steps_to_move < 0) { this->direction = 0; } + + + // decrement the number of steps, moving one step each time: + while (steps_left > 0) + { + unsigned long now = micros(); + // move only if the appropriate delay has passed: + if (now - this->last_step_time >= this->step_delay) + { + // get the timeStamp of when you stepped: + this->last_step_time = now; + // increment or decrement the step number, + // depending on direction: + if (this->direction == 1) + { + this->step_number++; + if (this->step_number == this->number_of_steps) { + this->step_number = 0; + } + } + else + { + if (this->step_number == 0) { + this->step_number = this->number_of_steps; + } + this->step_number--; + } + // decrement the steps left: + steps_left--; + // step the motor to step number 0, 1, ..., {3 or 10} + if (this->pin_count == 5) + stepMotor(this->step_number % 10); + else + stepMotor(this->step_number % 4); + } + } +} + +/* + * Moves the motor forward or backwards. + */ +void Stepper::stepMotor(int thisStep) +{ + if (this->pin_count == 2) { + switch (thisStep) { + case 0: // 01 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + break; + case 1: // 11 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, HIGH); + break; + case 2: // 10 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, LOW); + break; + case 3: // 00 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, LOW); + break; + } + } + if (this->pin_count == 4) { + switch (thisStep) { + case 0: // 1010 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, LOW); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, LOW); + break; + case 1: // 0110 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, LOW); + break; + case 2: //0101 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, LOW); + digitalWrite(motor_pin_4, HIGH); + break; + case 3: //1001 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, LOW); + digitalWrite(motor_pin_3, LOW); + digitalWrite(motor_pin_4, HIGH); + break; + } + } + + if (this->pin_count == 5) { + switch (thisStep) { + case 0: // 01101 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, LOW); + digitalWrite(motor_pin_5, HIGH); + break; + case 1: // 01001 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, LOW); + digitalWrite(motor_pin_4, LOW); + digitalWrite(motor_pin_5, HIGH); + break; + case 2: // 01011 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, LOW); + digitalWrite(motor_pin_4, HIGH); + digitalWrite(motor_pin_5, HIGH); + break; + case 3: // 01010 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, LOW); + digitalWrite(motor_pin_4, HIGH); + digitalWrite(motor_pin_5, LOW); + break; + case 4: // 11010 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, HIGH); + digitalWrite(motor_pin_3, LOW); + digitalWrite(motor_pin_4, HIGH); + digitalWrite(motor_pin_5, LOW); + break; + case 5: // 10010 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, LOW); + digitalWrite(motor_pin_3, LOW); + digitalWrite(motor_pin_4, HIGH); + digitalWrite(motor_pin_5, LOW); + break; + case 6: // 10110 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, LOW); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, HIGH); + digitalWrite(motor_pin_5, LOW); + break; + case 7: // 10100 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, LOW); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, LOW); + digitalWrite(motor_pin_5, LOW); + break; + case 8: // 10101 + digitalWrite(motor_pin_1, HIGH); + digitalWrite(motor_pin_2, LOW); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, LOW); + digitalWrite(motor_pin_5, HIGH); + break; + case 9: // 00101 + digitalWrite(motor_pin_1, LOW); + digitalWrite(motor_pin_2, LOW); + digitalWrite(motor_pin_3, HIGH); + digitalWrite(motor_pin_4, LOW); + digitalWrite(motor_pin_5, HIGH); + break; + } + } +} + +/* + version() returns the version of the library: +*/ +int Stepper::version(void) +{ + return 5; +} diff --git a/libs/Stepper/src/Stepper.h b/libs/Stepper/src/Stepper.h new file mode 100644 index 0000000..2e68979 --- /dev/null +++ b/libs/Stepper/src/Stepper.h @@ -0,0 +1,121 @@ +/* + * Stepper.h - Stepper library for Wiring/Arduino - Version 1.1.0 + * + * Original library (0.1) by Tom Igoe. + * Two-wire modifications (0.2) by Sebastian Gassner + * Combination version (0.3) by Tom Igoe and David Mellis + * Bug fix for four-wire (0.4) by Tom Igoe, bug fix from Noah Shibley + * High-speed stepping mod by Eugene Kozlenko + * Timer rollover fix by Eugene Kozlenko + * Five phase five wire (1.1.0) by Ryan Orendorff + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * + * Drives a unipolar, bipolar, or five phase stepper motor. + * + * When wiring multiple stepper motors to a microcontroller, you quickly run + * out of output pins, with each motor requiring 4 connections. + * + * By making use of the fact that at any time two of the four motor coils are + * the inverse of the other two, the number of control connections can be + * reduced from 4 to 2 for the unipolar and bipolar motors. + * + * A slightly modified circuit around a Darlington transistor array or an + * L293 H-bridge connects to only 2 microcontroler pins, inverts the signals + * received, and delivers the 4 (2 plus 2 inverted ones) output signals + * required for driving a stepper motor. Similarly the Arduino motor shields + * 2 direction pins may be used. + * + * The sequence of control signals for 5 phase, 5 control wires is as follows: + * + * Step C0 C1 C2 C3 C4 + * 1 0 1 1 0 1 + * 2 0 1 0 0 1 + * 3 0 1 0 1 1 + * 4 0 1 0 1 0 + * 5 1 1 0 1 0 + * 6 1 0 0 1 0 + * 7 1 0 1 1 0 + * 8 1 0 1 0 0 + * 9 1 0 1 0 1 + * 10 0 0 1 0 1 + * + * The sequence of control signals for 4 control wires is as follows: + * + * Step C0 C1 C2 C3 + * 1 1 0 1 0 + * 2 0 1 1 0 + * 3 0 1 0 1 + * 4 1 0 0 1 + * + * The sequence of controls signals for 2 control wires is as follows + * (columns C1 and C2 from above): + * + * Step C0 C1 + * 1 0 1 + * 2 1 1 + * 3 1 0 + * 4 0 0 + * + * The circuits can be found at + * + * http://www.arduino.cc/en/Tutorial/Stepper + */ + +// ensure this library description is only included once +#ifndef Stepper_h +#define Stepper_h + +// library interface description +class Stepper { + public: + // constructors: + Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2); + Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, + int motor_pin_3, int motor_pin_4); + Stepper(int number_of_steps, int motor_pin_1, int motor_pin_2, + int motor_pin_3, int motor_pin_4, + int motor_pin_5); + + // speed setter method: + void setSpeed(long whatSpeed); + + // mover method: + void step(int number_of_steps); + + int version(void); + + private: + void stepMotor(int this_step); + + int direction; // Direction of rotation + unsigned long step_delay; // delay between steps, in ms, based on speed + int number_of_steps; // total number of steps this motor can take + int pin_count; // how many pins are in use. + int step_number; // which step the motor is on + + // motor pin numbers: + int motor_pin_1; + int motor_pin_2; + int motor_pin_3; + int motor_pin_4; + int motor_pin_5; // Only 5 phase motor + + unsigned long last_step_time; // time stamp in us of when the last step was taken +}; + +#endif +