PuzzleBox
Componentes e suprimentos
![]() |
| × | 1 |
Aplicativos e serviços online
![]() |
|
Sobre este projeto
Observação:este tutorial pode estar desatualizado, vá aqui para uma versão mais atual.
Manter seus itens valiosos longe de olhos curiosos pode ser difícil às vezes, a menos que você os coloque em um grande cofre ou algo semelhante ... mas quem tem espaço para isso?
Em vez disso, crie sua própria caixa de quebra-cabeça usando os componentes do MKR IoT Bundle e um pouco de papelão! Não podemos garantir a segurança de seus pertences, mas pelo menos será um impedimento divertido para ladrões em potencial.
Claro, aconselhamos você a esconder seus doces lá ... não objetos de valor reais.
Em poucas palavras
Para abrir a caixa, que é mantida fechada com um servo motor, você terá que girar os potenciômetros até obter a combinação certa. A combinação pode ser definida através do aplicativo online Blynk. Um LED o ajudará a adivinhar, fornecendo feedbacks de cores:quanto mais próximo você estiver, mais quente será a cor.
Quando a combinação certa é acertada, a campainha começa a tocar uma música enquanto o servo abre a caixa.
Para criar nossa caixa de quebra-cabeça, precisaremos dos seguintes componentes:
- Buzzer
- LED RGB
- 3 potenciômetros
- tela LCD
- Servo motor

Metas de aprendizagem
- Apresentando a plataforma de internet Blynk
- Fiação e uso da tela LCD
- Jogando o tema Star Wars com a campainha
Quer saber mais?
Este tutorial é parte de uma série de experimentos que o familiarizam com o MKR1000 e a IoT. Todos os experimentos podem ser construídos usando os componentes contidos no MKR IoT Bundle.
- Travesseiro Eu te amo
- Caixa de quebra-cabeça
- Gato de Pavlov
- O Nerd
- Comunicador de planta
Apresentando Blynk
Blynk é um aplicativo móvel popular para Internet das Coisas, que nos permite controlar facilmente nosso Arduino conectado à Internet de qualquer lugar, a qualquer hora.
Foi fundado no Kickstarter e rapidamente se tornou um dos aplicativos mais usados neste campo, graças à sua documentação incrível e à sua simplicidade.
Primeiros passos com Blynk
Criar um novo projeto é realmente fácil, basta seguir estes poucos passos simples ou dar uma olhada no guia oficial de introdução por Blynk.









Depois de criar um novo projeto com sucesso, você também deverá receber por e-mail o Token de autenticação. É um identificador exclusivo necessário para conectar o hardware ao smartphone. Cada novo projeto que você criar terá seu próprio token de autenticação.
Para conectar o Arduino ao aplicativo, precisaremos instalar a biblioteca Blynk. Se você estiver usando o Arduino Web Editor, o download da biblioteca será feito automaticamente quando você incluí-lo no esboço, caso contrário, você pode fazer o download do gerenciador de biblioteca.
Agora estamos prontos para ir. Carregue este esboço e brincar com os controles deslizantes para ver o resultado:
#include #include const char * ssid =SECRET_SSID; // SSID (nome) da sua rede const char * password =SECRET_PSWD; // sua senha de rede char auth [] =SECRET_TOKEN; // seu token de API Blynk // Variáveis para armazenar o valor da combinação // Defina a combinação inicial para (1 1 1) int SliderValueOne =1; int SliderValueTwo =1; int SliderValueThree =1; // Blynk funciona para recuperar valores BLYNK_WRITE (V1) {SliderValueOne =param.asInt (); // atribuindo valor de entrada do pino V1 a uma variável} BLYNK_WRITE (V2) {SliderValueTwo =param.asInt (); // atribuindo valor de entrada do pino V1 a uma variável} BLYNK_WRITE (V3) {SliderValueThree =param.asInt (); // atribuindo valor de entrada do pino V1 a uma variável} void setup () {Serial.begin (9600); Blynk.begin (autenticação, ssid, senha); // inicia as funcionalidades do Blynk e conecta-se ao WiFi} void loop () {// Variáveis para armazenar temporariamente a combinação int Temp_Slider_One_value =SliderValueOne; int Temp_Slider_Two_value =SliderValueTwo; int Temp_Slider_Three_value =SliderValueThree; Blynk.run (); // pesquisar novos valores de combinação no aplicativo online // verificar se os valores de combinação foram alterados e imprimi-los no console if (Temp_Slider_One_value! =SliderValueOne || Temp_Slider_Two_value! =SliderValueTwo || Temp_Slider_Three_value! =SliderValueThree) {Serial.print ("Novo combinação:"); Serial.print (SliderValueOne); Serial.print (""); Serial.print (SliderValueTwo); Serial.print (""); Serial.println (SliderValueThree); }}

Usando a tela LCD
É hora de conectar a tela!
A tela LCD é fácil de usar, mas requer muitos fios, então esteja pronto para provar sua paciência.

Observe que estamos usando a fonte de alimentação de 5 V e um resistor de 220 Ohms.
O brilho pode ser regulado alterando o valor de saída do pino analógico 3 de 0 a 255, sendo 0 o valor máximo.
analogWrite (A3, 0);
Agora podemos fazer o upload do esboço de exemplo e ver se tudo está funcionando bem.
// inclui o código da biblioteca:#include // inicializa a biblioteca associando qualquer pino de interface LCD necessário // com o número do pino do arduino ao qual está conectado const int rs =12, en =11, d4 =2, d5 =3, d6 =4, d7 =5; LiquidCrystal lcd (rs, en, d4, d5, d6, d7); configuração vazia () {analogWrite (A3, 0); // Configure o brilho para seu valor máximo // configure o número de colunas e linhas do LCD:lcd.begin (16, 2); // Imprime uma mensagem no LCD. lcd.print ("olá, mundo!"); } void loop () {// define o cursor para a coluna 0, linha 1 // (nota:a linha 1 é a segunda linha, já que a contagem começa com 0):lcd.setCursor (0, 1); // imprime o número de segundos desde a reinicialização:lcd.print (millis () / 1000); }
Adicionar potenciômetros
Para ler o valor dos potenciômetros, precisaremos apenas de um
analogRead ()
no pino correto. Estamos conectando-os ao pino analógico 0, 1, 2. 
Observe que o valor de um potenciômetro varia de 0 a 1023, tornando a combinação impossível de adivinhar. Para mapear esses valores de 0 a 9, usaremos o
map ()
função, int PotOne =map (analogRead (A0), 0, 1023, 0, 9);
Você pode usar este código de exemplo para imprimir na tela LCD os valores dos potenciômetros.
#include // Pinos da tela LCD const int rs =12, en =11, d4 =2, d5 =3, d6 =4, d7 =5; LiquidCrystal lcd (rs, en, d4, d5, d6, d7); configuração vazia () {analogWrite (A3, 0); // define o brilho da tela LCD para o valor máximo Serial.begin (9600); lcd.begin (16, 2); // começa a tela LCD com 16 colunas e 2 linhas} void loop () {int PotOne =map (analogRead (A0), 0, 1023, 0, 9); int PotTwo =map (analogRead (A1), 0, 1023, 0, 9); int PotThree =map (analogRead (A2), 0, 1023, 0, 9); lcd.setCursor (0, 0); lcd.print (PotOne); lcd.setCursor (2, 0); lcd.print (PotTwo); lcd.setCursor (4, 0); lcd.print (PotThree); }
Adicione o LED RGB
Usaremos o LED RGB como um feedback para ajudar as pessoas a adivinharem a combinação, quanto mais perto elas chegarem do valor certo, mais quente será a cor do LED, variando de azul, água, amarelo e vermelho.


Você pode usar este esboço de exemplo para ver o RGB em ação!
// Pinos de LED RGB int redPin =6; int greenPin =8; int bluePin =7; void setup () {pinMode (redPin, OUTPUT); pinMode (greenPin, OUTPUT); pinMode (bluePin, OUTPUT); Serial.begin (9600); } void loop () {setColor (0, 0, 255); // atraso azul (1000); setColor (0, 255, 255); // aqua delay (1000); setColor (255, 255, 0); // atraso amarelo (1000); setColor (255, 0, 0); // Atraso vermelho (1000); } // Envia valores RGB para os pinos de LED void setColor (int red, int green, int blue) {analogWrite (redPin, red); analogWrite (greenPin, verde); analogWrite (bluePin, azul); }
Conecte-o ao Blynk
Agora estamos prontos para montar as coisas:conecte a placa ao Blynk, o potenciômetro à tela LCD e faça o LED piscar na cor verde quando a combinação estiver correta.
- Observe que usaremos a função
giveColorFeedback ()
para definir a cor do LED quando o valor absoluto de cada potenciômetro estiver mais próximo do que um certo limite da combinação correta.
void giveColorFeedback (int PotOne, int PotTwo, int PotThree) {...}
- Também usaremos essas variáveis para armazenar os valores enviados do aplicativo e, portanto, a combinação.
int SliderValueOne =1; int SliderValueTwo =1; int SliderValueThree =1;
Observe que o valor inicial é definido como 1, ele mudará apenas se você modificar os valores dos controles deslizantes no aplicativo. Se você reiniciar o tabuleiro, a combinação voltará ao valor padrão.
- Uma variável booleana
bool start =true;
é usado para detectar quando a combinação já foi adivinhada, para evitar reabrir a caixa a cada loop.
Carregue este esboço de exemplo para vê-lo em ação:
#include #include #include #include // Pinos de LED RGB int redPin =6; int greenPin =8; int bluePin =7; const char * ssid =SECRET_SSID; // SSID (nome) da sua rede const char * password =SECRET_PSWD; // sua senha de rede char auth [] =SECRET_TOKEN; // seu token de API Blynk // pinos da tela LCD const int rs =12, en =11, d4 =2, d5 =3, d6 =4, d7 =5; bool start =true; // Variáveis para armazenar o valor da combinação // Defina a combinação inicial para (1 1 1) int SliderValueOne =1; int SliderValueTwo =1; int SliderValueThree =1; // Blynk funciona para recuperar valores BLYNK_WRITE (V1) {SliderValueOne =param.asInt (); // atribuindo valor de entrada do pino V1 a uma variável} BLYNK_WRITE (V2) {SliderValueTwo =param.asInt (); // atribuindo valor de entrada do pino V1 a uma variável} BLYNK_WRITE (V3) {SliderValueThree =param.asInt (); // atribuindo valor de entrada do pino V1 a uma variável} LiquidCrystal lcd (rs, en, d4, d5, d6, d7); void setup () {pinMode (redPin, OUTPUT); pinMode (greenPin, OUTPUT); pinMode (bluePin, OUTPUT); analogWrite (A3, 0); // define o brilho da tela LCD para o valor máximo Serial.begin (9600); lcd.begin (16, 2); // inicia a tela LCD com 16 colunas e 2 linhas Blynk.begin (auth, ssid, senha); // inicia as funcionalidades do Blynk} void loop () {// Variáveis para armazenar temporariamente a combinação int Temp_Slider_One_value =SliderValueOne; int Temp_Slider_Two_value =SliderValueTwo; int Temp_Slider_Three_value =SliderValueThree; Blynk.run (); // pesquisar novos valores de combinação no aplicativo online // verificar se os valores de combinação foram alterados e imprimi-los no console if (Temp_Slider_One_value! =SliderValueOne || Temp_Slider_Two_value! =SliderValueTwo || Temp_Slider_Three_value! =SliderValueThree) {Serial.print ("Novo combinação:"); Serial.print (SliderValueOne); Serial.print (""); Serial.print (SliderValueTwo); Serial.print (""); Serial.println (SliderValueThree); } int PotOne =map (analogRead (A0), 0, 1023, 0, 9); int PotTwo =map (analogRead (A1), 0, 1023, 0, 9); int PotThree =map (analogRead (A2), 0, 1023, 0, 9); lcd.setCursor (0, 0); lcd.print (PotOne); lcd.setCursor (2, 0); lcd.print (PotTwo); lcd.setCursor (4, 0); lcd.print (PotThree); if (start) {giveColorFeedback (PotOne, PotTwo, PotThree); if (PotOne ==SliderValueOne &&PotTwo ==SliderValueTwo &&PotThree ==SliderValueThree) {blinkGreenLed (); início =falso; }} if (! start) {if (PotOne ==0 &&PotTwo ==0 &&PotThree ==0) {start =true; }}} // Dê feedback com base na proximidade do potenciômetro do valor de combinação // Quanto mais perto, mais quente é a cor do LED void giveColorFeedback (int PotOne, int PotTwo, int PotThree) {if (abs (PotOne - SliderValueOne) <=1 &&abs (PotTwo - SliderValueTwo) <=1 &&abs (PotThree - SliderValueThree) <=1) {// Red setColor (255, 0, 0); } else if (abs (PotOne - SliderValueOne) <=3 &&abs (PotTwo - SliderValueTwo) <=3 &&abs (PotThree - SliderValueThree) <=3) {// yellow setColor (255, 255, 0); } else if (abs (PotOne - SliderValueOne) <=4 &&abs (PotTwo - SliderValueTwo) <=4 &&abs (PotThree - SliderValueThree) <=4) {// aqua setColor (0, 255, 255); } else {// blue setColor (0, 0, 255); }} void blinkGreenLed () {for (int a =0; a <2; a ++) {for (int b =0; b <=255; b + =5) {setColor (0, b, 0); atraso (5); } para (int b =255; b> =0; b - =5) {setColor (0, b, 0); atraso (5); }} para (int b =0; b <=255; b + =5) {setColor (0, b, 0); atraso (5); }} // Envia valores RGB para os pinos de LED void setColor (int vermelho, int verde, int azul) {analogWrite (redPin, red); analogWrite (greenPin, verde); analogWrite (bluePin, azul); }
Adicione a campainha
Usaremos a campainha para tocar uma melodia quando a caixa for aberta. Mais precisamente, tocaremos a música-tema de Star Wars!
Conectar a campainha é simples:

Faça upload deste código de exemplo e ouça:
const int c =261; const int d =294; const int e =329; const int f =349; const int g =391; const int gS =415; const int a =440; const int aS =455; const int b =466; const int cH =523; const int cSH =554; const int dH =587; const int dSH =622; const int eH =659; const int fH =698; const int fSH =740; const int gH =784; const int gSH =830; const int aH =880; contador interno =0; # define buzzerPin 1 void setup () {pinMode (buzzerPin, OUTPUT); Serial.begin (9600); } void loop () {play_jingle (); atraso (3000); } void play_jingle () {beep (a, 500); bip (a, 500); bip (a, 500); bip (f, 350); bip (cH, 150); bip (a, 500); bip (f, 350); bip (cH, 150); bip (a, 650); atraso (500); bip (eH, 500); bip (eH, 500); bip (eH, 500); bip (fH, 350); bip (cH, 150); bip (gS, 500); bip (f, 350); bip (cH, 150); bip (a, 650); atraso (500); } void beep (int note, int duration) {// Toca o tom no buzzerPin tone (buzzerPin, nota, duração); // Interrompe o tom no buzzerPin noTone (buzzerPin); atraso (50); // Incrementa o contador ++; }
Adicione o servo motor
O servo motor é a fechadura da nossa caixa, vamos precisar que ele gire 90 graus quando a combinação estiver correta, para que a caixa se abra.
Conectar o servo requer apenas três fios.

Para girar 90 graus, usaremos as seguintes funções:
#include int pos =0; // variável para armazenar a posição do servo Servo myservo; // cria um objeto servo para controlar um servo void setup () {myservo.attach (9); // anexa o servo no pino 9 ao objeto servo myservo.write (pos); // define o servo na posição 0} void loop () {open_the_box (); atraso (2000); close_the_box (); atraso (2000); } void open_the_box () {for (pos =0; pos <=90; pos + =1) {// vai de 0 graus a 90 graus myservo.write (pos); // diz ao servo para ir para a posição na variável 'pos' delay (15); // espera 15ms para o servo alcançar a posição}} void close_the_box () {for (pos =90; pos> =0; pos - =1) {// vai de 90 graus para 0 graus myservo.write (pos); // diz ao servo para ir para a posição na variável 'pos' delay (15); // espera 15ms para o servo atingir a posição}}
Observe que para girar o servo de volta e fechar a caixa, tudo o que você precisa fazer é girar todo o potenciômetro para 0.
Construa sua caixa de quebra-cabeça
Não seria uma caixa sem uma caixa, então baixe o arquivo do caso abaixo e use-o como guia para construir o seu próprio.
Observe que usamos um papelão de 2 mm.
Código
Esboço completo
Peças personalizadas e gabinetes
Papelão de 2 mm box_E5j7tnFdNC.dxfEsquemas

Processo de manufatura