Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Smart Cube: Centro de Control Doméstico de Nueva Generación

Componentes y suministros

td>×
Arduino 101 × 1
LED (genérico) × 5
Resistencia 221 ohm × 5
Protoboard (genérica) × 1
Seeed Base Shield V2 × 1
Seeed Grove LCD RGB Backlight × 1
Seeed Grove Sound Sensor 1
Seeed Grove Buzzer × 1
Seeed Grove Temperature Sensor × 1
Teclado matricial (Keypad) × 1
Cables jumpers (genéricos) × 1
Batería 9V (genérica) × 1
Conector batería 9V × 1
Fibra de densidad media (MDF) 20x30 cm, 3mm × 1

Herramientas y máquinas necesarias

Aplicaciones y servicios en línea

Sobre el proyecto

¿Qué es SMART CUBE?

Smart Cube es un controlador para tus dispositivos de hogar inteligente.

Hoy en día, gestionar de forma más inteligente todos los dispositivos de nuestro hogar se está volviendo una exigencia. Necesitamos algo simple e intuitivo de usar. Smart Cube podría ser una solución: es un dispositivo portátil que contiene una placa Arduino 101 y algunos sensores que se comunican con los electrodomésticos y actuadores de tu hogar inteligente.

La innovación de este mando a distancia está relacionada con la innovación de la placa Arduino 101. Utiliza Bluetooth (BLE) para controlar luces, temperatura y tu TV, y también puedes sincronizarlo con tu smartphone. Pero la mayor innovación es la forma en que interactúas con Smart Cube mediante gestos usando el giroscopio y el acelerómetro. El cubo tiene 6 caras y cada una controla una función particular. La función que quieres usar se detecta gracias al giroscopio que reconoce la cara superior. Por ejemplo, puedes encender las luces de la habitación en la que estás simplemente colocando el cubo con la "cara de luces" en la posición superior. Si quieres apagar la luz, solo necesitas agitar el cubo.

Si una cara está ARRIBA y no se mueve durante más de 2 segundos, se activa la función relacionada. Este retraso se hace para que tengas tiempo de rotar e interactuar con el cubo para encontrar la cara que necesitas sin activar accidentalmente otras funciones. Cuando agitas el cubo durante más de 2 segundos, la última función activada se cierra.

Este proyecto pretende ayudarte a construir un controlador inteligente. Este dispositivo necesita un receptor (centralita inteligente en la imagen) que interprete los datos y gestione las funciones de tu hogar inteligente. La principal salida del cubo es una señal BLE que puede usarse de muchas formas: por ejemplo, puedes conectar el cubo con una app de smartphone (o crear la tuya propia), o puedes construir una estación con otro Arduino que recoja los datos BLE y controle directamente los electrodomésticos de tu casa. Debido a la variedad de casos, esta parte depende de tus necesidades. En esta guía veremos cómo construir un Smart Cube y aprenderás a personalizarlo.

Smart Cube: Centro de Control Doméstico de Nueva Generación

Funciones:

La estructura del código es fácil de personalizar (analizamos el código más adelante) para que decidas qué funciones controlar. Estas son las funciones que decidí controlar:

Smart Cube: Centro de Control Doméstico de Nueva Generación

LUZES: Esta cara en posición ARRIBA enciende las luces de la habitación en la que estás. Si agitas el cubo, las luces se apagan y un LED amarillo en esta cara se enciende para que puedas encontrar el cubo en la oscuridad. La comunicación con tus lámparas se hace por el BLE de la placa 101.

TEMPERATURA: Esta cara ARRIBA activa (vía BLE) el aire acondicionado si hace calor o la calefacción si hace frío. Detecta la temperatura usando un sensor térmico y enciende un LED azul si el aire acondicionado está activo (copito de nieve) o uno rojo si la calefacción está activa (sol).

TEMPORIZADOR: Esta cara ARRIBA inicia un temporizador que ves en la pantalla LCD. Hay un buzzer que funciona como alarma cuando termina la cuenta regresiva. Si agitas, detienes el temporizador y ves el tiempo restante. Cuando termina la cuenta regresiva, el color del LCD cambia de azul a rojo y el buzzer suena tres veces.

TV: Esta cara ARRIBA enciende la TV. El cubo se convierte en un mando a distancia para tu TV. Hay un panel de botones con números que se activa solo si esta cara está ARRIBA para evitar toques accidentales. El número que pulsas se envía vía BLE a la centralita que está conectada a tu TV. Agitando el cubo apagas la TV.

SONIDO: Esta cara ARRIBA activa un LED cuyo brillo se basa en el nivel de ruido de la habitación. El ruido se detecta gracias a un sensor de sonido. Si agitas el cubo, cierras esta función. (Si quieres, puedes activar tu función personal aplaudiendo).

Cara OFF: Si no agitas el cubo, esta cara es como una posición neutra en la que no cambia nada. Si quieres cerrar todo, coloca el cubo con la cara OFF ARRIBA y agítalo. Este gesto es como el botón de inicio en tu smartphone que pulsas si quieres salir rápido. Hay un LED rojo para que puedas encontrar el cubo si está oscuro.

Diferencias con el concepto original:

El plan original era usar también comunicación IR para conectar tu TV directamente al cubo. Como el Arduino 101 no soporta (por ahora) la librería que gestiona las señales IR, decidí enviar la información vía BLE a una estación que pueda gestionar esta librería (como Arduino UNO). Por este problema eliminé la función de radio (muy similar a la cara TV), reemplazándola por una cara con sensor de sonido. Esta cara podría usarse para reconocer un ruido fuerte (como aplausos) y activar algo. El mayor cambio está en el material del cubo. Inicialmente pensé en construirlo con una impresora 3D pero luego decidí usar una cortadora láser. Así es más fácil sustituir una cara si quieres cambiar una función. Por ejemplo, puedes quitar la cara del temporizador y cambiarla por una que llene automáticamente el cuenco de tu gato. Al ser modular, no necesitas reconstruir toda la estructura.

Smart Cube: Centro de Control Doméstico de Nueva Generación

¡Construyámoslo!

Sigue estas instrucciones para construir tu propio Smart Cube. Empezaremos por el hardware, ensamblando primero los componentes electrónicos y luego la caja del cubo cortada con láser en MDF. Después explicaré cómo funciona el código y cómo personalizarlo. Tras subir el código a tu Arduino 101, puedes descargar la app para ver la salida BLE del cubo o conectarlo directamente con tu hogar inteligente.

Smart Cube: Centro de Control Doméstico de Nueva Generación

Hardware - Electrónica:

Empecemos por tu Arduino 101. Este es el esquema Fritzing a seguir:

Smart Cube: Centro de Control Doméstico de Nueva Generación

Monta el Grove Base Shield en tu placa y empieza con las conexiones.

Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación

Keypad: debes conectar los cables en orden a los pines: 10, 8, 7, 6, 5, 4, 2.

Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación

Conexiones LED:

Primero preparamos los LEDs:

Ahora conecta los cables rojos a tu Arduino: LED VERDE al pin 9, LED AMARILLO al pin 11, LED ROJO al pin 12, LED AZUL al pin 13 y el último ROJO al pin A2.

Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación

Sensores Grove:

Conecta los sensores Grove al shield (ver esquema en adjuntos).

Buzzer a D3, LCD RGB a I2C, Sensor temperatura a A0, Sensor sonido a A1.

Smart Cube: Centro de Control Doméstico de Nueva Generación

Bien, ahora tenemos conectadas todas las partes eléctricas. Ahora necesitas la caja.

Hardware - Caja

Puedes descargar el esquema del cubo para cortar con láser. Las líneas rojas en el esquema son los símbolos de las caras, solo graba (grabado). Las líneas negras deben cortarse. La dimensión interna del cubo es 9 cm. El esquema sirve si usas material de 3mm, si usas otro grosor debes modificarlo (puedes usar esta web: https://www.makercase.com/).

El material que elijo es MDF (Fibra de Densidad Media) pero puedes usar lo que quieras.

Aquí algunas fotos del corte láser:

Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación

Ahora hay que ensamblarlo.

Pegué algunos trozos de cartón para dar grosor a los LEDs. Así quedarán alineados con la superficie.

Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación

Montamos el keypad. Insértalo en el agujero, quita la película adhesiva y vuelve a conectar los pines.

Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación

Ahora el LCD RGB. Encaja perfectamente en el agujero.

Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación

Preparamos el conector de batería:

Corté un enchufe de transformador viejo y lo conecté a un conector de batería. Así ahorramos espacio dentro de la caja.

Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación
Smart Cube: Centro de Control Doméstico de Nueva Generación

En este punto esto es lo que deberías tener:

Smart Cube: Centro de Control Doméstico de Nueva Generación

Ahora solo necesitas conectar la batería, subir el código y cerrar el cubo!

CONSEJO: fija la placa y la batería a la caja para que al agitar el cubo permanezcan estables.

Smart Cube: Centro de Control Doméstico de Nueva Generación

Código

Puedes encontrar el código en los adjuntos. Súbelo a tu placa con el Arduino IDE (recuerda actualizar tu software para compatibilidad con Arduino 101).

He comentado casi cada línea del código para hacerlo lo más comprensible posible. No te asustes por las 500+ líneas, la estructura no es tan complicada.

Al principio están las librerías y la declaración de todas las variables.

En esta parte también está la definición de servicios y características BLE. Usé el servicio Automation IO. Usé la característica Digital para luces y temperatura (usa 2 bits, así que 4 casos posibles para codificar) y la Analog para TV (para enviar todos los códigos del keypad).

Luego el setup. Esta parte se ejecuta una sola vez al principio. Aquí inicializamos los componentes como entradas o salidas e inicializamos el BLE y el giroscopio de la placa 101.

La parte principal es el loop. Está dividido en cuatro partes:

Puedes modificar las funciones de las caras con algunos cambios en el código. La estructura principal debe ser como se describe. Puedes cambiar la parte dentro de las condiciones if de cada cara.

if (face2 == true) { // cara TEMPERATURA
  // EMPEZAR CAMBIOS AQUÍ
  digitalWrite (LEDOFF, LOW); // si esta cara es true, el LED OFF está LOW
  if (central.connected() == true) { // si el cubo está conectado por BLE
    // leer valor temperatura
    int val = analogRead(pinTemp); // obtener valor analógico
    resistance=(float)(1023-val)*10000/val; // obtener resistencia
    temperature=1/(log(resistance/10000)/B+1/298.15)-273.15; // calcular temperatura
    // condiciones de activación
    if (temperature > tooHot) { // activar aire acondicionado
      digitalWrite(LEDhot, LOW); // apagar LED calefacción
      digitalWrite(LEDcold, HIGH); // encender LED aire acondicionado
      termoChar.setValue(1); // establecer vía BLE condición 1 = frío on - calor off
    }
    if (temperature < tooCold) { // activar calefacción
      digitalWrite(LEDhot, HIGH);
      digitalWrite(LEDcold, LOW);
      termoChar.setValue(2); // 2 = frío off - calor on
    }
    if (temperature > tooCold && temperature < tooHot) { // temperatura ideal: nada activado
      digitalWrite(LEDhot, LOW);
      digitalWrite(LEDcold, LOW);
      termoChar.setValue(0); // 0 = frío off - calor off
    }
  }
  // TERMINAR AQUÍ
}

También debes programar la parte "false" cuando se agita el cubo:

// Desactivación TEMPERATURA
if (lastFUNCTION == 2) { // cara TEMPERATURA
  // EMPEZAR CAMBIOS AQUÍ
  // si hay una central conectada al periférico:
  if (central.connected() == true) {
    digitalWrite(LEDhot, LOW); // apagar LED rojo temperatura
    digitalWrite(LEDcold, LOW); // apagar LED azul temperatura
    termoChar.setValue(0); // señal BLE temperatura: 0 = frío off - calor off
    // TERMINAR AQUÍ
  }
  Serial.println("TEMPERATURE false - CLOSE");
  face2 = false; // cara TEMPERATURA se vuelve false
}

Recuerda poner la cara como false cuando la agitas.

App:

Para ver las salidas BLE del cubo puedes descargar esta app: nRF Connect

https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=it

Al abrirla, solo busca dispositivos y conecta con "smartcubesketch". Luego verás tres pestañas "Automation IO", haz clic en ellas y pulsa el recolector de datos continuo.

Es importante conectar el cubo porque algunas funciones (luces, temperatura y TV) solo se ejecutan si el cubo está conectado.

Cómo funciona: VIDEO

Sube el código, inserta la batería, cierra la caja y...

...¡ahora tienes un SMART CUBE!

Hice un video para mostrarte todas las funciones del cubo y cómo usarlo.

Conclusiones

Este proyecto es solo el primer paso hacia un hogar inteligente. Mi objetivo era usar el potencial de la placa Arduino 101 para crear algo nuevo. Creo que el acelerómetro y el giroscopio dan a la placa nuevas oportunidades en términos de movilidad. Con el BLE, además de ser portátil, también es fácil de conectar.

Es la primera vez que realizo concretamente uno de mis proyectos (quiero decir con un prototipo funcional). Fue duro y hubo algunas dificultades en el camino, pero al final aprendí mucho y estoy contento con el resultado. Espero que todos los que lean esta guía puedan aprender algo de mi trabajo y también modifiquen este proyecto según sus necesidades. Disculpad mi mal inglés, pero espero que las imágenes os ayuden.

En el futuro de este proyecto espero crear la centralita que es como el puente entre el Smart Cube y los actuadores (luces, temperatura, TV...). Esta centralita recibirá la señal BLE del cubo y usará esta información para hacer cosas inteligentes en tu casa.

Estoy muy contento de haber tenido la oportunidad de usar Arduino 101 y el Grove kit (el kit es muy simple y rápido para prototipar).

Espero que usar la placa de esta manera pueda ser una inspiración para vuestros proyectos. Podéis personalizarlo como queráis: ¡tengo curiosidad por ver qué funciones crearéis y en qué contextos diferentes lo usaréis!

Quizás no sea una revolución, pero es una nueva forma de interactuar con tu hogar.

Espero que os guste este tutorial.

Ahora es vuestro turno: poned las manos en el cubo y ¡hackeadlo!

Código

SMART CUBE - código completo con comentarios Arduino
// Librerías
#include "CurieIMU.h" // Acelerómetro y Giroscopio
#include <CurieBLE.h> // Bluetooth Low Energy
#include <Wire.h>
#include "rgb_lcd.h" // LCD
#include <Keypad.h> // Keypad

rgb_lcd lcd; // Inicialización LCD

// Inicialización Bluetooth:
BLEPeripheral blePeripheral; // Dispositivo BLE Periférico (la placa que programas)
// Servicios BLE
BLEService lightsService("1815"); // BLE Automation IO (1815) - info luces
BLEService termoService("1815"); // BLE Automation IO - info temperatura
BLEService TVService("1815"); // BLE Automation IO - info TV
// Características BLE
BLEUnsignedCharCharacteristic lightsChar("2A56", // Característica Digital (2A56) - luces
  BLERead | BLENotify);
BLEUnsignedCharCharacteristic termoChar("2A56", // Característica Digital - temperatura
  BLERead | BLENotify);
BLEUnsignedCharCharacteristic TVChar("2A58", // Característica Analog (2A58) - TV
  BLERead | BLENotify);

// Constantes y declaración de variables:
// Funciones de orientación de cara y shake:
int lastOrientation = -1; // orientación anterior (para comparación)
unsigned long previousMillis = 0; // última actualización de tiempo
unsigned long interval = 2000; // tiempo de espera en posición superior antes de activar cara
unsigned long SHAKEpreviousMillis = 0; // última actualización tiempo shake
unsigned long SHAKEinterval = 2000; // tiempo de espera durante shake para desactivar cara
boolean keep = false; // usado para contar solo una vez el cambio de orientación de cara
int lastFUNCTION = -1; // usado para saber la orientación anterior

// Inicialización de caras: al principio todas false
boolean face0 = false;
boolean face1 = false;
boolean face2 = false;
boolean face3 = false;
boolean face4 = false;
boolean face5 = false;

// Cara LUCES
const int LEDlights = 11; // pin 11: LED amarillo

// Cara TEMPERATURA
const int pinTemp = A0; // pin A0: sensor temperatura
const int LEDhot = 12; // pin 12: LED rojo
const int LEDcold = 13; // pin 13: LED azul
float temperature; // valor temperatura memorizado
int B=3975; // valor B del termistor
float resistance; // valor resistencia memorizado
float tooHot = 26.0; // temperatura para activar aire acondicionado [AJUSTE]
float tooCold = 23.0; // temperatura para activar calefacción [AJUSTE]

// Cara TEMPORIZADOR
int BUZZER = 3; // pin 3: buzzer
boolean KEEPtime = false; // usado para contar solo una vez el cambio de orientación (no reiniciar mientras cuenta)
int TIMERmillis = 0; // para determinación de cuenta regresiva
int prevSHOWsecond = 0;
int CountdownInMillis = 0;
int SHOWmillis = 0; // cálculo resultado valor millis
int SHOWminute = 0; // valor minutos para mostrar en monitor cuenta regresiva
int SHOWseconds = 0; // valor segundos para mostrar en monitor cuenta regresiva
const int SETminute = 2; // temporizador 2 minutos [AJUSTE]
const int SETsecond = 30; // temporizador 30 segundos [AJUSTE]

// Cara SONIDO
const int soundLED = 9; // pin 9: LED verde
const int soundSENSOR = A1; // pin A0: sensor sonido
int brightness = 0; // brillo LED verde inicialización

// Cara TV
const byte ROWS = 4; // cuatro filas keypad
const byte COLS = 3; // tres columnas keypad
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
}; // valores botones keypad
byte rowPins[ROWS] = {10,8,7,6}; // pines 10,8,7,6: conectar a pines filas keypad
byte colPins[COLS] = {5,4,2}; // pines 5,4,2: conectar a pines columnas keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // inicialización keypad

// Cara OFF
const int LEDOFF = A2; // pin A2: LED rojo

void setup() {
  pinMode(LEDlights, OUTPUT); // cada LED como salida
  pinMode(LEDhot, OUTPUT);
  pinMode(LEDcold, OUTPUT);
  pinMode(soundLED, OUTPUT);
  pinMode(LEDOFF, OUTPUT);
  Serial.begin(9600); // inicializar comunicación serial
  CountdownInMillis = (SETminute*60 + SETsecond)*1000; // calcula valor en millis desde minutos y segundos
  lcd.begin(16, 2); // inicialización LCD
  lcd.setRGB(0, 0, 0); // LCD RGB APAGADO al inicio
  // inicializar dispositivo
  Serial.println("Inicializando dispositivo IMU...");
  CurieIMU.begin(); // Iniciar IMU
  // Establecer rango acelerómetro a 2G
  CurieIMU.setAccelerometerRange(2);
  // Activar detección de golpes
  CurieIMU.setDetectionThreshold(CURIE_IMU_SHOCK, 7000); // 7.0g = 7000 mg (intensidad del golpe)
  CurieIMU.setDetectionDuration(CURIE_IMU_SHOCK, 2000); // 2000ms (duración del golpe)
  CurieIMU.interrupts(CURIE_IMU_SHOCK);
  // Configuración BLE
  blePeripheral.setLocalName("SmartCubeSketch"); // nombre del proyecto
  blePeripheral.setAdvertisedServiceUuid(lightsService.uuid()); // añadir UUID servicio luces
  blePeripheral.addAttribute(lightsService); // añadir servicio BLE luces
  blePeripheral.addAttribute(lightsChar); // añadir característica BLE luces
  lightsChar.setValue(3); // valor inicial para esta característica = 3
  // Significado valor BLE luces: 0 = luces off, 1 = luces on, 3 = estado inicial, 4 = no usado
  blePeripheral.setAdvertisedServiceUuid(termoService.uuid()); // añadir UUID servicio temperatura
  blePeripheral.addAttribute(termoService); // añadir servicio BLE temperatura
  blePeripheral.addAttribute(termoChar); // añadir característica BLE temperatura
  termoChar.setValue(0); // valor inicial 0: frío off - calor off
  // Significado valor BLE termo: 0 = frío off - calor off, 1 = frío on - calor off, 2 = frío off - calor on, 3 = no usado
  blePeripheral.setAdvertisedServiceUuid(TVService.uuid()); // añadir UUID servicio TV
  blePeripheral.addAttribute(TVService); // añadir servicio BLE TV
  blePeripheral.addAttribute(TVChar); // añadir característica TV
  TVChar.setValue('x'); // valor inicial para esta característica (x = nada)
  // Significado valor BLE TV: #número corresponde a botón pulsado, C: cerrar TV, O: abrir TV, x: estado inicial
  blePeripheral.begin();
  Serial.println("Dispositivo Bluetooth activo, esperando conexiones...");
}
// fin setup

void loop() {
  BLECentral central = blePeripheral.central(); // conexión BLE
  unsigned long currentMillis = millis(); // valor actual tiempo en milisegundos
  // El siguiente código viene de www.arduino.cc/en/Tutorial/Genuino101CurieIMUAccelerometerOrientation
  // se usa para detectar la orientación de la placa
  int orientation = -1; // orientación de la placa
  String orientationString; // string para imprimir descripción orientación
  // leer acelerómetro:
  int x = CurieIMU.readAccelerometer(X_AXIS);
  int y = CurieIMU.readAccelerometer(Y_AXIS);
  int z = CurieIMU.readAccelerometer(Z_AXIS);
  // calcular valores absolutos para determinar el mayor
  int absX = abs(x);
  int absY = abs(y);
  int absZ = abs(z);
  if ((absZ > absX) && (absZ > absY)) { // orientación base en Z
    if (z > 0) {
      orientationString = "up";
      orientation = 0;
    } else {
      orientationString = "down";
      orientation = 1;
    }
  } else if ((absY > absX) && (absY > absZ)) { // orientación base en Y
    if (y > 0) {
      orientationString = "digital pins up";
      orientation = 2;
    } else {
      orientationString = "analog pins up";
      orientation = 3;
    }
  } else { // orientación base en X
    if (x < 0) {
      orientationString = "connector up";
      orientation = 4;
    } else {
      orientationString = "connector down";
      orientation = 5;
    }
  }
  // fin código tutorial.
  // En este punto tienes el valor de orientación de la placa constantemente actualizado:
  /* Orientaciones de la placa:
  0: plana, procesador hacia arriba (TEMPORIZADOR)
  1: plana, procesador hacia abajo (TV)
  2: horizontal, pines analógicos abajo (TEMPERATURA)
  3: horizontal, pines analógicos arriba (OFF)
  4: vertical, conector USB arriba (LUCES)
  5: vertical, conector USB abajo (SONIDO)
  */
  // Para este proyecto necesitas saber si la cara ha cambiado de la anterior [lastFUNCTION != orientation]
  // pero esta info se imprime solo si la cara está en posición SUPERIOR por más de [interval] tiempo
  // y solo una vez [keep] (no necesitas activar constantemente la cara, solo una vez)
  // como el valor de orientación se actualiza constantemente, necesitas empezar a contar tiempo cuando la orientación cambia [orientation != lastOrientation]
  if (orientation != lastOrientation) {
    // si la orientación cambió, empezar a contar tiempo
    lastOrientation = orientation; // memorizar orientación actual de la cara
    previousMillis = currentMillis; // memorizar tiempo cuando la cara cambió
    keep = false;
  } else if (currentMillis - previousMillis > interval && keep == false && lastFUNCTION != orientation) {
    // esta condición imprime la orientación solo si la cara está arriba por un intervalo
    // y solo una vez (keep)
    // y solo si la cara es diferente del loop anterior
    Serial.println(orientationString); // imprimir orientación
    // la cara actual [orientation] se pone como true (función de cara activada)
    if (orientation == 1) { // cara TV
      face1 = true; // cara TV true
      lastFUNCTION = orientation; // memorizar esta activación en [lastFUNCTION]
      Serial.println("TV true"); // imprimir cara activada
      TVChar.setValue('O'); // O: señal abrir TV (BLE): TV abierta solo una vez
    }
    if (orientation == 4) { // cara LUCES
      face4 = true;
      lastFUNCTION = orientation;
      Serial.println("LIGHTS true");
    }
    if (orientation == 3) { // cara OFF
      face3 = true;
      lastFUNCTION = orientation;
      Serial.println("OFF true");
    }
    if (orientation == 5) { // cara SONIDO
      face5 = true;
      lastFUNCTION = orientation;
      Serial.println("SOUND true");
    }
    if (orientation == 2) { // cara TEMPERATURA
      face2 = true;
      lastFUNCTION = orientation;
      Serial.println("TEMPERATURE true");
    }
    if (orientation == 0) { // cara TEMPORIZADOR
      face0 = true;
      lastFUNCTION = orientation;
      Serial.println("TIMER true");
      if (KEEPtime == false) { // temporizador activado solo si es 1er ciclo o se ha detenido
        TIMERmillis = currentMillis; // empezar a contar tiempo
      }
    }
    keep = true; // [keep] cambia valor para que en próximo loop no entre en esta condición si la cara no cambia (evita activar otra vez misma cara)
  }
  // Esta condición es para la función shake: si agitas por más de [SHAKEinterval] tiempo, la cara se desactiva
  if (CurieIMU.getInterruptStatus(CURIE_IMU_SHOCK) && currentMillis - SHAKEpreviousMillis > SHAKEinterval) {
    Serial.println("SHAKE"); // imprimir "SHAKE" si se detecta agitación
    // La última cara activada [lastFUNCTION] se pone como false (función de cara desactivada)
    // Desactivación TV
    if (lastFUNCTION == 1) { // cara TV
      TVChar.setValue('C'); // C: cerrar TV señal BLE
      Serial.println("TV false - CLOSE"); // imprimir cara cerrada
      face1 = false; // cara TV false
    }
    // Desactivación LUCES
    if (lastFUNCTION == 4) { // cara LUCES
      if (central.connected() == true) { // si hay central conectada a periférico:
        lightsChar.setValue(0); // luces OFF señal BLE
        digitalWrite(LEDlights, HIGH); // encender LED amarillo para ver cubo en oscuridad
      }
      Serial.println("LIGHTS false - CLOSE");
      face4 = false; // cara LUCES false
    }
    // OFF
    if (lastFUNCTION == 3) { // cara OFF
      // Cara OFF agitada: todo se cierra y LED rojo OFF se enciende
      digitalWrite(LEDOFF, HIGH); // LED rojo OFF encendido cuando cubo cerrado
      // ahora cerrar todas las funciones activadas:
      // CERRAR TV
      TVChar.setValue('C'); // C: cerrar TV señal BLE
      Serial.println("TV false - CLOSE");
      face1 = false;
      // CERRAR LUCES
      Serial.println("LIGHTS false - CLOSE");
      if (central.connected() == true) {
        lightsChar.setValue(0);
        digitalWrite(LEDlights, LOW); // LED luces apagado si cara OFF agitada
      }
      face4 = false;
      // CERRAR SONIDO
      analogWrite(soundLED, LOW); // apagar LED sonido
      Serial.println("SOUND false - CLOSE");
      face5 = false;
      // CERRAR TEMPERATURA
      if (central.connected() == true) {
        digitalWrite(LEDhot, LOW);
        digitalWrite(LEDcold, LOW);
        termoChar.setValue(0); // señal BLE temperatura: 0 = frío off - calor off
      }
      Serial.println("TEMPERATURE false - CLOSE");
      face2 = false;
      // CERRAR TEMPORIZADOR
      Serial.println("TIMER false - CLOSE");
      lcd.setRGB(0, 0, 0); // LCD RGB apagado
      lcd.clear();
      KEEPtime = false;
      face0 = false;
      // El cubo inactivo, solo LED OFF activo
      Serial.println("OFF false - CLOSE");
      face3 = false; // cara OFF false
    }
    // Desactivación SONIDO
    if (lastFUNCTION == 5) { // cara SONIDO
      analogWrite(soundLED, LOW); // apagar LED sonido
      Serial.println("SOUND false - CLOSE");
      face5 = false; // cara SONIDO false
    }
    // Desactivación TEMPERATURA
    if (lastFUNCTION == 2) { // cara TEMPERATURA
      // si hay central conectada a periférico:
      if (central.connected() == true) {
        digitalWrite(LEDhot, LOW); // apagar LED rojo temperatura
        digitalWrite(LEDcold, LOW); // apagar LED azul temperatura
        termoChar.setValue(0); // señal BLE temperatura: 0 = frío off - calor off
      }
      Serial.println("TEMPERATURE false - CLOSE");
      face2 = false; // cara TEMPERATURA false
    }
    // Desactivación TEMPORIZADOR
    if (lastFUNCTION == 0) { // cara TEMPORIZADOR
      Serial.println("TIMER false - CLOSE");
      face0 = false; // cara TEMPORIZADOR false
      // si agitas el cubo mientras el tiempo corre, el LCD se pone rojo y muestra tiempo restante
      lcd.setRGB(180, 40, 0); // retroiluminación RGB roja
      lcd.clear(); // LCD limpio
      lcd.setCursor(0, 0);
      lcd.print("STOP AT ");
      lcd.setCursor(8, 0);
      lcd.print(SHOWminute); // indica minutos al agitar
      lcd.setCursor(9, 0);
      lcd.print(":");
      lcd.setCursor(10, 0);
      lcd.print(SHOWseconds); // indica segundos al agitar
      tone(BUZZER,1000,1000); // sonido corto
      delay(2000);
      lcd.clear(); // limpiar LCD
      lcd.setRGB(0, 0, 0); // retroiluminación LCD apagada
      KEEPtime = false; // cara TEMPORIZADOR false
    }
    SHAKEpreviousMillis = currentMillis; // memorizar valor para cálculo [SHAKEinterval]
  }
  // Las siguientes instrucciones se ejecutan en loop solo si la cara está activada
  if (face1 == true) { // cara TV
    digitalWrite(LEDOFF, LOW); // si esta cara true, LED OFF LOW
    if (central.connected() == true) { // si cubo conectado BLE
      char key = keypad.getKey(); // leer valor keypad
      if (key && orientation == 1){ // si algo pulsado y solo cuando cara TV arriba (evitar pulsaciones involuntarias)
        if (key == '0') { TVChar.setValue(key); Serial.println(key); }
        if (key == '1') { TVChar.setValue(key); Serial.println(key); }
        if (key == '2') { TVChar.setValue(key); Serial.println(key); }
        if (key == '3') { TVChar.setValue(key); Serial.println(key); }
        if (key == '4') { TVChar.setValue(key); Serial.println(key); }
        if (key == '5') { TVChar.setValue(key); Serial.println(key); }
        if (key == '6') { TVChar.setValue(key); Serial.println(key); }
        if (key == '7') { TVChar.setValue(key); Serial.println(key); }
        if (key == '8') { TVChar.setValue(key); Serial.println(key); }
        if (key == '9') { TVChar.setValue(key); Serial.println(key); }
        if (key == '*') { TVChar.setValue(key); Serial.println(key); }
        if (key == '#') { TVChar.setValue(key); Serial.println(key); }
      }
    }
  }
  if (face4 == true) { // cara LUCES
    digitalWrite(LEDOFF, LOW);
    if (central.connected() == true) {
      lightsChar.setValue(1); // LUCES activada señal BLE
      digitalWrite(LEDlights, LOW); // LED amarillo apagado porque luces de casa encendidas
    }
  }
  if (face3 == true) { // cara OFF
    // cuando cara OFF arriba no se hace nada
    digitalWrite(LEDOFF, LOW); // LED OFF activado solo al agitar, ahora LOW
  }
  if (face5 == true) { // cara SONIDO
    digitalWrite(LEDOFF, LOW);
    // sensor sonido activado, brillo LED regulado por sonido
    // este código viene de ejemplo regulación brillo
    long sum = 0;
    for (int i=0; i<32; i++) {
      sum += analogRead(soundSENSOR);
    }
    sum >>= 5;
    brightness = (sum*255)/1024; // calcular valor brillo
    analogWrite(soundLED, brightness); // intensidad brillo LED verde regulada por ruido
    delay(50);
  }
  if (face2 == true) { // cara TEMPERATURA
    digitalWrite(LEDOFF, LOW);
    if (central.connected() == true) {
      // leer valor temperatura
      int val = analogRead(pinTemp); // obtener valor analógico
      resistance=(float)(1023-val)*10000/val; // obtener resistencia
      temperature=1/(log(resistance/10000)/B+1/298.15)-273.15; // calcular temperatura
      // condiciones activación
      if (temperature > tooHot) { // activar aire acondicionado
        digitalWrite(LEDhot, LOW); // apagar LED calefacción
        digitalWrite(LEDcold, HIGH); // encender LED aire acondicionado
        termoChar.setValue(1); // establecer vía BLE condición 1 = frío on - calor off
      }
      if (temperature < tooCold){ // activar calefacción
        digitalWrite(LEDhot, HIGH);
        digitalWrite(LEDcold, LOW);
        termoChar.setValue(2); // 2 = frío off - calor on
      }
      if (temperature > tooCold && temperature < tooHot){ // temperatura ideal: nada activado
        digitalWrite(LEDhot, LOW);
        digitalWrite(LEDcold, LOW);
        termoChar.setValue(0); // 0 = frío off - calor off
      }
    }
  }
  if (face0 == true) { // cara TEMPORIZADOR activada
    digitalWrite(LEDOFF, LOW);
    // calcular tiempo para mostrar en display
    SHOWmillis = (CountdownInMillis - (currentMillis - TIMERmillis))/1000;
    SHOWminute = SHOWmillis/60; // valor minutos para LCD
    SHOWseconds = SHOWmillis%60; // valor segundos para LCD
    lcd.setRGB(50, 100, 70); // abrir LCD con color RGB azul
    if (prevSHOWsecond != SHOWseconds){ // refrescar pantalla cada segundo (refrescar cada loop es muy rápido)
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("TIMER ");
      lcd.setCursor(7, 0);
      lcd.print(SETminute); // escribe minutos configurados
      lcd.setCursor(8, 0);
      lcd.print(":");
      lcd.setCursor(9, 0);
      lcd.print(SETsecond); // escribe segundos configurados
      lcd.setCursor(0, 1);
      lcd.print(SHOWminute); // escribe minutos restantes actuales
      lcd.setCursor(1, 1);
      lcd.print(":");
      lcd.setCursor(2, 1);
      lcd.print(SHOWseconds); // escribe segundos restantes actuales
      KEEPtime = true;
      prevSHOWsecond = SHOWseconds; // para refrescar cada segundo
    }
    if (SHOWminute == 0 && SHOWseconds == 0) { // cuando termina cuenta regresiva
      lcd.clear(); // limpiar LCD
      lcd.setCursor(4, 0);
      lcd.setRGB(180, 40, 0); // LCD RGB rojo
      lcd.print("TIME OUT");
      tone(BUZZER,1000,500); // tres sonidos
      delay(900);
      tone(BUZZER,1000,500);
      delay(900);
      tone(BUZZER,1000,1000);
      delay(1500);
      lcd.clear(); // limpiar y cerrar LCD
      lcd.setRGB(0, 0, 0);
      face0 = false; // cara TEMPORIZADOR cerrada (false)
      KEEPtime = false;
    }
  }
} // fin loop

Piezas personalizadas y cajas

Este es el archivo (.dxf) que puedes subir a tu cortadora láser. Usé tablero de fibra de densidad media (MDF) de 3mm. Corta las líneas negras y graba las rojas. Importante: si el grosor de tu material es diferente debes modificar este esquema.

smart_cube_8sVCflFmhM.dxf

El mismo archivo de la caja pero en formato diferente: .pdf

Esquemas

Este es un .jpeg del esquema Fritzing (los cables amarillos están conectados a componentes Grove)

Smart Cube: Centro de Control Doméstico de Nueva Generación

Este es un esquema de las conexiones en el Grove Shield

_cI0IwUsPVZ.Base%20shield%20connections

Proceso de manufactura

  1. Por Qué un Diseño Ligeramente Mayor Puede Acelerar la Innovación y Reducir Riesgo
  2. Construya una Red de Sensores Inalámbrica Económica para su Hogar
  3. Monitoriza la temperatura de tu casa con un panel Raspberry Pi
  4. Planta Inteligente IoT: Construye un Invernadero Conectado con Arduino y Azure
  5. Controla tu Ventilador de Techo con Alexa: Guía Paso a Paso
  6. Paneles solares: una inversión inteligente para su hogar
  7. Cómo la tecnología de hogar inteligente transforma la vida cotidiana
  8. Cerrando la Brecha de Habilidades en Hogar Inteligente: Por Qué Reino Unido Rezaga en Europa
  9. Evolución del Hogar Inteligente: Qué Nos Depara el Futuro de la Vida Conectada
  10. Seguridad inteligente: Estrategias de expertos para proteger sus dispositivos IoT domésticos de hackers
  11. Cómo Fortalecer la Seguridad de tu Hogar Inteligente: Consejos de Expertos