/* LCD ---- Pin 1 on the LCD is the one closest to the corner. Start there and work your way up. 1 to GND 2 to 5V 3 to the 10K resistor, which is connected to ground 4 to Arduino digital pin 12 5 to GND 6 to Arduino digital pin 11 7 (no connection) 8 (no connection) 9 (no connection) 10 (no connection) 11 to Arduino digital pin 5 12 to Arduino digital pin 4 13 to Arduino digital pin 9 14 to Arduino digital pin 8 15 to 5V 16 to GND Rotary Encoder Pinouts (I don't think there is an necessary orientation?): ----------------------- Three pin Side: 1 to digital pin 3 2 to GND 3 to digital pin 2 Two pin side- 1 to digital pin 13 2 to digital pin 7, also 560 Ohm resistor connected to ground Limit Pin Door -------------- V to 5V S to digital pin 6 G to GND Limit Pin Home --------------- V to 5V S to digital pin 10 G to GND I2C Bus Slave Board Connection ------------------------------- A4 to other Slave Arduino's A4 A5 to Slave Arduino's A5 Slave GND must be connected to Master GND */ #include #include LiquidCrystal lcd(12,11,5,4,9,8); // Pins the LCD is using static int encoderPinA = 2; // Our first hardware interrupt pin is digital pin 2 static int encoderPinB = 3; // Our second hardware interrupt pin is digital pin 3 static int limitPinHome = 10; static int limitPinDoor = 6; static int buttonPin = 13; volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on encoderPinA to signal that the encoder has arrived at a detent volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on encoderPinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set) volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255 volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor) volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent int desiredPos = 0; bool b_selectedPos = 0; String homeStr = "Enter Position:"; bool STEPPER_COMPLETE = 0; int STEPPER_MSG = 0; void setup() { Serial.begin(9600); // start the serial monitor link Wire.begin(); // To talk to Arduino #2 via I2C Bus // The LiquidCrystal library can be used with many different // LCD sizes. We're using one that's 2 lines of 16 characters, // so we'll inform the library of that: lcd.begin(16, 2); // Data sent to the display will stay there until it's // overwritten or power is removed. This can be a problem // when you upload a new sketch to the Arduino but old data // remains on the display. Let's clear the LCD using the // clear() command from the LiquidCrystal library: lcd.clear(); lcd.print(homeStr); lcd.setCursor(0,1); // Set cursor to column 0, line 1 (2nd row) lcd.print("HOME"); pinMode(buttonPin, OUTPUT); digitalWrite(buttonPin, HIGH); pinMode(encoderPinA, INPUT_PULLUP); // set encoderPinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases) pinMode(encoderPinB, INPUT_PULLUP); // set encoderPinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases) attachInterrupt(0,EncoderPinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below) attachInterrupt(1,EncoderPinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below) } void EncoderPinA(){ cli(); //stop interrupts happening before we read pin values reading = PIND & 0xC; // read all eight pin values then strip away all but encoderPinA and encoderPinB's values if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge encoderPos --; //decrement the encoder's position count bFlag = 0; //reset flags for the next turn aFlag = 0; //reset flags for the next turn } else if (reading == B00000100) bFlag = 1; //signal that we're expecting encoderPinB to signal the transition to detent from free rotation sei(); //restart interrupts } void EncoderPinB(){ cli(); //stop interrupts happening before we read pin values reading = PIND & 0xC; //read all eight pin values then strip away all but encoderPinA and encoderPinB's values if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge encoderPos ++; //increment the encoder's position count bFlag = 0; //reset flags for the next turn aFlag = 0; //reset flags for the next turn } else if (reading == B00001000) aFlag = 1; //signal that we're expecting encoderPinA to signal the transition to detent from free rotation sei(); //restart interrupts } void confirmDesiredPos(int desired_pos) { bool b_optionSelected = 0; delay(1000); // must add delay after every selection or logic doesn't work lcd.clear(); lcd.print("Pos " + (String) desired_pos + " selected:"); lcd.setCursor(0,1); lcd.print(" "); while (!b_optionSelected) { int contButtonState = digitalRead(7); lcd.setCursor(0,1); if ((encoderPos % 2) == 0) { lcd.print("Continue"); if (contButtonState == HIGH) { b_selectedPos = 1; desiredPos = desired_pos; b_optionSelected = 1; delay(1000); } } else { lcd.print("Go Back "); if (contButtonState == HIGH) { lcd.clear(); lcd.print(homeStr); b_optionSelected = 1; delay(1000); } } } } void studentAuthorization() { delay(1000); bool b_bitChecked = 0; String authStr = "Click to confirm you will scan bit after wheel moves."; while (!b_bitChecked) { lcd.clear(); lcd.setCursor(0,0); lcd.print(authStr.substring(0,16)); lcd.setCursor(0,1); lcd.print(authStr.substring(17,32)); // Have to use timer here while displaying msg instead of delay so you can still read incoming button state int contButtonState = LOW; long time1 = millis(); long time2 = millis(); while (time2 - time1 < 2000 & contButtonState == LOW) { contButtonState = digitalRead(7); time2 = millis(); } lcd.clear(); lcd.setCursor(0,0); lcd.print(authStr.substring(32, 47)); lcd.setCursor(0,1); lcd.print(authStr.substring(47, authStr.length())); time1 = millis(); while (time2 - time1 < 2000 & contButtonState == LOW) { contButtonState = digitalRead(7); time2 = millis(); Serial.println(time2 - time1); } if (contButtonState == HIGH) { b_selectedPos = 1; b_bitChecked = 1; delay(1000); } } } int checkEncoderPosition(){ if(!b_selectedPos & oldEncPos != encoderPos) { //Serial.println(encoderPos); lcd.print(" "); // Erase the largest possible number lcd.setCursor(0,1); //lcd.print(int (encoderPos*30/256)); // Map values between 0-30 as opposed to 0-255 lcd.print(encoderPos); oldEncPos = encoderPos; } } bool b_door_opened = 0; void loop() { checkEncoderPosition(); int buttonState = digitalRead(7); if (buttonState == HIGH) { // if position selected confirmDesiredPos(encoderPos); // confirm this is the actual position they wanted } if (b_selectedPos == 1) { // if user confirmed position is correct studentAuthorization(); // verify that they have used the checkout system // Function: Send to Stepper lcd.clear(); lcd.print("Moving... "); while (!STEPPER_COMPLETE) { if (b_door_opened == 0) { STEPPER_MSG = (int) desiredPos; // Send desired position Wire.beginTransmission(9); // transmit to device #9 Wire.write(STEPPER_MSG); // Tell Stepper to Start Wire.endTransmission(); // stop transmitting } if (digitalRead(limitPinDoor) == 1) { lcd.setCursor(0,0); lcd.print("Door Opened"); b_door_opened = 1; // if (digitalRead(limitPinDoor == 0)) { // Wire.write( // } } else if (digitalRead(limitPinHome) == 0 and b_door_opened == 1) { STEPPER_COMPLETE = 1; // Wire.write(-1); // -1 Message Tells the Stepper it is home. } else if (digitalRead(limitPinDoor) == 0 & b_door_opened == 1) { lcd.setCursor(0,0); lcd.print("Returning Home... "); Wire.beginTransmission(9); // transmit to device #9 Wire.write(0); // 0 Tells stepper to turn left until it is home Wire.endTransmission(); // stop transmitting } } STEPPER_COMPLETE = 0; b_selectedPos = 0; b_door_opened = 0; lcd.clear(); lcd.print(homeStr); } }