«SCAN-IT»

Autores:

Erik Fernández Orgaz

Alejandro Herrera González

Adrián Leonis García

EscanerFotoGeneral
Imagen final del «Scan-It»

Introducción del proyecto

Nuestro proyecto se basa en un escáner 3d con varias funcionalidades las cuales son: escáner, cinemática y control manual.

La implementación se ha llevado acabo con: varias piezas impresas en 3d como estructura del proyecto, una placa Arduino uno R3, regulador de voltaje DC-DC, bluetooth hc-06, motor paso a paso, driver controlador motor paso a paso, lcd 16×2, modulo I2C y módulo joystick.


Implementación

LCD y Joystick

Primero empezamos viendo como presentar la interfaz a través del módulo lcd, una vez que lo tuvimos claro, la implementación se llevó a cabo de la siguiente manera: Al tener el modulo I2C se utilizaron los pines A4 y A5, se utilizaron estos pines porque son los que viene por defecto en Arduino uno R3 para SCL y SDA que son las conexiones de comunicación que salían del módulo I2C. La librería que se utilizó fue LiquidCrystal_I2C.

Seguimos por cómo implementar la navegación del menú con el módulo joystick en función de los valores que se obtenían.  En este caso la conexión del switch que tenía el módulo joystick se conectó al pin 8 digital y se configuró como pin de entrada y a un valor alto, los pines de los ejes X e Y se conectaron a los pines A0 y A1 porque los valores que podrían tomar no son 0 ó 1 sino que están entre varios rangos y para poder controlarlos se necesitaba una señal analógica.

LCD_Joystick
LCD y Joystick
Problemas encontrados

El número de conexiones hacía la placa era muy elevado, esto, se subsano instalando un módulo i2c para el lcd y así minimizar el número de conexiones.

Apartado desarrollado por Alejandro Herrera González

Motor Paso a Paso y Driver

De esta parte se encargó Adrián Leonis García, pero cuando surgieron los problemas a la hora de combinar el módulo lcd y el motor paso a paso con el driver, buscamos una solución entre los tres integrantes del grupo ya que nos costó bastante poder encontrar el camino a la solución.

Una vez realizado estos dos pasos nos pusimos en marcha con el motor paso a paso y el driver controlador del mismo. Primero hicimos una demo para ver como funcionaba, una vez que entendimos como funcionaba hicimos la relación de pasos con los engranajes que teníamos, en este caso fue con prueba error hasta que se consiguió. Cuando quisimos juntos lo que teníamos realizado del lcd y el motor nos dimos cuenta que el módulo lcd empezaba a parpadear cuando giraba el motor. Esto nos llevó un tiempo darnos cuenta cómo solucionarlo y mucha búsqueda en internet. La solución que implementamos fue sacar el voltaje de la energía suministrada por el Arduino en este caso 9v y pasarlo por un regulador de voltaje que convirtiera de 9v a 5v necesarios para el driver del motor paso a paso.

Problemas encontrados

La tensión demandada era muy elevada para poder combinarlo con el lcd se solucionó este problema implementando un regulador de voltaje DC-DC el cual suministra la tensión al driver.

MotorPasoAPasoDriver
Motor Paso a Paso y Driver

Módulo Bluetooth

Parte realizada por:  Erik Fernández Orgaz.

Ahora ya solo nos quedaba el módulo bluetooth que tras una búsqueda exhaustiva por internet nos dimos cuenta que los comandos AT por los que se regía el módulo bluetooth no nos valía para la implementación que queríamos realizar. Encontramos un GitHub que podía flashear el módulo haciéndolo pasar de un hc-06 a módulo rn-42 de mejores prestaciones y con las funcionalidades que necesitábamos. Una vez llevado a cabo esta operación tuvimos el problema de cómo comunicarnos con el módulo, nos dimos cuenta que el módulo trabaja con 3.3 voltios el pin de recepción, esto se resolvió con un divisor de tensión con resistencias de 1k ohm y 2k ohm.

Bluetooth
Bluetooth HC-06
Problemas encontrados

Los comandos reconocidos por el módulo no eran suficiente para lo que necesitábamos, la solución fue flashear el módulo para que por firmware fuera un dispositivo rn-42 esto se llevó a cabo con la ayuda de un módulo ftdi-usb en el cual se soldaron los pines del módulo ftdi-usb RTS,RSD,RI y DTR a los pines CLK, MISO, MOSI y CSB del módulo bluetooth respectivamente de la siguiente forma:

ComunicacionBluetooth

Esto nos permitió poder iniciar una comunicación del dispositivo hc-06 al ordenador y con la utilización de las aplicaciones Bluesuite y Pstool se pudo llevar acabo el flasheo del dispositivo.

Una vez realizado este paso faltaba configurar el dispositivo para que simulara un teclado y poder utilizar la tecla «enter» para que hiciera una foto desde la aplicación nativa de la cámara del teléfono, esto se llevó a cabo con ayuda de la librería BPLib referenciada en la bibliografía de la presentación hecha.


Esquema general de conexiones

EsquemaGeneralComponentes
Esquema de conexiones

Código del Software

#include <LiquidCrystal_I2C.h>  // RH - use this library for LCD displays with I2C backpack
#include <Stepper.h>
#include <SoftwareSerial.h>

const int SW_pin = 8; // digital pin connected to switch output
const int X_pin = A0; // analog pin connected to X output
const int Y_pin = A1; // analog pin connected to Y output

int bluetoothTx = 2;  // TX-O pin of bluetooth mate, Arduino D2
int bluetoothRx = 3;  // RX-I pin of bluetooth mate, Arduino D3

int MenuNr = 0;   // Menu number
int PhotoNr = 2;  // The amount of photos that have to be taken
bool Flag1 = 0;   // This flag is only active during 1 program cycle (prevents constantly adding/subtracting 1 to the menu number when the joystick is pushed to the side) 
bool Flag2 = 0;   // This flag is only active during 1 program cycle (prevents constantly adding/subtracting 2 to the photo number when the joystick is pushed up or down)
bool Flag3 = 0;   // This flag is only active during 1 program cycle (prevents constantly adding/subtracting 1 to the RPM when the joystick is pushed up or down)
bool Flag4 = 0;   // This flag is only active during 1 program cycle (prevents constantly adding/subtracting 1 to the turn number when the joystick is pushed to the side)
bool Flag5 = 0;   // This flag is only active during 1 program cycle (prevents constantly adding/subtracting 1 to the RPM when the joystick is pushed up or down)
bool Flag6 = 0;   // This flag is only active during 1 program cycle to clear the lcd
int SwMenu = 0;   // Switch menu (Sub menu's in the main menu's)
bool BtnFlag = 0; // This flag is only active during 1 program cycle (prevents constantly adding of 1 to SwMenu when button is pressed)

// RH - added variables for fast change & cancel modes
int FastChng = 0;  // indicates fast change value mode.  0 = off, 1 = delay mode, 2 = fast changing mode
const unsigned long FastDelay = 1000;  // delay mode time (before values change fast)
const unsigned long ShortInt = 100;  // short fast change interval
const unsigned long LongInt = 300;  // long fast change interval
const unsigned long BtnDelay = 2000;  // delay for button press to cancel operations.  Note this is an approximate delay, since stepper motor
                                     // suspends all program execution until motor finishes its move
unsigned long SetTime = 0; // time value for fast change & button cancel modes.  Used to calculate time intervals
bool BtnCancelFlag = 0; // This flag is used to detect when button is pressed for canceling operations
bool MaxSwMenu = 0;  // This flag is used for detecting when the maximum SwMenu is reached
bool CinCancelFlag = 0;  // This flag is used to trigger cinematic cancel.  1 = cancel cinematic operation
int StepPoll = 480;  // number of motor steps to poll for cinematic cancel (at 15 rpm)
int Cntr = 0;  // step counter for cinematic motor cancel
// RH - end of added variables

const int stepsPerRevolution = 2048;  // change this to fit the number of steps per revolution
int FullRev = 14336;                  // 1 full revolution of the big gear -> Small-Big gear ratio is 7:1
int rolePerMinute = 15;               // Adjustable range of 28BYJ-48 stepper is 0~17 rpm
int PhotoTaken = 0;                   // Amount of photo's that have been taken
int StepPerPhoto;                     // Amount of steps per photo (calculated -> see MenuNr 0/SwMenu 2)
int TurnNr = 1;                       // Amount of turns
int CurrentTurn = 0;                  // Stores current turn number
int Steps = 0;                        // Amount of individual steps the stepper motor has to turn

LiquidCrystal_I2C lcd(0x27, 16, 2);  // RH - use this for I2C LCD.  Assumes default address of 0x27
Stepper myStepper(stepsPerRevolution, 9, 11, 10, 12);  // Use these pins for the stepper motor
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);


void setup() {
  
  bluetooth.begin(115200);  // The Bluetooth Mate defaults to 115200bps
  delay(100);

  bluetooth.print("$$$");
  delay(100);
  
  bluetooth.println("C");
  delay(100);
  
  bluetooth.println("U,9600,N");
  delay(100);
  
  bluetooth.begin(9600);
  
  lcd.init();                         // RH - I2C LCD init command
  lcd.backlight();                    // RH - I2C LCD turn backlight on
  pinMode(SW_pin, INPUT);             //Set pushbutton as input
  digitalWrite(SW_pin, HIGH);         //Set SW_pin High
  
  myStepper.setSpeed(rolePerMinute);  //Set RPM of steppermotor

  lcd.setCursor(4, 0);                //Startup screen start
  lcd.print("Welcome!");              //      """""      //
  lcd.setCursor(1, 1);                //      """""      //
  lcd.print("Software: V1.6");        //      """""      //
  delay(3000);                        //      """""      //
  lcd.clear();                        //      """""      //
  lcd.setCursor(0, 0);                //      """""      //
  lcd.print("Designed by");           //      """""      //
  lcd.setCursor(0, 1);                //      """""      //
  lcd.print("Erik,Alejandro,Adrian");         //      """""      //
  delay(2000);                        //      """""      //
  lcd.clear();                        //Startup screen end
}

void loop() {

  int XValue = analogRead(X_pin);     // Read the analog value from The X-axis from the joystick
  int YValue = analogRead(Y_pin);     // Read the analog value from The Y-axis from the joystick
  int SwValue = digitalRead(SW_pin);  // Read the digital value from The Button from the joystick

  if (MenuNr < 0){  //This sets the min number of menu's
    MenuNr = 0;
  }
  else if ( MenuNr > 2){  //This sets the max numbers of menu's
    MenuNr = 2;
  }
  
  if (XValue < 400 && Flag1 == 0 && SwMenu == 0){  //if the joystick is pushed to the right side and flag1 is 0 then 1 will be added to the menu number (purpose of the flag -> see comment Flags above)
    MenuNr = MenuNr + 1; 
    Flag1 = 1;
    lcd.clear();
  }

  if (XValue > 600 && Flag1 == 0 && SwMenu == 0){  //if the joystick is pushed to the left side and flag1 is 0 then 1 will be subtracted from the menu number (purpose of the flag -> see comment Flags above)
    MenuNr = MenuNr - 1;
    Flag1 = 1;
    lcd.clear();
  }
  
  if (XValue > 399 && XValue < 599 && Flag1 == 1){  //if joystick is at neutral possition, flag1 is set to 0 (purpose of the flag -> see comment Flags above)
    Flag1 = 0;
  }


  if (SwValue == 0 && BtnFlag == 0 && MaxSwMenu == 0){  //if the button is pressed and the flag is 0 -> add 1 to menu 
    SwMenu = SwMenu + 1;
    BtnFlag = 1;
    BtnCancelFlag = 0;
    lcd.clear();
  }

  if (SwValue == 1 && BtnFlag == 1){  //if the button is not pressed and the flag is 0 -> Reset the flag (purpose of the flag -> see comment Flags above)
    BtnFlag = 0;
  }
  


  switch (MenuNr){
    case 0: //***********************************************Menu0***********************************************//
            if (SwMenu == 0){ //Menu 0 selected
              lcd.setCursor(3, 0);
              lcd.print("Escaner");
              lcd.setCursor(14,0);
              lcd.print("->");
            }
          
            if (SwMenu == 1){ //entered menu 0
              lcd.setCursor(0, 0);
              lcd.print("Nr of photo's");
              lcd.setCursor(7, 1);
              lcd.print(PhotoNr);
        
              if (FastChng == 0) {  // RH - if not in fast change mode, update set time
                SetTime = millis();
              }
              
              if (YValue < 400 && Flag2 == 0){ //joystick up -> Add 2 to number of photo's
                PhotoNr = PhotoNr + 2;
                Flag2 = 1;
                FastChng = 1;
                lcd.clear();
              }
              if (YValue > 600 && Flag2 == 0){ //joystick down -> Subtract 2 from number of photo's
                PhotoNr = PhotoNr - 2;
                Flag2 = 1;
                FastChng = 1;
                lcd.clear();
              }
              if (YValue > 399 && YValue < 599 && Flag2 == 1){  //if the Y-axis is back at it's neutral possition -> Flag3 = 0 -> Prevents constant adding or subtracting of 2
                Flag2 = 0;
                FastChng = 0;
              }
        
              if (YValue < 400 && FastChng == 1) {  // RH - if joystick up is held for > the fast delay time, then enter fast change mode
                if ((millis() - SetTime) > FastDelay) {
                  FastChng = 2;
                  SetTime = millis();  // update the set time
                }
              }
        
              if (YValue > 600 && FastChng == 1) {  // RH - if joystick down is held for > the fast delay time, then enter fast change mode
                if ((millis() - SetTime) > FastDelay) {
                  FastChng = 2;
                  SetTime = millis();  // update the set time
                }
              }
        
              if (YValue < 400 && FastChng == 2) {  // RH - we are in fast change mode, so we want to update the values quickly, proportional between
                if ((millis() - SetTime) > (LongInt - (400 - YValue) * (LongInt - ShortInt) / 400)) {  // ShortInt and LongInt based on joystick deflection
                  PhotoNr = PhotoNr + 2;
                  SetTime = millis();
                  lcd.clear();
                }
              }
        
              if (YValue > 600 && FastChng == 2) {  // RH - same for joystick down in fast change mode
                if ((millis() - SetTime) > (LongInt - (YValue - 600) * (LongInt - ShortInt) / 400)) {
                  PhotoNr = PhotoNr - 2;
                  SetTime = millis();
                  lcd.clear();
                }
              }
        
              if (PhotoNr < 2){    //Min allowable Nr of photo's
                PhotoNr = 2;
              }
              if (PhotoNr > 200){  //Max allowable Nr of photo's
                PhotoNr = 200;
              }
            }
        
            if (SwMenu == 2){ //Program started
        
              MaxSwMenu = 1;
              
              lcd.setCursor(0, 0);
              lcd.print("Program started");
              lcd.setCursor(0, 1);
              lcd.print("Photo Nr: ");
              lcd.print(PhotoTaken);
              
              StepPerPhoto = FullRev / PhotoNr;  //Calculate amount of steps per photo
        
              if (PhotoTaken < PhotoNr){          
              myStepper.setSpeed(rolePerMinute);  //Set motor speed
              myStepper.step(StepPerPhoto);       //move the calculated amount of steps
              PhotoTaken = PhotoTaken + 1;        //Add 1 to photos taken
              lcd.setCursor(0, 1);
              lcd.print("Photo Nr: ");            //Taking photo's
              lcd.print(PhotoTaken);
              delay(100);
              bluetooth.println();                //Take a photo simulating press key enter
              delay(10000);
              }
        
              if (PhotoTaken == PhotoNr){  //If the amount of photos taken is equal to the amount of photos that have to be taken -> Program finished
                lcd.setCursor(0, 0);
                lcd.print("Program finished");
                delay(3000);
                lcd.clear();  //Rest parameters
                PhotoTaken = 0;
                PhotoNr = 2;
                SwMenu = 0;
                MaxSwMenu = 0;
                Steps = 0;
              }
        
              // RH NOTE - cancelling works but delay is longer than expected since stepper motor movement is blocking
              if (SwValue == 0 && BtnCancelFlag == 0) {  // if button is pressed, start timing for cancel
                BtnCancelFlag = 1;
                SetTime = millis();
              }
        
              if (SwValue == 1 && BtnCancelFlag == 1) {  // RH - if button released before BtnDelay, then reset flag
                BtnCancelFlag = 0;
              }
        
              if (SwValue == 0 && BtnCancelFlag == 1 && ((millis() - SetTime) > BtnDelay)) {  // RH - button has been held for > BtnDelay, so cancel operation
                lcd.clear();
                lcd.setCursor(0, 0);
                lcd.print("Program cancel");
                delay(3000);
                lcd.clear();
                PhotoTaken = 0;
                PhotoNr = 2;
                SwMenu = 0;
                MaxSwMenu = 0;
                Steps = 0;
                BtnCancelFlag = 0;
              }
            }   
          break;
          
    case 1:  //***********************************************Menu1***********************************************//
            if (SwMenu == 0){  //Menu1 selected
                lcd.setCursor(0,0);
                lcd.print("<-");
                lcd.setCursor(3, 0);
                lcd.print("Cinematica");
                lcd.setCursor(14,0);
                lcd.print("->");
                CinCancelFlag = 0;
                Cntr = 0;
              }
          
              if (SwMenu == 1){  //Entered menu1 - sub menu1
                lcd.setCursor(0, 0);
                lcd.print("motor speed");
                lcd.setCursor(7, 1);
                lcd.print(rolePerMinute);
          
                if (FastChng == 0) {  // RH - if not in fast change mode, update set time
                  SetTime = millis();
                }
                
                if (YValue < 400 && Flag3 == 0){ // joystick up -> Add 1 RPM
                  rolePerMinute = rolePerMinute + 1;
                  Flag3 = 1;
                  FastChng = 1;
                  lcd.clear();
                }
                if (YValue > 600 && Flag3 == 0){ // joystick down -> Subtract 1 RPM
                  rolePerMinute = rolePerMinute - 1;
                  Flag3 = 1;
                  FastChng = 1;
                  lcd.clear();
                }
                if (YValue > 399 && YValue < 599 && Flag3 == 1){  //if the Y-axis is back at it's neutral possition -> Flag3 = 0 -> Prevents constant adding or subtracting of 1
                  Flag3 = 0;
                  FastChng = 0;
                }
          
                if (YValue < 400 && FastChng == 1) {  // RH - if joystick up is held for > the fast delay time, then enter fast change mode
                  if ((millis() - SetTime) > FastDelay) {
                    FastChng = 2;
                    SetTime = millis();  // update the set time
                  }
                }
          
                if (YValue > 600 && FastChng == 1) {  // RH - if joystick down is held for > the fast delay time, then enter fast change mode
                  if ((millis() - SetTime) > FastDelay) {
                    FastChng = 2;
                    SetTime = millis();  // update the set time
                  }
                }
          
                if (YValue < 400 && FastChng == 2) {  // RH - we are in fast change mode, so we want to update the values at the LongInt interval
                  if ((millis() - SetTime) > LongInt) {  // (using fixed LongInt since not that many values to cycle through)
                    rolePerMinute = rolePerMinute + 1;
                    SetTime = millis();
                    lcd.clear();
                  }
                }
          
                if (YValue > 600 && FastChng == 2) {  // RH - same for joystick down in fast change mode
                  if ((millis() - SetTime) > LongInt) {
                    rolePerMinute = rolePerMinute - 1;
                    SetTime = millis();
                    lcd.clear();
                  }
                }
                
                if (rolePerMinute < 1){  //Min allowable RPM
                  rolePerMinute = 1;
                }
                if (rolePerMinute > 17){  //Max allowable RPM
                  rolePerMinute = 17;
                }
              }
          
              if (SwMenu == 2){  //Entered menu1 - sub menu2
                lcd.setCursor(0, 0);
                lcd.print("Nr of turns");
                lcd.setCursor(7, 1);
                lcd.print(TurnNr);
          
                if (FastChng == 0) {  // RH - if not in fast change mode, update set time
                  SetTime = millis();
                }
                
                if (YValue < 400 && Flag4 == 0){ // joystick up -> Add 1 turn
                  TurnNr = TurnNr + 1;
                  Flag4 = 1;
                  FastChng = 1;
                  lcd.clear();
                }
                if (YValue > 600 && Flag4 == 0){ // joystick down -> Subtract 1 turn
                  TurnNr = TurnNr - 1;
                  Flag4 = 1;
                  FastChng = 1;
                  lcd.clear();
                }
                if (YValue > 399 && YValue < 599 && Flag4 == 1){  //if the Y-axis is back at it's neutral possition -> Flag3 = 0 -> Prevents constant adding or subtracting of 1
                  Flag4 = 0;
                  FastChng = 0;
                }
          
                if (YValue < 400 && FastChng == 1) {  // RH - if joystick up is held for > the fast delay time, then enter fast change mode
                  if ((millis() - SetTime) > FastDelay) {
                    FastChng = 2;
                    SetTime = millis();  // update the set time
                  }
                }
          
                if (YValue > 600 && FastChng == 1) {  // RH - if joystick down is held for > the fast delay time, then enter fast change mode
                  if ((millis() - SetTime) > FastDelay) {
                    FastChng = 2;
                    SetTime = millis();  // update the set time
                  }
                }
          
                if (YValue < 400 && FastChng == 2) {  // RH - we are in fast change mode, so we want to update the values quickly, proportional between
                  if ((millis() - SetTime) > (LongInt - (400 - YValue) * (LongInt - ShortInt) / 400)) {  // ShortInt and LongInt based on joystick deflection
                    TurnNr = TurnNr + 1;
                    SetTime = millis();
                    lcd.clear();
                  }
                }
          
                if (YValue > 600 && FastChng == 2) {  // RH - same for joystick down in fast change mode
                  if ((millis() - SetTime) > (LongInt - (YValue - 600) * (LongInt - ShortInt) / 400)) {
                    TurnNr = TurnNr - 1;
                    SetTime = millis();
                    lcd.clear();
                  }
                }
                
                if (TurnNr < 1){  //Min allowable amount of turns
                  TurnNr = 1;
                }
                if (TurnNr > 200){  //Max allowable amount of turns
                  TurnNr = 200;
                }
              }
          
              if (SwMenu == 3){  //Program started
                MaxSwMenu = 1;
                StepPoll = 32 * rolePerMinute;  // RH - set polling rate StepPoll = number of steps per second (roughly)
                lcd.setCursor(0, 0);
                lcd.print("Program started");
                lcd.setCursor(0, 1);
                lcd.print("Turns done: ");
                lcd.print(CurrentTurn);
          
                if (CurrentTurn < TurnNr){ 
                  myStepper.setSpeed(rolePerMinute);
                  Cntr = 0;  // RH - initialize step counter
                  while ((Cntr <= FullRev) && (CinCancelFlag == 0)) { 
                    myStepper.step(StepPoll);  // RH - breaking up plate rotation into roughly 1 sec intervals to check for cancel
                    Cntr = Cntr + StepPoll;
                    SwValue = digitalRead(SW_pin);
                    if (SwValue == 0 && BtnCancelFlag == 0) {  // RH - check if button is pressed, if so start timing for cancel
                      BtnCancelFlag = 1;
                      SetTime = millis();
                    }
                    if (SwValue == 1 && BtnCancelFlag == 1) {  // RH - if button released before BtnDelay, then reset button flag
                      BtnCancelFlag = 0;
                    }
                    if (SwValue == 0 && BtnCancelFlag == 1 && ((millis() - SetTime) > BtnDelay)) {  // RH - button has been held for > BtnDelay, so cancel operation
                      CinCancelFlag = 1;
                      CurrentTurn = TurnNr;  
                    }
                  }
                  if (CinCancelFlag == 0) {  // RH - operation not cancelled, so continue
                    myStepper.step(FullRev + StepPoll - Cntr);  // RH - need to move remainder of steps for 1 full turn due to kickout from while loop
                    CurrentTurn = CurrentTurn + 1;
                    lcd.setCursor(0, 1);
                    lcd.print("Turns done: ");
                    lcd.print(CurrentTurn);
                  }
                }
          
                if (CurrentTurn == TurnNr){  //If the current turn is equal to the amount of thurns that need to be turned -> program finished (RH - or cancelled)
                  lcd.setCursor(0, 0);
                  if (CinCancelFlag == 0) {
                    lcd.print("Program finished");
                  }
                  else {
                    lcd.clear();
                    lcd.print("Program cancel");
                  }
                  delay(3000);
                  lcd.clear();  //Reset
                  CurrentTurn = 0;
                  PhotoNr = 1;
                  rolePerMinute = 15;
                  SwMenu = 0;
                  MaxSwMenu = 0;
                  CinCancelFlag = 0;
                  Steps = 0;
                }
              }
              break;
              
    case 2: //***********************************************Menu2***********************************************//
          if (SwMenu == 0){
            lcd.setCursor(0,0);
            lcd.print("<-");
            lcd.setCursor(3, 0);
            lcd.print("Manual");
            lcd.setCursor(3,1);
            lcd.print("control");
          }
      
           if (SwMenu == 1){  //Entered menu2
            lcd.setCursor(0, 0);
            lcd.print("motor speed");
            lcd.setCursor(7, 1);
            lcd.print(rolePerMinute);
      
            if (FastChng == 0) {  // RH - if not in fast change mode, update set time
              SetTime = millis();
            }
            
            if (YValue < 400 && Flag5 == 0){ // joystick up -> Add 1 RPM
              rolePerMinute = rolePerMinute + 1;
              Flag5 = 1;
              FastChng = 1;
              lcd.clear();
            }
            if (YValue > 600 && Flag5 == 0){ // joystick down -> Subtract 1 RPM
              rolePerMinute = rolePerMinute - 1;
              Flag5 = 1;
              FastChng = 1;
              lcd.clear();
            }
            if (YValue > 399 && YValue < 599 && Flag5 == 1){  //if the Y-axis is back at it's neutral possition -> Flag3 = 0 -> Prevents constant adding or subtracting of 1
              Flag5 = 0;
              FastChng = 0;
            }
      
            if (YValue < 400 && FastChng == 1) {  // RH - if joystick up is held for > the fast delay time, then enter fast change mode
              if ((millis() - SetTime) > FastDelay) {
                FastChng = 2;
                SetTime = millis();  // update the set time
              }
            }
      
            if (YValue > 600 && FastChng == 1) {  // RH - if joystick down is held for > the fast delay time, then enter fast change mode
              if ((millis() - SetTime) > FastDelay) {
                FastChng = 2;
                SetTime = millis();  // update the set time
              }
            }
      
            if (YValue < 400 && FastChng == 2) {  // RH - we are in fast change mode, so we want to update the values at the LongInt interval
              if ((millis() - SetTime) > LongInt) {  // (using fixed LongInt since not that many values to cycle through)
                rolePerMinute = rolePerMinute + 1;
                SetTime = millis();
                lcd.clear();
              }
            }
      
            if (YValue > 600 && FastChng == 2) {  // RH - same for joystick down in fast change mode
              if ((millis() - SetTime) > LongInt) {
                rolePerMinute = rolePerMinute - 1;
                SetTime = millis();
                lcd.clear();
              }
            }
            
            if (rolePerMinute < 1){  //Min allowable RPM
              rolePerMinute = 1;
            }
            if (rolePerMinute > 17){  //Max allowable RPM
              rolePerMinute = 17;
            }
      
            if (XValue > 400 ){  //if the joystick is pushed to the right side and the neutral flag is 0 then 1 will be added to the menu number (purpose of the flag -> see comment Flag1 above)
              Steps = Steps + 1;
              myStepper.setSpeed(rolePerMinute);
              myStepper.step(Steps);
              lcd.setCursor(14, 1);
              lcd.print("<-");
              Flag6 = 1;
            }
      
            if (XValue < 600 ){  //if the joystick is pushed to the left side and the neutral flag is 0 then 1 will be subtracted from the menu number (purpose of the flag -> see comment Flag1 above)
              Steps = Steps + 1;
              myStepper.setSpeed(rolePerMinute);
              myStepper.step(-Steps);
              lcd.setCursor(0, 1);
              lcd.print("->");
              Flag6 = 1;
            }
      
            if (XValue > 399 && XValue < 599){  //if the Y-axis is back at it's neutral possition -> Flag3 = 0 -> Prevents constant adding or subtracting of 1
              Steps = 0;
              if (Flag6 == 1){
                lcd.clear();
                Flag6 = 0;  //This flag is only active during 1 program cycle to clear the lcd
              }
            }
           }
      
           if (SwMenu == 2){  //Leave menu 2 when button is pressed
             lcd.clear();
             CurrentTurn = 0;
             PhotoNr = 1;
             rolePerMinute = 15;
             SwMenu = 0;
             Steps = 0;
           }
           break;
           
    default:
           break;       
  }
  
}

Limitaciones

  • El modelo 3D final conlleva un nivel de comprensión de modelaje 3D elevado junto con acceso a aplicaciones externas de la calidad requerida para el proceso.
  • Podría haber una futura implementación en la cual automatizáramos la grabación del vídeo.
  • La única compatibilidad es con dispositivos Android.
  • El tamaño y peso de los objetos es limitado debido a que nuestro modelo es «casero».

Reparto de tareas

La implementación hardware de todo el conjunto se encargó Erik Fernández Orgaz, de la creación del PowerPoint de presentación Adrián Leonis García y de la creación de esta Memoria Alejandro Herrera González.


Presupuesto

ComponentesPrecio
Módulo LCD 16×2 con módulo I2C6 €
Motor paso a paso0 €
Driver0 €
Módulo Bluetooth hc-0610 €
Regulador de voltaje5 €
Módulo FTDI-USB5 €
Piezas impresas en 3D0 €
TOTAL26 €

Vídeos de los Casos de Uso

Funcionalidad del Modo Escáner
Funcionalidad del Modo Cinemática
Funcionalidad del Modo de Control Manual

Vídeo Explicativo «Scan-It»


Material Extra

Vídeo de la presentación PowerPoint de apoyo

Bibliografía

https://www.youtube.com/watch?v=y8PcNbAA6AQ  (Flash Hc-06)

https://github.com/lorf/csr-spi-ftdi  (Software para Flash)

https://github.com/witnessmenow/BPLib  (Comandos de configuración RN-42)

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *