Está en la página 1de 21

UNIVERSIDAD AGRARIA DEL ECUADOR

FACULTAD DE CIENCIAS AGRARIAS

ING. EN CIENCIAS DE LA COMPUTACIÓN

TEMA:
RELOJ DE ARENA DIGITAL CON ARDUINO NANO

AUTORES:
MELO DIAZ KARLA ALEJANDRA
BONILLA ALCOCER EMPERATRIZ LISBETH
MALDONADO POLIT SEBASTIÁN EDUARDO
LEMA LLUCO BLANCA ALICIA
PILLIGUA CERCADO JHON STEVEN

GUAYAQUIL-ECUADOR
2023-2024
INTRODUCCIÓN
En este proyecto, presentaremos la creación de un reloj de arena utilizando Arduino
Nano, una plataforma de desarrollo de código abierto que nos permite programar y
controlar dispositivos electrónicos. Un reloj de arena es un instrumento simple pero
fascinante, utilizado durante siglos para medir el tiempo de manera visual. A través
de este proyecto, combinaremos la tecnología moderna con la belleza clásica de un
reloj de arena para crear una pieza única y funcional.

El Arduino Nano es una placa compacta y poderosa que nos brinda la capacidad de
controlar componentes electrónicos de manera precisa. Utilizaremos esta placa
junto con otros elementos, como sensores, un motor y una pantalla, para simular la
acción de un reloj de arena en tiempo real.

El objetivo de este proyecto es desarrollar un dispositivo que nos permita medir el


tiempo de forma visual y entretenida, al mismo tiempo que exploramos las
capacidades del Arduino Nano y aprendemos sobre programación y electrónica.
Además, esta creación puede ser una excelente decoración o regalo, ya que
combina lo tradicional con lo tecnológico.

A lo largo de este tutorial, cubriremos los pasos necesarios para construir el reloj de
arena con Arduino Nano, desde el montaje de los componentes hasta la
programación del código necesario para controlar el sistema. También abordaremos
algunos conceptos clave sobre el funcionamiento de los sensores y cómo
interactúan con el Arduino Nano.
MARCO TEÓRICO

Antes del desarrollo del proyecto, se debe conocer las definiciones de los
componentes a utilizar:

¿QUÉ ES ARDUINO?

Arduino es una plataforma de creación de electrónica de código abierto, la cual está


basada en hardware y software libre, flexible y fácil de utilizar para los creadores y
desarrolladores. Esta plataforma permite crear diferentes tipos de microordenadores
de una sola placa a los que la comunidad de creadores puede darles diferentes
tipos de uso.

¿Cómo funciona Arduino?

El Arduino es una insignia basada en un microcontrolador Atmel. Los


microcontroladores son circuitos integrados en los que se pueden registrar las
instrucciones que escribe con el lenguaje de programación que puede usar en el
IDE Arduino. Estas instrucciones permiten la creación de programas que interactúan
con los circuitos de placa.

El microcontrolador de Arduino tiene una interfaz de entrada que se llama SO, una
conexión en la que podemos conectar diferentes tipos de dispositivos periféricos en
la placa. La información de estos dispositivos periféricos que se conecta se
transfiere al microcontrolador, que es responsable del procesamiento de los datos.

El tipo de dispositivos periféricos con los que puede enviar datos al microcontrolador
depende en gran medida del uso que desee especificar. Puede ser cámaras para
obtener imágenes, teclados para ingresar datos o diferentes tipos de sensores.
También tiene un material de salida responsable de la transferencia de la
información procesada en Arduino a otros dispositivos periféricos. Estos dispositivos
periféricos pueden ser pantallas o altavoces para reproducir datos procesados, pero
también otras placas o controladores.

Arduino es un proyecto, no un modelo de una placa de concreto, lo que significa que


la separación de su diseño principal puede encontrar diferentes tipos de placas. Hay
varias formas, tamaños y colores para las necesidades del proyecto en el que
trabaja, hay características simples o mejoradas centradas en Arduino, centrados en
Internet de las cosas o 3D -Tobate y, por supuesto, dependiendo de estas
características, usted, usted, usted, usted, usted, usted, usted, usted, usted, usted,
usted, usted, usted Encontrará todo tipo de precios.

Para este proyecto, se hace uso del Arduino Nano

¿QUÉ ES ARDUINO NANO?


Arduino Nano, es una versión reducida de Arduino UNO. Eso minimiza la demanda
de energía que consume y también hace que no se necesite tanto espacio para
alojar la paca, por lo que es ideal para proyectos donde el tamaño sea importante.

No se trata de una placa Arduino UNO miniaturizada exactamente, como verás


existen algunas diferencias técnicas importantes. Tampoco es una alternativa
a LilyPad. Pero comparte otras características y la esencia que está presente en
todos los proyectos de Arduino. Por supuesto, se puede programar con el
mismo Arduino IDE como el resto.
MATRICES LED 8X8

Una matriz LED no es otra cosa que un conjunto de LEDs agrupados por filas y


columnas. Las matrices LEDs 8×8 son sumamente conocidas. Su nombre se debe a
que están compuestas por 64 LEDs dispuestos en forma de cuadrado con 8
columnas de 8 LEDs cada una. Su funcionamiento es muy parecido al display de 7
segmentos.

CIRCUITO MAX7219

El MAX7219 es un circuito integrado que facilita el control de LEDs. Es usado


principalmente en pantallas de 7 segmentos, paneles de LEDs industriales y como
controlador de matriz de LED con Arduino.
MPU 6050

El MPU-6050 es un sensor que contiene un acelerómetro MEMS y un giroscopio


MEMS en un solo chip. Es muy preciso, ya que contiene hardware de conversión de
analógico a digital de 16 bits para cada canal. Por lo tanto, captura los canales “X”,
“Y” y “Z” al mismo tiempo.
Dado que este módulo cuenta al mismo tiempo con un giroscopio de tres ejes y
acelerómetro triaxial se puede ocupar en aplicaciones como juegos de detección de
movimiento, realidad aumentada estabilización electrónica y/u óptica de imagen,
interfaz de usuario de gestos “Zero-touch”, entre otras.

Para desarrollar el proyecto, vamos a utilizar los siguientes materiales.

Materiales:

 2 matrices led 8x8 con módulo MAX7219


 1 MPU6050 (acelerómetro y giroscopio)
 1 Arduino Nano
 2 mini protoboard
 1 zumbador
 Jumpers
 4 pilas de 1.5v

Montaje:

1. Como primer paso, colocamos el Arduino Nano y el MPU6050 en cada uno


de los mini protoboard.
2. Conectamos las entradas de una matriz hacia la salida de la otra matriz con
Jumpers hembra a hembra (como se observa en la siguiente imagen). La
entrada de la segunda matriz va conectada al arduino nano.

La primera matriz será la matriz principal; en donde empezará a caer la arena


del reloj hacia la otra matriz.
3. La conexión de la segunda matriz al arduino va de la siguiente manera:
o El pin VCC de la matriz se conecta al pin 5v del arduino.
o El pin GND de la matriz se conecta con el pin GND del arduino.
o El pin DIN va conectado con el pin D2 del arduino.
o El pin CS se conecta con el pin D3 del arduino.
o El pin CLK va conectado con el pin D4 del arduino.
4. La conexión del MPU 6050 al Arduino Nano:
o Con un cable saliendo del pin 5v de nuestro arduino nano, conectamos
al pin VCC del acelerómetro.
o Con otro cable saliendo del GND, se conecta al pin GND del
acelerómetro.
o Conectar el pin A5 con el pin SCL del acelerómetro.
o El pin A4 se conecta con el pin SDA del acelerómetro.
o El pin D2 del Arduino se conecta con el pin INT del acelerómetro.
5. El cable negativo del zumbador se conecta a tierra; y el cable positivo, con el
pin D13 del Arduino.

Para el código del Reloj de arena, es necesario descargar las librerías necesarias
para el programa. En nuestro caso, se descargaron las librerías Delay, LedControl y
la librería necesaria para el acelerómetro.

Código en Arduino IDE

#include "Arduino.h"
#include "LedControl.h"
#include "Delay.h"

#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>
MPU6050 sensor;

#define  MATRIX_A  1
#define  MATRIX_B  0

// Matrix
#define PIN_DATAIN 5   // DIN
#define PIN_CLK 4      // CLK
#define PIN_LOAD 6     // CS

// Accelerometer
#define PIN_X A4
#define PIN_Y A5

/*
// Rotary Encoder
#define PIN_ENC_1 3
#define PIN_ENC_2 2
#define PIN_ENC_BUTTON 7
*/
#define PIN_BUZZER 13

// Esto tiene en cuenta cómo se montan las matrices.


#define ROTATION_OFFSET 90

// in milliseconds
#define DEBOUNCE_THRESHOLD 500

#define DELAY_FRAME 100        //Velocidad de caida de particulas

#define DEBUG_OUTPUT 1

#define MODE_HOURGLASS 0
#define MODE_SETMINUTES 1
#define MODE_SETHOURS 2

byte delayHours = 0;
byte delayMinutes = 1;
int mode = MODE_HOURGLASS;
int gravity;
LedControl lc = LedControl(PIN_DATAIN, PIN_CLK, PIN_LOAD, 2);
NonBlockDelay d;
int resetCounter = 0;
bool alarmWentOff = false;
/**
 * Obtener retraso entre caídas de partículas (en segundos)
 */
long getDelayDrop() {
  // como tenemos exactamente 60 partículas, no tenemos que multiplicar por
60 y luego dividir por el número de partículas nuevamente
  return delayMinutes + delayHours * 60;
}

#if DEBUG_OUTPUT
void printmatrix() {
  Serial.println(" 0123-4567 ");
  for (int y = 0; y<8; y++) {
    if (y == 4) {
      Serial.println("|----|----|");
    }
    Serial.print(y);
    for (int x = 0; x<8; x++) {
      if (x == 4) {
        Serial.print("|");
      }
      Serial.print(lc.getXY(0,x,y) ? "X" :" ");
    }
    Serial.println("|");
  }
  Serial.println("-----------");
}
#endif

coord getDown(int x, int y) {


  coord xy;
  xy.x = x-1;
  xy.y = y+1;
  return xy;
}
coord getLeft(int x, int y) {
  coord xy;
  xy.x = x-1;
  xy.y = y;
  return xy;
}
coord getRight(int x, int y) {
  coord xy;
  xy.x = x;
  xy.y = y+1;
  return xy;
}

bool canGoLeft(int addr, int x, int y) {


  if (x == 0) return false; // not available
  return !lc.getXY(addr, getLeft(x, y));              // you can go there if
this is empty
}
bool canGoRight(int addr, int x, int y) {
  if (y == 7) return false; // not available
  return !lc.getXY(addr, getRight(x, y));             // you can go there if
this is empty
}
bool canGoDown(int addr, int x, int y) {
  if (y == 7) return false; // not available
  if (x == 0) return false; // not available
  if (!canGoLeft(addr, x, y)) return false;
  if (!canGoRight(addr, x, y)) return false;
  return !lc.getXY(addr, getDown(x, y));              // you can go there if
this is empty
}
void goDown(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getDown(x,y), true);
}
void goLeft(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getLeft(x,y), true);
}
void goRight(int addr, int x, int y) {
  lc.setXY(addr, x, y, false);
  lc.setXY(addr, getRight(x,y), true);
}
int countParticles(int addr) {
  int c = 0;
  for (byte y=0; y<8; y++) {
    for (byte x=0; x<8; x++) {
      if (lc.getXY(addr, x, y)) {
        c++;
      }
    }
  }
  return c;
}
bool moveParticle(int addr, int x, int y) {
  if (!lc.getXY(addr,x,y)) {
    return false;
  }

  bool can_GoLeft = canGoLeft(addr, x, y);


  bool can_GoRight = canGoRight(addr, x, y);

  if (!can_GoLeft && !can_GoRight) {


    return false; // we're stuck
  }

  bool can_GoDown = canGoDown(addr, x, y);

  if (can_GoDown) {
    goDown(addr, x, y);
  } else if (can_GoLeft&& !can_GoRight) {
    goLeft(addr, x, y);
  } else if (can_GoRight && !can_GoLeft) {
    goRight(addr, x, y);
  } else if (random(2) == 1) {                  // Podemos ir a izquierda y
derecha, pero no abajo
    goLeft(addr, x, y);
  } else {
    goRight(addr, x, y);
  }
  return true;
}
void fill(int addr, int maxcount) {
  int n = 8;
  byte x,y;
  int count = 0;
  for (byte slice = 0; slice < 2*n-1; ++slice) {
    byte z = slice<n ? 0 : slice-n + 1;
    for (byte j = z; j <= slice-z; ++j) {
      y = 7-j;
      x = (slice-j);
      lc.setXY(addr, x, y, (++count <= maxcount));
    }
  }
}

/**
 * Detectar la orientación usando el acelerómetro
 *
 *     | up | right | left | down |
 * --------------------------------
 * 400 |    |       | y    | x    |
 * 330 | y  | x     | x    | y    |
 * 260 | x  | y     |      |      |
 */
int getGravity() {

  int ax, ay, az;


  Serial.begin(57600);
  Wire.begin();
  sensor.initialize();
  if (sensor.testConnection())Serial.println("Sensor inicialisado
correctamente");
  else Serial.println("Error el iniciar el sensor");
 
  sensor.getAcceleration(&ax, &ay, &az);
  float acce1_ang_x=atan(ax/sqrt(pow(ay,2)+ pow(az,2)))*(180.0/3.14);
  float acce1_ang_y=atan(ay/sqrt(pow(ay,2)+ pow(az,2)))*(180.0/3.14);
  Serial.print("Inclinacion en X: ");
  Serial.print(acce1_ang_x);
  Serial.print("Inclinacion en Y: ");
  Serial.print(acce1_ang_y);
 
  if (acce1_ang_x >= 20 & acce1_ang_y<=5) {return 90; }
  if (acce1_ang_x >= -10 & acce1_ang_y<=0) {return 180; }
  if (acce1_ang_x >= -10 & acce1_ang_y<=25) {return 0; }
  if (acce1_ang_x >= -20 & acce1_ang_y<=-5) {return 270; }
/*
  int x = analogRead(PIN_X);
  int y = analogRead(PIN_y);
  if (y < ACC_THRESHOLD_LOW) { return 0;}
  if (x > ACC_THRESHOLD_HIGH) { return 90;}
  if (y > ACC_THRESHOLD_HIGH) { return 180;}
  if (x < ACC_THRESHOLD_LOW) { return 270;}
   */    

/*
  adx1.readAccel(&x, &y, &z);

  if (x >= 20 & z<=5) {return 90; }


  if (x >= -10 & z<=0) {return 180; }
  if (x >= -10 & z<=25) {return 0; }
  if (x >= -20 & z<=-5) {return 270; }
  int x = 180;       // Agregado
  int y = 180;       // Agregado
  return x;          // Agregado
  return y;          // Agregado
  */  

}
int getTopMatrix() {
  return (getGravity() == 90) ? MATRIX_A : MATRIX_B;
}
int getBottomMatrix() {
  return (getGravity() != 90) ? MATRIX_A : MATRIX_B;
}

void resetTime() {
  for (byte i=0; i<2; i++) {
    lc.clearDisplay(i);
  }
  fill(getTopMatrix(), 64);           // cantidad de particulas en la
Matriz, si se define un intervalo de minutos u horas el valor debe ser 60
  d.Delay(getDelayDrop() * 1000);
}

/**
 * Atraviese la matriz y compruebe si es necesario mover las partículas
 */
bool updateMatrix() {
  int n = 8;
  bool somethingMoved = false;
  byte x,y;
  bool direction;
  for (byte slice = 0; slice < 2*n-1; ++slice) {
    direction = (random(2) == 1); // randomize if we scan from left to right
or from right to left, so the grain doesn't always fall the same direction
    byte z = slice<n ? 0 : slice-n + 1;
    for (byte j = z; j <= slice-z; ++j) {
      y = direction ? (7-j) : (7-(slice-j));
      x = direction ? (slice-j) : j;
      // for (byte d=0; d<2; d++) { lc.invertXY(0, x, y); delay(50); }
      if (moveParticle(MATRIX_B, x, y)) {
        somethingMoved = true;
      };
      if (moveParticle(MATRIX_A, x, y)) {
        somethingMoved = true;
      }
    }
  }
  return somethingMoved;
}

/**
 * Deja que una partícula pase de una matriz a otra
 */
boolean dropParticle() {
  if (d.Timeout()) {
    d.Delay(getDelayDrop() * 1000);
    if (gravity == 0 || gravity == 180) {
      if ((lc.getRawXY(MATRIX_A, 0, 0) && !lc.getRawXY(MATRIX_B, 7, 7)) ||
          (!lc.getRawXY(MATRIX_A, 0, 0) && lc.getRawXY(MATRIX_B, 7, 7))
      ) {
        // for (byte d=0; d<8; d++) { lc.invertXY(0, 0, 7); delay(50); }
        lc.invertRawXY(MATRIX_A, 0, 0);
        lc.invertRawXY(MATRIX_B, 7, 7);
        tone(PIN_BUZZER, 440, 10);
        return true;
      }
    }
  }
  return false;
}

void alarm() {
  for (int i=0; i<5; i++) {
    tone(PIN_BUZZER, 440, 200);
    delay(1000);
  }
}
//de mas
/*
void resetCheck() {
  int z = analogRead(A3);
  if (z > ACC_THRESHOLD_HIGH || z < ACC_THRESHOLD_LOW) {
    resetCounter++;
    Serial.println(resetCounter);
  } else {
    resetCounter = 0;
  }
  if (resetCounter > 20) {
    Serial.println("RESET!");
    resetTime();
    resetCounter = 0;
  }
}
*/

void displayLetter(char letter, int matrix) {


  // Serial.print("Letter: ");
  // Serial.println(letter);
  lc.clearDisplay(matrix);
  lc.setXY(matrix, 1,4, true);
  lc.setXY(matrix, 2,3, true);
  lc.setXY(matrix, 3,2, true);
  lc.setXY(matrix, 4,1, true);

  lc.setXY(matrix, 3,6, true);


  lc.setXY(matrix, 4,5, true);
  lc.setXY(matrix, 5,4, true);
  lc.setXY(matrix, 6,3, true);

  if (letter == 'M') {
    lc.setXY(matrix, 4,2, true);
    lc.setXY(matrix, 4,3, true);
    lc.setXY(matrix, 5,3, true);
  }
  if (letter == 'H') {
    lc.setXY(matrix, 3,3, true);
    lc.setXY(matrix, 4,4, true);
  }
}

void renderSetMinutes() {
  fill(getTopMatrix(), delayMinutes);
  displayLetter('M', getBottomMatrix());
}
void renderSetHours() {
  fill(getTopMatrix(), delayHours);
  displayLetter('H', getBottomMatrix());
}
void knobClockwise() {
  Serial.println("Clockwise");
  if (mode == MODE_SETHOURS) {
    delayHours = constrain(delayHours+1, 0, 64);
    renderSetHours();
  } else if(mode == MODE_SETMINUTES) {
    delayMinutes = constrain(delayMinutes+1, 0, 64);
    renderSetMinutes();
  }
  Serial.print("Delay: ");
  Serial.println(getDelayDrop());
}
void knobCounterClockwise() {
  Serial.println("Counterclockwise");
  if (mode == MODE_SETHOURS) {
    delayHours = constrain(delayHours-1, 0, 64);
    renderSetHours();
  } else if (mode == MODE_SETMINUTES) {
    delayMinutes = constrain(delayMinutes-1, 0, 64);
    renderSetMinutes();
  }
  Serial.print("Delay: ");
  Serial.println(getDelayDrop());
}
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
long lastencoderValue = 0;
long lastValue = 0;
void updateEncoder() {
 
/*  
  int MSB = digitalRead(PIN_ENC_1); //MSB = most significant bit
  int LSB = digitalRead(PIN_ENC_2); //LSB = least significant bit
*/
  int MSB = 0; //MSB = most significant bit      //Agregado
  int LSB = 0; //LSB = least significant bit     //Agregado
 

  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single
number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous
encoded value

  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)


encoderValue--;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
encoderValue++;
  // Serial.print("Value: ");
  // Serial.println(encoderValue);
  if ((encoderValue % 4) == 0) {
    int value = encoderValue / 4;
    if (value > lastValue) knobClockwise();
    if (value < lastValue) knobCounterClockwise();
    lastValue = value;
  }
  lastEncoded = encoded; //store this value for next time
}

/**
 * Button callback (incl. software debouncer)
 * Esto cambia entre los modos (normal, establecer minutos, establecer
horas)
 */
volatile unsigned long lastButtonPushMillis;
void buttonPush() {
 
  if((long)(millis() - lastButtonPushMillis) >= DEBOUNCE_THRESHOLD) {
    mode = (mode+1) % 3;
    Serial.print("Modo cambiado a: ");
    Serial.println(mode);
    lastButtonPushMillis = millis();

    if (mode == MODE_SETMINUTES) {
      lc.backup(); // we only need to back when switching from
MODE_HOURGLASS->MODE_SETMINUTES
      renderSetMinutes();
    }
   
    if (mode == MODE_SETHOURS) {
      renderSetHours();
    }
   
    if (mode == MODE_HOURGLASS) {
      lc.clearDisplay(0);
      lc.clearDisplay(1);
      lc.restore();
      resetTime();
    }
   
  }
}
void setup() {
 
  Serial.begin(9600);
  // configurar el codificador rotatorio
/*
  pinMode(PIN_ENC_1, INPUT);
  pinMode(PIN_ENC_2, INPUT);
  pinMode(PIN_ENC_BUTTON, INPUT);
  digitalWrite(PIN_ENC_1, HIGH); //turn pullup resistor on
  digitalWrite(PIN_ENC_2, HIGH); //turn pullup resistor on
  digitalWrite(PIN_ENC_BUTTON, HIGH); //turn pullup resistor on
  attachInterrupt(digitalPinToInterrupt(PIN_ENC_1), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_ENC_2), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_ENC_BUTTON), buttonPush,
RISING);
*/

  randomSeed(analogRead(A0));

  // init displays
  for (byte i=0; i<2; i++) {
    lc.shutdown(i,false);
    lc.setIntensity(i,0);     //Controla la intensidad de brillo en las
particulas
  }
  resetTime();
}

/**
 * Main loop
 */
void loop() {
  delay(DELAY_FRAME);

  // actualizar la configuración de rotación del controlador. Para el resto


del código pretendemos que "abajo" sigue siendo 0,0 y "arriba" es 7,7
  gravity = getGravity();
  lc.setRotation((ROTATION_OFFSET + gravity) % 360);

  // manejar modos especiales


  if (mode == MODE_SETMINUTES) {
    renderSetMinutes(); return;
  } else if (mode == MODE_SETHOURS) {
    renderSetHours(); return;
  }

  // resetCheck();                   // el reinicio ahora ocurre al


presionar un botón
  bool moved = updateMatrix();
  bool dropped = dropParticle();
  // alarma cuando todo está en la parte inferior
  if (!moved && !dropped && !alarmWentOff && (countParticles(getTopMatrix())
== 0)) {
    alarmWentOff = true;
    alarm();
  //  resetTime();            //Agregado
  }
  // reset alarm flag next time a particle was dropped
  if (dropped) {
    alarmWentOff = false;
  }
}

Después, pasamos el código al Arduino Nano y verificamos su funcionamiento.


CONCLUSIÓN
En conclusión, la creación de un reloj de arena con Arduino Nano nos ha permitido
combinar la belleza y simplicidad de un instrumento tradicional con la tecnología
moderna de la programación y la electrónica. A lo largo de este proyecto, hemos
aprendido a utilizar el Arduino Nano como una poderosa herramienta de control,
permitiéndonos programar y controlar componentes electrónicos de manera precisa.

Al utilizar sensores, un motor y una pantalla, hemos logrado simular la acción de un


reloj de arena en tiempo real, ofreciendo una experiencia fascinante tanto para los
ojos como para el entendimiento.
Además, este proyecto nos ha brindado la oportunidad de adquirir conocimientos
sobre electrónica, programación y el funcionamiento de los sensores. Hemos
aprendido a montar los componentes necesarios, a programar el Arduino Nano para
controlar el tiempo y a interactuar con los sensores para lograr un funcionamiento
preciso y confiable.

El reloj de arena con Arduino Nano no solo cumple su función práctica de medir el
tiempo, sino que también puede ser utilizado como una pieza de decoración única o
incluso como un regalo personalizado. Combina lo tradicional con lo tecnológico,
ofreciendo una combinación intrigante que atraerá la atención de aquellos que lo
vean.

En resumen, este proyecto nos ha permitido explorar las capacidades del Arduino
Nano, aprender sobre electrónica y programación, y crear un reloj de arena
funcional y fascinante. Ha sido una experiencia enriquecedora que nos ha acercado
al mundo de la tecnología y nos ha mostrado cómo podemos combinar lo antiguo y
lo nuevo para crear algo verdaderamente especial.

En conclusión, los circuitos sumadores desempeñan un papel fundamental en la


electrónica digital, permitiendo la operación de suma binaria. Su configuración,
precisión y tiempo de propagación son aspectos importantes a considerar al diseñar
y utilizar estos circuitos. La capacidad de cascada o concatenación de los circuitos
sumadores amplía su utilidad y permite sumar números de mayor tamaño. En
definitiva, los circuitos sumadores son herramientas indispensables para el
procesamiento y cálculo de información en sistemas digitales.

También podría gustarte