Smart Cube: Hub de Controle Residencial de Próxima Geração
Componentes e Materiais Necessários
| Componente | Quantidade | Observações |
|---|---|---|
| Arduino 101 | 1 | |
| LED (genérico) | 5 | 1 azul - 1 amarelo - 1 verde - 2 vermelhos |
| Resistor 221 ohm | 5 | |
| Protoboard (genérica) | 1 | Não obrigatório |
| 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 | |
| Keypad | 1 | |
| Jumpers (genéricos) | 1 | |
| Bateria 9V (genérica) | 1 | |
| Conector de Bateria 9V | 1 | |
| Fibra de Média Densidade (MDF) 20x30 cm | 1 | 3mm MDF ou outro material para corte a laser |
Ferramentas e Máquinas Necessárias
- Cortadora a laser (genérica)
- Ferro de solda (genérico)
Aplicativos e Serviços Online
- Arduino IDE
- Nordic Semiconductor nRF Connect SDK (não obrigatório)
Sobre o Projeto
O que é o SMART CUBE?
O Smart Cube é um controlador para seus dispositivos de casa inteligente.
Hoje em dia, gerenciar de forma mais inteligente todos os dispositivos em nossas casas está se tornando uma exigência. Precisamos de algo simples e intuitivo de usar. O Smart Cube pode ser uma solução: é um dispositivo portátil que contém uma placa Arduino 101 e alguns sensores que se comunicam com os eletrodomésticos e atuadores em sua casa inteligente.
A inovação deste controlador remoto está relacionada à inovação da placa Arduino 101. Ele usa Bluetooth (BLE) para controlar luzes, temperatura e sua TV, e você também pode sincronizá-lo com seu smartphone. Mas a grande inovação é a forma como você interage com o Smart Cube com seus gestos usando o giroscópio e o acelerômetro. O cubo tem 6 faces e cada uma controla uma função específica. A função que você deseja usar é detectada graças ao giroscópio que reconhece a face superior. Por exemplo, você pode acender as luzes do ambiente em que está apenas posicionando o cubo com a "face de luz" na posição superior. Se quiser apagar a luz, basta sacudir o cubo.
Se uma face estiver PARA CIMA e não se mover por mais de 2 segundos, a função relacionada é ativada. Este atraso é feito para que você possa ter tempo para girar e interagir com o cubo para encontrar a face que precisa sem ativar acidentalmente outras funções. Quando você sacode o cubo por mais de 2 segundos, a última função ativada é fechada.
Este projeto visa ajudá-lo a construir um controlador inteligente. Este dispositivo precisa de um receptor (central inteligente na imagem) que interprete os dados e gerencie as funções de sua casa inteligente. A principal saída do cubo é um sinal BLE que pode ser usado de várias maneiras: por exemplo, você pode conectar o cubo com um aplicativo para smartphone (ou criar o seu próprio), ou pode construir uma estação com outro Arduino que colete os dados BLE e controle diretamente os eletrodomésticos de sua casa. Devido à variedade de casos, esta parte depende de sua necessidade. Neste guia, veremos como construir um smart cube e você aprenderá como personalizá-lo.
Funções
A estrutura do código é fácil de personalizar (analisamos o código depois) para que você possa decidir quais funções controlar. Estas são as funções que decidi controlar:
LUZES: Esta face na posição PARA CIMA acende as luzes do ambiente em que você está. Se você sacudir o cubo, as luzes apagam e um LED amarelo nesta face é ativado para que você encontre o cubo no escuro. A comunicação com suas lâmpadas é feita pelo BLE da placa 101.
TEMPERATURA: Esta face PARA CIMA ativa (via BLE) o ar condicionado se estiver quente ou o aquecimento se estiver frio. Detecta a temperatura usando um sensor térmico e acende um LED azul se o condicionador estiver ligado (floco de neve) ou um vermelho se o aquecimento estiver ativado (sol).
TIMER: Esta face PARA CIMA inicia um temporizador que você pode ver no display LCD. Há um buzzer que funciona como alarme quando a contagem regressiva termina. Se você sacudir, para o temporizador e vê o tempo restante. Quando a contagem termina, a cor do LCD muda de azul para vermelho e o buzzer emite três sons.
TV: Esta face PARA CIMA liga a TV. O cubo se torna um controle remoto para sua TV. Há um painel de botões com números que é ativado apenas se esta face estiver PARA CIMA, para evitar toques acidentais. O número que você pressiona é enviado via BLE para o controlador central conectado à sua TV. Sacudindo o cubo, você desliga a TV.
SOM: Esta face PARA CIMA ativa um LED cujo brilho é baseado no nível de ruído do ambiente. O ruído é detectado graças a um sensor de som. Se você sacudir o cubo, fecha esta função. (Se quiser, pode ativar sua função pessoal batendo palmas).
FACE OFF: Se você não sacudir o cubo, esta face é como uma posição neutra na qual nada é alterado. Se quiser fechar tudo, posicione o cubo com a face OFF PARA CIMA e sacuda-o. Este gesto é como o botão home do seu smartphone que você pressiona se quiser sair rapidamente. Há um LED vermelho para que você encontre o cubo se estiver escuro.
Diferenças do Conceito Original
O plano original era usar também comunicação IR para conectar sua TV diretamente ao cubo. Como o Arduino 101 não suporta (por enquanto) a biblioteca que gerencia sinais IR, decidi enviar as informações via BLE para uma estação que possa gerenciar esta biblioteca (como Arduino UNO). Por causa desse problema, removi a função rádio (muito similar à face TV), substituindo-a por uma face com sensor de som. Esta face pode ser usada para reconhecer um ruído alto (como bater palmas) para ativar algo. A maior mudança está no material do cubo. Inicialmente pensei em construí-lo com uma impressora 3D, mas depois decidi usar um cortador a laser. Dessa forma, é mais fácil substituir uma face se você quiser mudar uma função. Por exemplo, você pode remover a face do timer e trocá-la por uma que encha automaticamente o pote do seu gato. Sendo modular, você não precisa reconstruir toda a estrutura!
Vamos Construí-lo
Siga estas instruções para construir seu próprio smart cube. Começaremos pelo hardware, montando os componentes eletrônicos primeiro e depois o corpo do cubo cortado a laser feito de MDF. Após esta operação, explicarei como o código funciona e como você pode personalizá-lo. Depois de fazer o upload do código no seu Arduino 101, você pode baixar o aplicativo para ver a saída BLE do cubo ou conectá-lo diretamente com sua casa inteligente!
Hardware - Eletrônica
Vamos começar pelo seu Arduino 101. Este é o esquema fritzing a seguir:
Monte o Grove base shield na sua placa e comece com as conexões.
Keypad: você deve conectar os fios em ordem aos pinos: 10, 8, 7, 6, 5, 4, 2.
Conexões dos LEDs:
Primeiro, temos que preparar os LEDs:
- Conecte a perna longa do LED (ânodo) a um resistor de 220 ohm e depois a um fio vermelho (este é o cabo para conectar ao pino)
- Conecte a perna curta (cátodo) a um fio branco (este irá para o GND)
- Solde as partes e cubra-as com fita isolante
- Conecte todos os cabos brancos a um único cabo branco (este irá para o GND) e solde-os todos juntos
Agora conecte os fios vermelhos ao seu Arduino: LED VERDE no pino 9, LED AMARELO no pino 11, LED VERMELHO no pino 12, LED AZUL no pino 13 e o último VERMELHO no pino A2.
Sensores Grove:
Conecte os sensores Grove ao shield (veja o esquema nos anexos).
Buzzer no D3, LCD RGB no I2C, Sensor de temperatura no A0, Sensor de som no A1.
Ok, agora conectamos todas as partes elétricas. Agora você precisa do gabinete.
Hardware - Caixa
Você pode baixar o esboço do cubo para cortar com laser. As linhas vermelhas no esboço são os símbolos das faces, apenas grave elas. As linhas pretas devem ser cortadas. A dimensão interna do cubo é 9 cm. O esboço está ok se você usar material de 3mm, se usar espessura diferente, deve modificá-lo (pode usar este site: https://www.makercase.com/).
O material que escolhi é MDF (Fibra de Média Densidade), mas você pode usar o que quiser.
Aqui estão algumas fotos do corte a laser:
Agora temos que montá-lo.
Eu colei alguns pedaços de papelão para dar espessura aos LEDs. Dessa forma, eles ficarão alinhados com a superfície.
Agora montamos o keypad. Insira-o no furo e remova a película adesiva, depois reconecte os pinos.
Agora o LCD RGB. Este encaixa perfeitamente no furo.
Vamos preparar o conector da bateria:
Cortei um plug de transformador velho e conectei a um clipe de bateria. Dessa forma, economizamos espaço dentro da caixa.
Neste ponto, é isso que você deve ter:
Agora você só precisa conectar a bateria, fazer o upload do código e fechar o cubo!
DICA: fixe a placa e a bateria no gabinete para que, quando você sacudir o cubo, eles fiquem estáveis.
Código
Você pode encontrar o código nos anexos. Faça o upload na sua placa com o Arduino IDE (lembre-se de atualizar seu software para compatibilidade com Arduino 101).
Eu comentei quase todas as linhas do código para torná-lo o mais compreensível possível. Não se assuste com as 500+ linhas, a estrutura não é tão complicada.
No início estão as bibliotecas e todas as variáveis de declaração.
Nesta parte também há a definição de serviços e características BLE. Usei o serviço Automation IO. Usei a característica Digital para luzes e temperatura (usa 2 bits, então 4 casos possíveis para codificar) e a Analog para TV (para enviar todos os códigos do keypad).
Então o setup. Esta parte é executada apenas uma vez no início. Aqui inicializamos os componentes como entradas ou saídas e inicializamos o BLE e o giroscópio da placa 101.
A parte principal é o loop. Ele é dividido em quatro partes:
- 1 A primeira parte é copiada do tutorial do site Arduino: (https://www.arduino.cc/en/Tutorial/Genuino101CurieIMUAccelerometerOrientation) esta parte é constantemente executada e retorna a orientação da placa.
- 2 A segunda parte ativa uma face apenas se ela estiver na posição superior por mais de dois segundos. Usamos a função millis para contar o tempo. Quando a posição muda, memoriza o valor de millis e se a orientação permanecer a mesma, após um intervalo (2 seg), entramos em uma zona if onde a face selecionada se torna verdadeira (para a 4ª parte).
- 3 A terceira parte é ativada apenas se o cubo for sacudido com certa intensidade e por mais de 2 segundos. A última face ativada tem sua função fechada e a face é definida como false. Se a face for false, não pode entrar na 4ª parte.
- 4 A quarta parte é apenas para faces true. Aqui está o núcleo das funções do smart cube. Nesta parte, são executadas constantemente apenas as faces que são true no loop.
Você pode modificar as funções das faces com algumas modificações no código. A estrutura principal deve ser como descrita. Você pode mudar a parte dentro das condições if de cada face.
if (face2 == true) { // face TEMPERATURA
// INÍCIO DA PERSONALIZAÇÃO
digitalWrite (LEDOFF, LOW); // se esta face é true, o LED da face OFF fica LOW
if (central.connected() == true) { // se o cubo está conectado via BLE
// lê valor de temperatura
int val = analogRead(pinTemp); // obtém valor analógico
resistance=(float)(1023-val)*10000/val; // obtém resistência
temperature=1/(log(resistance/10000)/B+1/298.15)-273.15; // calcula temperatura
// condições de ativação
if (temperature > tooHot) { // ativar ar condicionado
digitalWrite(LEDhot, LOW); // fechar LED de aquecimento
digitalWrite(LEDcold, HIGH); // abrir LED de ar condicionado
termoChar.setValue(1); // definir via BLE a condição 1 = frio ligado - quente desligado
}
if (temperature < tooCold) { // ativar aquecimento
digitalWrite(LEDhot, HIGH);
digitalWrite(LEDcold, LOW);
termoChar.setValue(2); // 2 = frio desligado - quente ligado
}
if (temperature > tooCold && temperature < tooHot) { // temperatura ideal: nada ativado
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // 0 = frio desligado - quente desligado
}
}
// FIM DA PERSONALIZAÇÃO
}
Você deve codificar a parte "true" (como no código anterior) e também a parte "false" quando o cubo é sacudido:
// Desativação TEMPERATURA
if (lastFUNCTION == 2) { // face TEMPERATURA
// INÍCIO DA PERSONALIZAÇÃO
// se um central está conectado ao peripheral:
if (central.connected() == true) {
digitalWrite(LEDhot, LOW); // fechar LED vermelho de temperatura
digitalWrite(LEDcold, LOW); // fechar LED azul de temperatura
termoChar.setValue(0); // sinal BLE temperatura: 0 = frio desligado - quente desligado
// FIM DA PERSONALIZAÇÃO
}
Serial.println("TEMPERATURA false - FECHAR");
face2 = false; // face TEMPERATURA torna-se false
}
Lembre-se de definir a face como false quando sacudir.
Aplicativo
Para ver as saídas BLE do cubo, você pode baixar este aplicativo: nRF Connect
https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=it
Quando abri-lo, apenas busque por dispositivos e conecte com "smartcubesketch". Então você verá três abas "Automation IO", clique nelas e pressione o coletor de dados contínuo.
É importante conectar o cubo porque algumas funções (luzes, temperatura e TV) são executadas apenas se o cubo estiver conectado.
Como Funciona: VÍDEO
Faça o upload do código, insira a bateria, feche a caixa e...
...agora você tem um SMART CUBE!
Fiz um vídeo para mostrar todas as funções do cubo e como usá-lo.
Conclusões
Este projeto é apenas o primeiro passo para uma casa inteligente. Meu objetivo era usar o potencial da placa Arduino 101 para criar algo novo. Acho que o acelerômetro e o giroscópio dão à placa novas oportunidades em termos de mobilidade. Com o BLE, além de ser portátil, também é fácil de conectar.
Esta é a primeira vez que realizo concretamente um dos meus projetos (quero dizer, com um protótipo funcional). Foi difícil e houve algumas dificuldades no caminho, mas no final aprendi muito e estou feliz com o resultado. Espero que todos que lerem este guia também possam aprender algo com meu trabalho e modificar este projeto para suas necessidades. Peço desculpas pelo meu inglês ruim, mas espero que as imagens possam ajudar.
No futuro deste projeto, espero criar a central que é como a ponte entre o smart cube e os atuadores (luzes, temperatura, tv...). Esta central receberá o sinal BLE do cubo e usará esta informação para fazer coisas inteligentes em sua casa.
Estou muito feliz por ter a oportunidade de usar o Arduino 101 e o Grove kit (o kit é muito simples e rápido para prototipagem).
Espero que usar a placa desta forma possa ser uma inspiração para seu projeto. Você pode personalizá-lo como quiser: Tenho curiosidade para ver quais funções você criará e em que contextos diferentes você o usará!
Talvez não seja uma revolução, mas é uma nova forma de interagir com sua casa.
Espero que tenha gostado deste tutorial.
Agora é sua vez: coloque as mãos no cubo e faça seu hack!
Código Completo
SMART CUBE - Código completo com comentários (Arduino)
// Bibliotecas
#include "CurieIMU.h" // Acelerômetro & Giroscópio
#include <CurieBLE.h> // Bluetooth Low Energy
#include <Wire.h>
#include "rgb_lcd.h" // LCD
#include <Keypad.h> // Keypad
rgb_lcd lcd; // Inicialização do LCD
// Inicialização do Bluetooth:
BLEPeripheral blePeripheral; // Dispositivo Peripheral BLE (a placa que você está programando)
// Serviços BLE
BLEService lightsService("1815"); // BLE Automation IO (1815) - informações de luzes
BLEService termoService("1815"); // BLE Automation IO - informações de temperatura
BLEService TVService("1815"); // BLE Automation IO - informações de TV
// Características BLE
BLEUnsignedCharCharacteristic lightsChar("2A56", // Característica BLE Digital (2A56) - luzes
BLERead | BLENotify);
BLEUnsignedCharCharacteristic termoChar("2A56", // Característica BLE Digital - temperatura
BLERead | BLENotify);
BLEUnsignedCharCharacteristic TVChar("2A58", // Característica BLE Analog (2A58) - TV
BLERead | BLENotify);
// Constantes e declaração de variáveis:
// Funções de orientação da face e shake:
int lastOrientation = -1; // orientação anterior (para comparação)
unsigned long previousMillis = 0; // última atualização de tempo
unsigned long interval = 2000; // tempo para esperar na posição superior antes da ativação da face
unsigned long SHAKEpreviousMillis = 0; // última atualização de tempo
unsigned long SHAKEinterval = 2000; // tempo para esperar durante o shake para desativação da face
boolean keep = false; // usado para contar apenas uma vez a mudança de orientação da face
int lastFUNCTION = -1; // usado para saber qual era a orientação anterior
// Inicialização das faces: no início, cada face é false
boolean face0 = false;
boolean face1 = false;
boolean face2 = false;
boolean face3 = false;
boolean face4 = false;
boolean face5 = false;
// Face LUZES
const int LEDlights = 11; // pino 11: LED amarelo
// Face TEMPERATURA
const int pinTemp = A0; // pino A0: sensor de temperatura
const int LEDhot = 12; // pino 12: LED vermelho
const int LEDcold = 13; // pino 13: LED azul
float temperature; // valor de temperatura memorizado
int B=3975; // valor B do termistor
float resistance; // valor de resistência memorizado
float tooHot = 26.0; // temperatura na qual o ar condicionado é ativado [CONFIGURÁVEL]
float tooCold = 23.0; // temperatura na qual o aquecedor é ativado [CONFIGURÁVEL]
// Face TIMER
int BUZZER = 3; // pino 3: buzzer
boolean KEEPtime = false; // usado para contar apenas uma vez a mudança de orientação (não reiniciar enquanto conta)
int TIMERmillis = 0; // para determinação da contagem regressiva
int prevSHOWsecond = 0;
int CountdownInMillis = 0;
int SHOWmillis = 0; // valor de millis calculado
int SHOWminute = 0; // valor de minutos para mostrar no monitor na contagem regressiva
int SHOWseconds = 0; // valor de segundos para mostrar no monitor na contagem regressiva
const int SETminute = 2; // definir timer de 2 minutos [CONFIGURÁVEL]
const int SETsecond = 30; // definir timer de 30 segundos [CONFIGURÁVEL]
// Face SOM
const int soundLED = 9; // pino 9: LED verde
const int soundSENSOR = A1; // pino A0: sensor de som
int brightness = 0; // inicialização do brilho do LED verde
// Face TV
const byte ROWS = 4; // quatro linhas do keypad
const byte COLS = 3; // três colunas do keypad
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
}; // valores dos botões do keypad
byte rowPins[ROWS] = {10,8,7,6}; // pinos 10,8,7,6: conectar aos pinos de linha do keypad
byte colPins[COLS] = {5,4,2}; // pinos 5,4,2: conectar aos pinos de coluna do keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // inicialização do keypad
// Face OFF
const int LEDOFF = A2; // pino A2: LED vermelho
void setup() {
pinMode(LEDlights, OUTPUT); // cada LED é definido como saída
pinMode(LEDhot, OUTPUT);
pinMode(LEDcold, OUTPUT);
pinMode(soundLED, OUTPUT);
pinMode(LEDOFF, OUTPUT);
Serial.begin(9600); // inicializa comunicação Serial
CountdownInMillis = (SETminute*60 + SETsecond)*1000; // calcula o valor correspondente em millis a partir de minutos e segundos
lcd.begin(16, 2); // Inicialização do LCD
lcd.setRGB(0, 0, 0); // LCD RGB está DESLIGADO no início
// Inicialização do dispositivo
Serial.println("Inicializando dispositivo IMU...");
CurieIMU.begin(); // Inicializa IMU
// Define o alcance do acelerômetro para 2G
CurieIMU.setAccelerometerRange(2);
// Habilita Detecção de Choque
CurieIMU.setDetectionThreshold(CURIE_IMU_SHOCK, 7000); // 7.0g = 7000 mg (este valor define a intensidade do choque)
CurieIMU.setDetectionDuration(CURIE_IMU_SHOCK, 2000); // 2000ms (este valor define a duração do choque)
CurieIMU.interrupts(CURIE_IMU_SHOCK);
// Inicialização do BLE
blePeripheral.setLocalName("SmartCubeSketch"); // nome do projeto
blePeripheral.setAdvertisedServiceUuid(lightsService.uuid()); // adiciona UUID do serviço de luzes
blePeripheral.addAttribute(lightsService); // adiciona serviço BLE de luzes
blePeripheral.addAttribute(lightsChar); // adiciona característica BLE de luzes
lightsChar.setValue(3); // valor inicial para esta característica = 3
// Significado do valor BLE lights: 0 = luzes desligadas, 1 = luzes ligadas, 3 = estado inicial, 4 = não usado
blePeripheral.setAdvertisedServiceUuid(termoService.uuid()); // adiciona UUID do serviço de temperatura
blePeripheral.addAttribute(termoService); // adiciona serviço BLE de temperatura
blePeripheral.addAttribute(termoChar); // adiciona característica BLE de temperatura
termoChar.setValue(0); // valor inicial é 0: frio desligado - quente desligado
// Significado do valor BLE termo: 0 = frio desligado - quente desligado, 1 = frio ligado - quente desligado, 2 = frio desligado - quente ligado, 3 = não usado
blePeripheral.setAdvertisedServiceUuid(TVService.uuid()); // adiciona UUID do serviço de TV
blePeripheral.addAttribute(TVService); // adiciona serviço BLE de TV
blePeripheral.addAttribute(TVChar); // adiciona característica de TV
TVChar.setValue('x'); // valor inicial para esta característica (x significa nada)
// Significado do valor BLE TV: #número corresponde ao botão pressionado, C: fechar TV, O: abrir TV, x: estado inicial
blePeripheral.begin();
Serial.println("Dispositivo Bluetooth ativo, aguardando conexões...");
}
// Fim do setup
void loop() {
BLECentral central = blePeripheral.central(); // Conexão BLE
unsigned long currentMillis = millis(); // valor atual do tempo em millissegundos
// O código a seguir vem de www.arduino.cc/en/Tutorial/Genuino101CurieIMUccelerometerOrientation
// é usado para detectar a orientação da placa
int orientation = -1; // orientação da placa
String orientationString; // string para imprimir descrição da orientação
// Lê acelerômetro:
int x = CurieIMU.readAccelerometer(X_AXIS);
int y = CurieIMU.readAccelerometer(Y_AXIS);
int z = CurieIMU.readAccelerometer(Z_AXIS);
// Calcula valores absolutos para determinar o maior
int absX = abs(x);
int absY = abs(y);
int absZ = abs(z);
if ((absZ > absX) && (absZ > absY)) {
// orientação baseada no Z
if (z > 0) {
orientationString = "up";
orientation = 0;
} else {
orientationString = "down";
orientation = 1;
}
} else if ((absY > absX) && (absY > absZ)) {
// orientação baseada no Y
if (y > 0) {
orientationString = "pinos digitais up";
orientation = 2;
} else {
orientationString = "pinos analógicos up";
orientation = 3;
}
} else {
// orientação baseada no X
if (x < 0) {
orientationString = "conector up";
orientation = 4;
} else {
orientationString = "conector down";
orientation = 5;
}
}
// Fim do código do tutorial.
// Neste ponto, você tem o valor de orientação da placa constantemente atualizado:
/* As orientações da placa:
0: plana, processador virado para cima (TIMER)
1: plana, processador virado para baixo (TV)
2: paisagem, pinos analógicos para baixo (TEMPERATURA)
3: paisagem, pinos analógicos para cima (OFF)
4: retrato, conector USB para cima (LUZES)
5: retrato, conector USB para baixo (SOM) */
// Para este projeto, você precisa saber se a face mudou da face anterior [lastFUNCTION != orientation]
// Mas esta informação é impressa apenas se a face estiver na posição UP por mais de [interval] tempo
// E apenas por uma vez [keep] (você não precisa ativar a face constantemente, precisa apenas uma vez)
// Como o valor de orientação é constantemente atualizado, você precisa começar a contar o tempo quando a orientação muda [orientation != lastOrientation]
if (orientation != lastOrientation) {
// Se a orientação mudou, começa a contar o tempo
lastOrientation = orientation; // memoriza a orientação atual da face
previousMillis = currentMillis; // memoriza o tempo quando a face mudou
keep = false;
} else if (currentMillis - previousMillis > interval && keep == false && lastFUNCTION != orientation) {
// Esta condição imprime a orientação apenas se a face estiver para cima por um intervalo
// E apenas por uma vez (keep)
// E apenas se a face for diferente do loop anterior
Serial.println(orientationString); // imprime a orientação
// A face atual [orientation] é definida como true (isso significa que a função da face é definida como ativada)
if (orientation == 1) { // face TV
face1 = true; // face TV torna-se true
lastFUNCTION = orientation; // memoriza esta ativação em [lastFUNCTION]
Serial.println("TV true"); // imprime a face ativada
TVChar.setValue('O'); // O: sinal de abrir TV (BLE): TV aberta apenas uma vez
}
if (orientation == 4) { // face LUZES
face4 = true;
lastFUNCTION = orientation;
Serial.println("LUZES true");
}
if (orientation == 3) { // face OFF
face3 = true;
lastFUNCTION = orientation;
Serial.println("OFF true");
}
if (orientation == 5) { // face SOM
face5 = true;
lastFUNCTION = orientation;
Serial.println("SOM true");
}
if (orientation == 2) { // face TEMPERATURA
face2 = true;
lastFUNCTION = orientation;
Serial.println("TEMPERATURA true");
}
if (orientation == 0) { // face TIMER
face0 = true;
lastFUNCTION = orientation;
Serial.println("TIMER true");
if (KEEPtime == false) { // timer ativado apenas se for o 1º ciclo ou foi parado
TIMERmillis = currentMillis; // começa a contar o tempo
}
}
keep = true; // [keep] muda valor para que, no próximo loop, não possa entrar nesta condição se a face não mudar (evita ativar novamente a mesma face)
}
// Esta condição é para a função shake: se você sacudir por mais de [SHAKEinterval] tempo, a face é desativada
if (CurieIMU.getInterruptStatus(CURIE_IMU_SHOCK) && currentMillis - SHAKEpreviousMillis > SHAKEinterval) {
Serial.println("SHAKE"); // imprime "SHAKE" se shake for detectado
// A última face ativada [lastFUNCTION] é definida como false (significa que a função da face é desativada)
// Desativação TV
if (lastFUNCTION == 1) { // face TV
TVChar.setValue('C'); // C: fechar sinal BLE da TV
Serial.println("TV false - FECHAR"); // imprime a face fechada
face1 = false; // face TV torna-se false
}
// Desativação LUZES
if (lastFUNCTION == 4) { // face LUZES
if (central.connected() == true) { // se um central está conectado ao peripheral:
lightsChar.setValue(0); // sinal BLE luzes DESLIGADAS
digitalWrite(LEDlights, HIGH); // abre o LED amarelo para ver o cubo no escuro
}
Serial.println("LUZES false - FECHAR");
face4 = false; // face LUZES torna-se false
}
// OFF
if (lastFUNCTION == 3) { // face OFF
// Face OFF sacudida: tudo é fechado e LED vermelho OFF é aberto
digitalWrite(LEDOFF, HIGH); // LED vermelho OFF liga quando cubo é fechado
// Agora fecha todas as funções ativadas:
// FECHAR TV
TVChar.setValue('C'); // C: fechar sinal BLE da TV
Serial.println("TV false - FECHAR");
face1 = false;
// FECHAR LUZES
Serial.println("LUZES false - FECHAR");
if (central.connected() == true) {
lightsChar.setValue(0);
digitalWrite(LEDlights, LOW); // LED de luzes é fechado se face OFF é sacudida
}
face4 = false;
// FECHAR SOM
analogWrite(soundLED, LOW); // fecha o LED de som
Serial.println("SOM false - FECHAR");
face5 = false;
// FECHAR TEMPERATURA
if (central.connected() == true) {
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // sinal BLE temperatura: 0 = frio desligado - quente desligado
}
Serial.println("TEMPERATURA false - FECHAR");
face2 = false;
// FECHAR TIMER
Serial.println("TIMER false - FECHAR");
lcd.setRGB(0, 0, 0); // o RGB do LCD é fechado
lcd.clear();
KEEPtime = false;
face0 = false;
// O cubo está inativo, apenas LED OFF está ativo
Serial.println("OFF false - FECHAR");
face3 = false; // face OFF torna-se false
}
// Desativação SOM
if (lastFUNCTION == 5) { // face SOM
analogWrite(soundLED, LOW); // fecha o LED de som
Serial.println("SOM false - FECHAR");
face5 = false; // face SOM torna-se false
}
// Desativação TEMPERATURA
if (lastFUNCTION == 2) { // face TEMPERATURA
// Se um central está conectado ao peripheral:
if (central.connected() == true) {
digitalWrite(LEDhot, LOW); // fechar LED vermelho de temperatura
digitalWrite(LEDcold, LOW); // fechar LED azul de temperatura
termoChar.setValue(0); // sinal BLE temperatura: 0 = frio desligado - quente desligado
}
Serial.println("TEMPERATURA false - FECHAR");
face2 = false; // face TEMPERATURA torna-se false
}
// Desativação TIMER
if (lastFUNCTION == 0) { // face TIMER
Serial.println("TIMER false - FECHAR");
face0 = false; // face TIMER torna-se false
// Se você sacudir o cubo quando o tempo está rodando, o LCD fica vermelho e mostra o tempo restante da contagem regressiva
lcd.setRGB(180, 40, 0); // o backlight RGB torna-se vermelho
lcd.clear(); // LCD é limpo
lcd.setCursor(0, 0);
lcd.print("PARAR EM ");
lcd.setCursor(8, 0);
lcd.print(SHOWminute); // indica os minutos quando você sacode o cubo
lcd.setCursor(9, 0);
lcd.print(":");
lcd.setCursor(10, 0);
lcd.print(SHOWseconds); // indica os segundos quando você sacode o cubo
tone(BUZZER,1000,1000); // emite um som curto
delay(2000);
lcd.clear(); // limpa o LCD
lcd.setRGB(0, 0, 0); // backlight RGB do LCD é fechado
KEEPtime = false; // face TIMER torna-se false
}
SHAKEpreviousMillis = currentMillis; // memoriza o valor para o cálculo [SHAKEinterval]
}
// As instruções a seguir são executadas no loop apenas se a face estiver ativada
if (face1 == true) { // face TV
digitalWrite(LEDOFF, LOW); // se esta face é true, o LED da face OFF é LOW
if (central.connected() == true) { // se o cubo está conectado via BLE
char key = keypad.getKey(); // lê o valor do keypad
if (key && orientation == 1){ // se algo é pressionado e apenas quando a face TV está para cima (evita pressão involuntária do keypad)
if (key == '0') { // se a tecla pressionada é 0
TVChar.setValue(key); // envia o valor [key] via BLE
Serial.println(key); // imprime o botão pressionado (comente se não quiser mostrar esta informação)
}
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) { // face LUZES
digitalWrite(LEDOFF, LOW); // se esta face é true, o LED da face OFF é LOW
if (central.connected() == true) { // se um central está conectado ao peripheral:
lightsChar.setValue(1); // sinal BLE LUZES ativado
digitalWrite(LEDlights, LOW); // LED amarelo é fechado porque as luzes da casa estão ligadas
}
}
if (face3 == true) { // face OFF
// Quando face OFF está para cima, nada é feito
digitalWrite(LEDOFF, LOW); // LED OFF é ativado apenas quando o cubo é sacudido, então agora é LOW
}
if (face5 == true) { // face SOM
digitalWrite(LEDOFF, LOW); // se esta face é true, o LED da face OFF é LOW
// Sensor de som ativado, brilho do LED regulado pelo som
// Este código vem do exemplo de regulação de brilho
long sum = 0;
for (int i=0; i<32; i++) {
sum += analogRead(soundSENSOR);
}
sum >>= 5;
brightness = (sum*255)/1024; // calcula o valor de brilho
analogWrite(soundLED, brightness); // intensidade do brilho do LED verde é regulada pelo ruído
delay(50);
// Fim do exemplo de brilho
}
if (face2 == true) { // face TEMPERATURA
digitalWrite(LEDOFF, LOW); // se esta face é true, o LED da face OFF é LOW
if (central.connected() == true) { // se o cubo está conectado via BLE
// lê valor de temperatura
int val = analogRead(pinTemp); // obtém valor analógico
resistance=(float)(1023-val)*10000/val; // obtém resistência
temperature=1/(log(resistance/10000)/B+1/298.15)-273.15; // calcula temperatura
// Condições de ativação
if (temperature > tooHot) { // ativar ar condicionado
digitalWrite(LEDhot, LOW); // fechar LED de aquecimento
digitalWrite(LEDcold, HIGH); // abrir LED de ar condicionado
termoChar.setValue(1); // definir via BLE a condição 1 = frio ligado - quente desligado
}
if (temperature < tooCold){ // ativar aquecimento
digitalWrite(LEDhot, HIGH);
digitalWrite(LEDcold, LOW);
termoChar.setValue(2); // 2 = frio desligado - quente ligado
}
if (temperature > tooCold && temperature < tooHot){ // temperatura ideal: nada ativado
digitalWrite(LEDhot, LOW);
digitalWrite(LEDcold, LOW);
termoChar.setValue(0); // 0 = frio desligado - quente desligado
}
}
}
if (face0 == true) { // Face TIMER ativada
digitalWrite(LEDOFF, LOW); // se esta face é true, o LED da face OFF é LOW
// Isto calcula o tempo para mostrar no display
SHOWmillis = (CountdownInMillis - (currentMillis - TIMERmillis))/1000;
SHOWminute = SHOWmillis/60; // valor de minutos para mostrar no LCD
SHOWseconds = SHOWmillis%60; // valor de segundos para mostrar no LCD
lcd.setRGB(50, 100, 70); // abre LCD com cor RGB azul
if (prevSHOWsecond != SHOWseconds){ // atualiza a tela a cada segundo (porque atualizar a cada loop é muito rápido)
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("TIMER ");
lcd.setCursor(7, 0);
lcd.print(SETminute); // escreve os minutos que você definiu
lcd.setCursor(8, 0);
lcd.print(":");
lcd.setCursor(9, 0);
lcd.print(SETsecond); // escreve os segundos que você definiu
lcd.setCursor(0, 1);
lcd.print(SHOWminute); // escreve os minutos restantes atuais
lcd.setCursor(1, 1);
lcd.print(":");
lcd.setCursor(2, 1);
lcd.print(SHOWseconds); // escreve os segundos restantes atuais
KEEPtime = true;
prevSHOWsecond = SHOWseconds; // para atualizar a cada segundo
}
if (SHOWminute == 0 && SHOWseconds == 0) { // quando a contagem regressiva termina
lcd.clear(); // limpa o LCD
lcd.setCursor(4, 0);
lcd.setRGB(180, 40, 0); // RGB do LCD torna-se vermelho
lcd.print("TEMPO ESGOTADO");
tone(BUZZER,1000,500); // três sons
delay(900);
tone(BUZZER,1000,500);
delay(900);
tone(BUZZER,1000,1000);
delay(1500);
lcd.clear(); // limpa e fecha o LCD
lcd.setRGB(0, 0, 0);
face0 = false; // Face TIMER agora está fechada (false)
KEEPtime = false;
}
}
} // Fim do loop
Peças Personalizadas e Gabinetes
Este é o arquivo (.dxf) que você pode enviar para seu cortador a laser. Usei uma placa de fibra de média densidade (MDF) de 3mm. Corte as linhas pretas e grave as linhas vermelhas. Importante: se a espessura do seu material for diferente, você deve modificar este esboço.
smart_cube_8sVCflFmhM.dxf
O mesmo arquivo da caixa mas em formato diferente: .pdf
Esquemáticos
Este é um .jpeg do esquema Fritzing (fios amarelos estão conectados aos componentes Grove)
Este é um esquema das conexões no Grove Shield
_cI0IwUsPVZ.Base%20shield%20connections
Processo de manufatura
- Painéis Solares: Um Investimento Sábio para Sua Casa
- Por que um Design Ligeiramente Maior Pode Acelerar Inovação e Reduzir Risco
- Como Tecnologia de Casa Inteligente Transforma Vida Cotidiana
- Construa uma Rede de Sensores Sem Fio Acessível para Sua Casa
- Monitore a Temperatura da Sua Casa com Dashboard no Raspberry Pi
- Preenchendo a Lacuna de Habilidades em Casas Inteligentes: Por Que a Grã-Bretanha Fica Atrás da Europa
- Evolução Casa Inteligente: O Que o Futuro Reserva para Vida Conectada
- Segurança Inteligente: Estratégias de Especialistas para Proteger Dispositivos IoT Domésticos de Hackers
- Como Fortalecer a Segurança da Sua Casa Inteligente: Dicas de Especialistas
- Planta Inteligente IoT: Estufa Conectada com Arduino e Azure