Project 1
Onderzoeksverslag
Schetsen individuele lift etage
Componenten diagram individuele lift etage
Filmpje werkende liftetage
Code liftetage
#include <Wire.h>
// Define the pins for the sensor, LEDs and buttons connected to the arduino
const int IRSensorPin = 2;
const int DoorOpenLED = 3;
const int dataPin = 5; //Pin connected to DS of 74HC595 to be used as data line
const int latchPin = 6;//Pin connected to ST_CP of 74HC595 which indicates if data is sent or not
const int clockPin = 7;//Pin connected to SH_CP of 74HC595 for the clock signal
const int buttonUpPin = 8;
const int buttonUpLED = 9;
const int buttonDownPin = 10;
const int buttonDownLED = 11;
// Variables to keep track of the status of the sensor and buttons
int liftAvailable, buttonUp, buttonDown;
// Array of values which corresponds to the numbers 0 till 9 on the 7 segment display
int datArray[10] = {3, 159, 37, 13, 153, 73, 65, 31, 1, 9};
void setup() {
// Specify if the pins are input, output or input_pullup(connected with an internal resistor, so the input is always high and will be low when a button is pressed
pinMode(buttonUpPin, INPUT_PULLUP);
pinMode(buttonDownPin, INPUT_PULLUP);
pinMode(IRSensorPin, INPUT);
pinMode(DoorOpenLED, OUTPUT);
pinMode(buttonUpLED, OUTPUT);
pinMode(buttonDownLED, OUTPUT);
pinMode(latchPin,OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin,OUTPUT);
// Start the I2C connection with 12 as address
Wire.begin(12);
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
// Show an 8 on the 7segment to test if the 7segment is working well when the elevator is turned on
ShowOn7Segment(8);
}
void loop() {
static unsigned long startTime = millis(); //Specify the starttime
// When the buttons are pressed, the corresponding LEDs will turn on, the values are inverted because of the pullup resistor
if(!digitalRead(buttonUpPin)){
digitalWrite(buttonUpLED, HIGH);
buttonUp = 1;
}
if(!digitalRead(buttonDownPin)){
digitalWrite(buttonDownLED, HIGH);
buttonDown = 1;
}
// Inverted because HIGH signal on the IRSensorPin means no elevator detected
// When the Elevator is detected, 4 is shown on the 7segment which is my floor and when the elevator is on the floor for 1 second, the doors will open
if(!digitalRead(IRSensorPin)){
liftAvailable = 1; // When the elevator is detected, set liftAvailable to 1
if(millis() - startTime > 1500){ // When the elevator is detected for 1,5 seconds, open the doors, turn off the LEDs and set the state of the buttons to 0
digitalWrite(DoorOpenLED, HIGH);
digitalWrite(buttonUpLED, LOW);
buttonUp = 0;
digitalWrite(buttonDownLED, LOW);
buttonDown = 0;
}
} else{
liftAvailable = 0; // When the elevator is not detected, set liftAvailable to 0, close the doors and reset the timer
digitalWrite(DoorOpenLED, LOW);
startTime = millis();
}
}
// to start sending data, the latchPin is set to LOW and to stop sending data, the latchPin is set to HIGH
// The data is sent as serial communication, so every clock signal there will be sent 1 bit with the least signicant bit as first
void ShowOn7Segment(int number){
digitalWrite(latchPin, LOW);
shiftOut(dataPin,clockPin,LSBFIRST,datArray[number]);
digitalWrite(latchPin, HIGH);
}
// When the master sends a request, set the first, second and third bit of the integer "data" to 1 or 0 dependent on the state of the buttons or the sensor
// and send the data to the master with Wire.write
void requestEvent(){
int data = B00000000;
data += B1 * liftAvailable;
data += B10 * buttonUp;
data += B100 * buttonDown;
Wire.write(data);
}
// When the master sends data, read it with Wire.read and use it to show the floor number on the 7segment
void receiveEvent(int howMany){
int liftPos = Wire.read();
ShowOn7Segment(liftPos);
}
Links Git
Schetsen gehele lift
Filmpje werkende lift
Testrapport gehele lift
Code master
#include <Wire.h>
#include <LiquidCrystal.h>
#include <Keypad.h>
// Setup stepper
#define IN1 2
#define IN2 3
#define IN3 4
#define IN4 5
// Setup LCD Screen
#define d4 8
#define d5 9
#define d6 10
#define d7 11
#define rs 12
#define en 13
// Setup Keypad
#define ROW1 22
#define ROW2 24
#define ROW3 26
#define ROW4 28
#define COL1 30
#define COL2 32
#define COL3 34
// Stepper
int steps = 0;
boolean clockwise = true;
// LCD Screen
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Keypad
const byte ROWS = 4; //four rows
const byte COLS = 3; //four columns
char liftLayout[ROWS][COLS] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}
};
byte rowPins[ROWS] = {ROW1, ROW2, ROW3, ROW4};
byte colPins[COLS] = {COL1, COL2, COL3};
Keypad liftKeypad = Keypad( makeKeymap(liftLayout), rowPins, colPins, ROWS, COLS);
// For I2C and lift
const int CONNECTED_SLAVES = 5; // Amount of slaves attached
int floorButtonUp[CONNECTED_SLAVES]; // Array containing button information from the slaves
int floorButtonDown[CONNECTED_SLAVES]; // Array containing button information from the slaves
int floorButtonElevator[CONNECTED_SLAVES]; // Array containing button information from the master
int emergencyButton; // Value containing information about the emergency button
boolean liftAvailable[CONNECTED_SLAVES]; // Array containing which IR-modules are currently triggered
int currentFloor = 0; // Current location of the elevator
int floorStopTime = 4000; // Amount of milliseconds to stop on a floor
boolean movingUp = true; // which direction the elevator is going
boolean moveUp = false; // Should the motor move clockwise
boolean moveDown = false; // Should the motor move counter-clockwise
void setup() {
Serial.begin(2000000); // Begin serial communication
Wire.begin(); // Begin I2C communication
lcd.begin(16, 2); // Begin LCD Scherm
// Setup stepper
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
// this data is used for obtaining the information from the slaves, so set to false first
for (int i = 0; i < CONNECTED_SLAVES; i++) {
liftAvailable[i] = false;
floorButtonUp[i] = 0;
floorButtonDown[i] = 0;
}
// Call the keypadEvent function when event is received from the keypad
liftKeypad.addEventListener(keypadEvent);
}
void loop() {
char liftKey = liftKeypad.getKey(); // Check the input of the keypad every loop cycle
// Serial.println("getAndSendDataToAllFloors");
getAndSendDataToAllFloors(); // Retrieve which buttons are pressed and send the location of the elevator to the slaves
lcdDisplayHandler(currentFloor); // Change the display on the master
// Serial.println("debugArray");
// debugArray(); // Print contents of the arrays to the terminal for debugging purposes
// Serial.println("checkForMoveLift");
checkForMoveLift(); // Check to see whether the elevator needs to move
// Serial.println("moveLift");
moveLift(); // Move the elevator to its destination
// Serial.print("Current lift location is ");
// Serial.println(currentFloor);
// Serial.println("End of loop");
}
/*********************** I2C CODE ***********************/
void getAndSendDataToAllFloors() {
// For each of the connected slaves, request the currently pressed buttons and send where the elevator is and whether the door should open
for (int i = 0; i < CONNECTED_SLAVES; i++) {
int c = 0; // Initialize the variable for the data received from the slave
Wire.requestFrom(i + 8, 1); // Request 1 byte from the slave
while (Wire.available()) { // Only process the data when the slave sends data
c = Wire.read(); // Load the data into the variable
liftAvailable[i] = c & 1; // Put the first received bit in the liftAvailable array
if (c & 1) { // If the first bit is set, change the currentfloor
currentFloor = i;
}
floorButtonUp[i] = c >> 1 & 1; // If the second bit is set, set the value of the buttonup to 1 for the specific floor, otherwise to 0
floorButtonDown[i] = c >> 2 & 1; // If the third bit is set, set the value of the buttondown to 1 for the specific floor, otherwise to 0
}
}
// Send the current floor to each of the slaves
for (int j = 0; j < CONNECTED_SLAVES; j++) {
Wire.beginTransmission(j + 8);
Wire.write(currentFloor);
Wire.endTransmission();
}
}
/*********************** NON I2C CODE ***********************/
void debugArray() {
// Prints all the arrays to the terminal for debugging purposes
Serial.print("Array length is ");
Serial.println(sizeof(floorButtonUp) / sizeof(int));
Serial.println("Floor button up");
for (int i = 0; i < (sizeof(floorButtonUp) / sizeof(int)); i++) {
Serial.println(floorButtonUp[i]);
}
Serial.println("Floor button down");
for (int i = 0; i < (sizeof(floorButtonDown) / sizeof(int)); i++) {
Serial.println(floorButtonDown[i]);
}
Serial.println("Elevator button");
for (int i = 0; i < 6; i++) {
Serial.println(floorButtonElevator[i]);
}
}
//===============================================================
void keypadEvent(KeypadEvent liftKey) {
// In case of 0 till 4, set the place in the array corresponding to the floor to 1
// When the '*' is pressed, set the emergencyButton variable to 1, so the Elevator will stop
switch(liftKey){
case '0':
floorButtonElevator[0] = 1;
break;
case '1':
floorButtonElevator[1] = 1;
break;
case '2':
floorButtonElevator[2] = 1;
break;
case '3':
floorButtonElevator[3] = 1;
break;
case '4':
floorButtonElevator[4] = 1;
break;
case '*':
emergencyButton = 1;
break;
}
}
//=================================================================
void checkForMoveLift() {
// Main algorithm to check to where the lift should move
Serial.print("Check to see if current floor wants to use lift: ");
if ((floorButtonDown[currentFloor] || floorButtonUp[currentFloor] || floorButtonElevator[currentFloor]) && liftAvailable[currentFloor]) { // If there is a button pressed for the current floor and the lift is available
if (movingUp && (floorButtonUp[currentFloor] || floorButtonElevator[currentFloor])) {
// If lift is moving up and floorUp is pressed, stop at current floor
moveUp = false;
moveDown = false;
Serial.println("Current floor wants to use lift");
delay(floorStopTime);
floorButtonElevator[currentFloor] = 0; // If the elevator has stopped on the currentfloor, it doesn't has to stop there anymore, so set to 0
return;
} else if (!movingUp && (floorButtonDown[currentFloor] || floorButtonElevator[currentFloor])) {
// If lift is moving down and floorDown is pressed, stop at current floor
moveUp = false;
moveDown = false;
Serial.println("Current floor wants to use lift");
delay(floorStopTime);
floorButtonElevator[currentFloor] = 0; // If the elevator has stopped on the currentfloor, it doesn't has to stop there anymore, so set to 0
return;
} else if (movingUp) {
// if lift is moving up and buttonDown is pressed and there are no buttons pressed above me, stop at current floor
boolean stopHere = true;
for (int i = currentFloor + 1; i < (sizeof(floorButtonUp) / sizeof(int)); i++) {
if (floorButtonUp[i] || floorButtonDown[i] || floorButtonElevator[i]) {
stopHere = false;
break;
}
}
if (stopHere) {
moveUp = false;
moveDown = false;
Serial.println("Current floor wants to use lift");
delay(floorStopTime);
floorButtonElevator[currentFloor] = 0; // If the elevator has stopped on the currentfloor, it doesn't has to stop there anymore, so set to 0
return;
}
} else if (!movingUp) {
// if lift is moving down and buttonUp is pressed and there are no buttons pressed below me, stop at current floor
boolean stopHere = true;
for (int i = currentFloor - 1; i >= 0; i--) {
if (floorButtonUp[i] || floorButtonDown[i] || floorButtonElevator[i]) {
stopHere = false;
break;
}
}
if (stopHere) {
moveUp = false;
moveDown = false;
Serial.println("Current floor wants to use lift");
delay(floorStopTime);
floorButtonElevator[currentFloor] = 0; // If the elevator has stopped on the currentfloor, it doesn't has to stop there anymore, so set to 0
return;
}
} else {
Serial.println("current floor wants to go in a different direction, skipping floor");
}
} else {
Serial.println("Current floor does not want to use the lift");
}
Serial.print("Check for other floor wants to use lift: ");
if (movingUp) { // When the lift is moving up
// check floors above current floor to see if anyone wants to go up
for (int i = currentFloor; i < (sizeof(floorButtonUp) / sizeof(int)); i++) { // sizeof(int) used bacause arduino is a bitch https://www.arduino.cc/en/Reference/Sizeof
if (floorButtonUp[i] || floorButtonElevator[i]) {
Serial.println("A floor above me wants to go up");
moveUp = true;
moveDown = false;
movingUp = true;
return;
}
}
//====================================================================
// check floors above current floor to see if anyone wants to go down
for (int i = currentFloor; i < (sizeof(floorButtonUp) / sizeof(int)); i++) { // sizeof(int) used bacause arduino is a bitch https://www.arduino.cc/en/Reference/Sizeof
if (floorButtonDown[i] || floorButtonElevator[i]) {
Serial.println("A floor above me wants to go down");
moveUp = true;
moveDown = false;
movingUp = true;
return;
}
}
//=============================================================================
// check floor below current floor to see if anyone wants to go down
for (int i = currentFloor; i >= 0; i--) {
if (floorButtonDown[i] || floorButtonElevator[i]) {
Serial.println("A floor below me wants to go up");
moveUp = false;
moveDown = true;
movingUp = false;
return;
}
}
// check floors below current floor to see if anyone wants to go up
for (int i = currentFloor; i >= 0; i--) {
if (floorButtonUp[i] || floorButtonElevator[i]) {
Serial.println("A floor below me wants to go down");
moveUp = false;
moveDown = true;
movingUp = false;
return;
}
}
Serial.println("Nothing wants to use lift");
} else if (!movingUp) { // When the lift is moving down
// check floors below current floor to see if anyone wants to go up
for (int i = currentFloor; i >= 0; i--) {
if (floorButtonUp[i] || floorButtonElevator[i]) {
Serial.println("A floor below me wants to go up");
moveUp = false;
moveDown = true;
movingUp = false;
return;
}
}
// check floor below current floor to see if anyone wants to go down
for (int i = currentFloor; i >= 0; i--) {
if (floorButtonDown[i] || floorButtonElevator[i]) {
Serial.println("A floor below me wants to go down");
moveUp = false;
moveDown = true;
movingUp = false;
return;
}
}
//===============================================================
// check floors above current floor to see if anyone wants to go down
for (int i = currentFloor; i < (sizeof(floorButtonUp) / sizeof(int)); i++) {
if (floorButtonDown[i] || floorButtonElevator[i]) {
Serial.println("A floor above me wants to go down");
moveUp = true;
moveDown = false;
movingUp = true;
return;
}
}
//===============================================================
// check floors above current floor to see if anyone wants to go up
for (int i = currentFloor; i < (sizeof(floorButtonUp) / sizeof(int)); i++) {
if (floorButtonUp[i] || floorButtonElevator[i]) {
Serial.println("A floor above me wants to go up");
moveUp = true;
moveDown = false;
movingUp = true;
return;
}
}
}
Serial.println("Nothing wants to use lift");
moveUp = false;
moveDown = false;
}
void moveLift() {
// Controls the lift controller
if (moveUp) {
liftController(true);
} else if (moveDown) {
liftController(false);
}
}
void liftController(boolean up) {
// Controls how many the stepping motor should rotate
clockwise = !up;
if (emergencyButton) { // When the emergency button is pressed, stop moving the motor until the arduino resets
return;
}
for (int i = 0; i < 100; i++) {
// with this for loop the motor moves more between requests.
stepper();
delayMicroseconds(2000);
char liftKey = liftKeypad.getKey(); // Also check the input of the keypad while the elevator is moving
}
}
// http://www.nmbtc.com/step-motors/engineering/full-half-and-microstepping/
// Using two-phase fullstep
void stepper() {
// controls the steppenmotor
switch (steps) {
case 0:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
case 1:
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
break;
case 2:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, HIGH);
break;
case 3:
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
break;
default:
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
break;
}
if (clockwise) {
steps++;
} else {
steps--;
}
if (steps > 3) {
steps = 0;
} else if (steps < 0) {
steps = 3;
}
}
void lcdDisplayHandler(int currentFloor){
// Print the status of the elevator on the lcd screen
lcd.setCursor(0, 0);
lcd.print("Lift: ");
lcd.setCursor(6, 0);
if(moveUp){
lcd.print("Going Up ");
} else if(moveDown){
lcd.print("Going Down");
} else{
lcd.print("Idle ");
}
// Print the current floor on the lcd screen
lcd.setCursor(0, 1);
lcd.print("Current floor:");
lcd.setCursor(14, 1);
lcd.print(currentFloor);
}