Introduction: The Crazy Potentiometer Game

About: Artista brasileiro interessado em gambiarras no geral!

Em algum momento na internet eu me deparei com alguém que havia feito um jogo como esse, mas infelizmente, eu perdi o bookmark. Então decidi fazer minha versão, me baseando um pouco no que eu lembrava do joguinho que vi.

O jogo consiste em calibrar os três V.U.s usando os três potenciômetros. Parece moleza, mas a cada rodada, os potenciômetros são sorteados. Então, sem sempre o potenciômetro azul vai mover o ponteiro do V.U. com o Led Azul. E ainda, nem sempre o ponteiro do V.U. e o potenciômetro se movem na mesma direção . Você tem 15 segundos para encontrar a calibragem ou o sistema reinicia e troca novamente todas as posições. São 48 possibilidades diferentes!

Lista de Materiais:

  • 1 Arduino (eu usei o Nano)
  • 3 potenciômetros de 10k
  • 3 V.U.s (os meus eram de 15V e eu tive que fazer a substituição de um resistor para funcionarem com 5V do Arduino. O padrão era 15k e eu substitui por 4k7);
  • 1 Led Azul
  • 1 Led Amarelo
  • 1 Led Vermelho
  • 3 Resistores de 220 Ohms.

===

At some point on the internet I came across someone who had made a game like that, but unfortunately, I missed the bookmark. So I decided to make my version, basing myself a bit on what I remembered the little game I saw.

The game consists of calibrating the three V.U.s using the three potentiometers. It sounds like a cinch, but with each round, the pots are drawn. So without always the blue potentiometer will move the V.U pointer. with the Blue Led. And yet, not always the pointer of the V.U. and the potentiometer move in the same direction. You have 15 seconds to find the calibration or the system restarts and replaces all the positions. There are 48 different possibilities!

List of materials:

  • 1 Arduino (I used the Nano)
  • 3 pots of 10k
  • 3 V.U.s (mine were 15V and I had to do a replacement of a resistor to run with Arduino 5V. The default was 15k and I replaced with 4k7);
  • 1 Led Blue
  • 1 Led Yellow
  • 1 Led Red
  • 3 Resistors of 220 Ohms.

Step 1: Ligando Tudo No Arduino Nano

Eu costumo fazer os meus conectores e ligar diretamente no Nano, ao invés de usar um Shield.

Os leds são ligados nos pinos digitais 6, 7 e 8 através de resistores para limitar a corrente (eu usei três de 220 Ohms).

Depois eu liguei o positivo dos V.U.s nas saídas PWM 9, 10, e 11 o negativo em GND.

Também fiz outra ligação nos V.U.s, dessa vez para monitorar as tensões deles: Os pinos 3, 4 e 5. Esse passo foi muito importante aqui e eu só pude resolver com a ajuda desse link aqui:

https://arduino.stackexchange.com/questions/10041/can-i-connect-a-pwm-pin-on-one-arduino-to-an-analog-input-on-another

Desse modo eu consigo saber qual a tensão que está sendo mostrada no V.U. , já que os potenciômetros vão sempre mudar de posição e direção.

Por fim, liguei os potenciômetros nas entradas analógicas A5, A6 e A7.

Estou usando o pino A0 como seed dos meus números aleatórios.

E ainda, os pinos 12 e 13 como Buzzer e Relê.

===

I usually make my connectors and plug directly into the Nano, rather than using a shield.

The LEDs are connected to the digital pins 6, 7 and 8 through resistors to limit the current (I used three of 220 Ohms).

Then I connected the positive of the V.U.s in the outputs PWM 9, 10, and 11 the negative in GND.

I also made another call in the U.S., this time to monitor their voltages: Pins 3, 4 and 5. This step was very important here and I could only solve with the help of this link here:

https://arduino.stackexchange.com/questions/10041/can-i-connect-a-pwm-pin-on-one-arduino-to-an-analog-input-on-another

That way I can tell what voltage is being displayed in the V.U. , since the potentiometers will always change position and direction.

Finally, I connected the potentiometers to the analog inputs A5, A6 and A7.

I'm using pin A0 as the seed of my random numbers.

Also, pins 12 and 13 like Buzzer and Relay.

Step 2: Código - CODE

/**
   App:               THE CRAZY POTS
   Desenvolvido por:  Djair Guilherme (Nicolau dos Brinquedos)
   Usando ARDUINO NANO
   Abril de 2018

                      +-----+
         +------------| USB |------------+
         |            +-----+            |
    B5   | [ ]D13/SCK        MISO/D12[ ] |   B4
         | [ ]3.3V           MOSI/D11[ ]~|   B3
         | [ ]V.ref     ___    SS/D10[ ]~|   B2
    C0   | [ ]A0       / N \       D9[ ]~|   B1
    C1   | [ ]A1      /  A  \      D8[ ] |   B0
    C2   | [ ]A2      \  N  /      D7[ ] |   D7
    C3   | [ ]A3       \_0_/       D6[ ]~|   D6
    C4   | [ ]A4/SDA               D5[ ]~|   D5
    C5   | [ ]A5/SCL               D4[ ] |   D4
         | [ ]A6              INT1/D3[ ]~|   D3
         | [ ]A7              INT0/D2[ ] |   D2
         | [ ]5V                  GND[ ] |
    C6   | [ ]RST                 RST[ ] |   C6
         | [ ]GND   5V MOSI GND   TX1[ ] |   D0
         | [ ]Vin   [ ] [ ] [ ]   RX1[ ] |   D1
         |          [ ] [ ] [ ]          |
         |          MISO SCK RST         |
         | NANO-V3                       |
         +-------------------------------+

          http://busyducks.com/ascii-art-arduinos


*/
#define DEBUG


// Led Pins
#define blue  6
#define yellow 7
#define red 8


// Vu meters
#define left 9
#define center 10
#define right 11


// Potentiometers
#define bpot A7
#define ypot A6
#define rpot A5


// The readings of pins 3, 4 and 5 will detect correct number
// Connected to Vu meters, convert PWM readings into Analog Reading


#define read0 3
#define read1 4
#define read2 5


// Outputs
#define buzzer 12
#define relay 13


// Time for clue
#define timeclue 1000


//Winning Numbers 935
#define winner0 10
#define winner1 5
#define winner2 7


unsigned long ultimaRodada = 0;
unsigned long tempoRodada = 15000;


// Array tha contains pin numbers


int led[3] = {blue, yellow, red}; // Blue, Yellow, Red
int vu[3] = {left, center, right};
int pot[3] = {bpot, ypot, rpot};
int readings[3] = {read0, read1, read2};


int winner[3] = {winner0, winner1, winner2};


int pot0, pot1, pot2;
int out0, out1, out2;


const byte inactive [2] = {1, 2};


// To follow puzzle States


enum PuzzleState {Initialising, Running, Solved};
PuzzleState puzzleState = Initialising;


bool lastState = false;
int sensorValue = 0;
int outputValue = 0;


void setup() {
  for (int i = 0; i < 3; i++) {
    pinMode(led[i], OUTPUT);
    pinMode(vu[i], OUTPUT);
    pinMode(readings[i], INPUT);
  }


  // Avoiding noises!!!


  for (int j = 0; j < 9; j++) {
    pinMode(inactive [j], INPUT_PULLUP);
  }


  pinMode (relay, OUTPUT);


  randomSeed (analogRead(0));


#ifdef DEBUG
  Serial.begin(9600);
  Serial.println(F("Starting Serial Communication... SETUP"));
#endif
  digitalWrite (blue, LOW);
  digitalWrite (yellow, LOW);
  digitalWrite (red, LOW);


  puzzleState = Running;
}


void loop() {


  digitalWrite (relay, LOW);
  maxMinVu (0);
  delay (500);


  setLed (HIGH, LOW, LOW);
  analogWrite (left, 255);
  delay(timeclue);


  setLed (LOW, HIGH, LOW);
  analogWrite (center, 255);
  delay(timeclue);


  setLed (LOW, LOW, HIGH);
  analogWrite (right, 255);
  delay(timeclue);


  maxMinVu(0);


  ultimaRodada = millis();


  int choice = random (1, 48); // 48 probabilities!


  while ((millis() - ultimaRodada < tempoRodada)) {


    sorteio (choice);


    // reading VU values and Map it to numbers 0 to 10
    int number0 = map (readPWM(read0), 0, 1023, 0, 10);
    int number1 = map (readPWM(read1), 0, 1023, 0, 10);
    int number2 = map (readPWM(read2), 0, 1023, 0, 10);


    //Detect if evaluated numbers are the winners!;

    if (evaluate (number2, number1, number0)) {
      onSolve();
      delay(10000);
    } else if (!evaluate) {
      onUnsolve();
    }
  }
  Serial.println ("Next round");
}


// Here are the custom functions:


void maxMinVu(int flag) {
  if (flag == 0) {
    setLed (LOW, LOW, LOW);
    analogWrite (left, 0);
    analogWrite (center, 0);
    analogWrite (right, 0);
  } else if (flag == 1) {
    analogWrite (left, 255);
    analogWrite (center, 255);
    analogWrite (right, 255);
  }
}


void normal (int sense, int vumeter) {
  // Pot and VU at same direction
  int potentiometro = analogRead(sense);
  int saida = map (potentiometro, 1023, 0 , 0, 255);
  analogWrite (vumeter, saida);
}


void reverso (int sense, int vumeter) {
  // Pot and VU are reversed
  int potentiometro = analogRead(sense);
  int saida = map (potentiometro, 0, 1023 , 0, 255);
  analogWrite (vumeter, saida);
}


void setLed (int stateBlue, int stateYellow, int stateRed) {
  // Led is on if Pot and VU matches
  digitalWrite (blue, stateBlue);
  digitalWrite (yellow, stateYellow);
  digitalWrite (red, stateRed);
}


int readPWM(int digitalPin) {
  // Detect PWM
  int var = pulseIn (digitalPin, HIGH, 4200);
  if (var == 0 && digitalRead (digitalPin) == 1) {
    var = 2100;
  }
  var = map (var, 0 , 2100, 0, 1023);
  return var;
}


bool evaluate (int num0, int num1, int num2) {
  // Evaluate Results to detect Winner:
#ifdef DEBUG
  Serial.print (num0);
  Serial.print (" ");
  Serial.print (num1);
  Serial.print (" ");
  Serial.println (num2);
  Serial.println ("-----");
#endif


   if (num0 == winner[0] && num1 == winner[1] && num2 == winner[2]) {
    return true;
  } else if (num0 != winner[0] || num1 != winner[1] || num2 != winner[2]) {
    return false;
  }
}




void onSolve() {
  // Aciona o relê se o quebra-cabeça foi resolvido
  digitalWrite (relay, HIGH);
#ifdef DEBUG
  Serial.println(F("Quebra Cabeca Resolvido!"));
#endif
  // E toca cinco bipes!
  for (int i = 0; i < 5; i++) {
    tone (buzzer, 2500, 1000);
    setLed (HIGH, HIGH, HIGH);
    delay(200);
    noTone(buzzer);
    setLed (LOW, LOW, LOW);
    delay(200);
  }
  puzzleState = Solved;
}


void onUnsolve() {
#ifdef DEBUG
  //Serial.println(F("Quebra Cabeca Desmanchado!"));
#endif
  puzzleState = Running;
}


void sorteio (int choice) {
  // Aqui são 48 possibilidades!!!
  switch (choice) {
    case 1:
      normal (bpot, left);
      normal (ypot, center);
      normal (rpot, right);
      setLed (HIGH, HIGH, HIGH);
      break;
    case 2:
      normal (bpot, left);
      normal (ypot, right);
      normal (rpot, center);
      setLed (HIGH, LOW, LOW);
      break;
    case 3:
      normal (bpot, right);
      normal (ypot, center);
      normal (rpot, left);
      setLed (LOW, HIGH, LOW);
      break;
    case 4:
      normal (bpot, right);
      normal (ypot, left);
      normal (rpot, center);
      setLed (LOW, LOW, LOW);
      break;
    case 5:
      normal (bpot, center);
      normal (ypot, left);
      normal (rpot, right);
      setLed (LOW, LOW, HIGH);
      break;
    case 6:
      normal (bpot, center);
      normal (ypot, right);
      normal (rpot, left);
      setLed (LOW, LOW, LOW);
      break;


    case 7:
      reverso (bpot, left);
      normal (ypot, center);
      normal (rpot, right);
      setLed (HIGH, HIGH, HIGH);
      break;
    case 8:
      reverso (bpot, left);
      normal (ypot, right);
      normal (rpot, center);
      setLed (HIGH, LOW, LOW);
      break;
    case 9:
      reverso (bpot, right);
      normal (ypot, center);
      normal (rpot, left);
      setLed (LOW, HIGH, LOW);
      break;
    case 10:
      reverso (bpot, right);
      normal (ypot, left);
      normal (rpot, center);
      setLed (LOW, LOW, LOW);
      break;
    case 11:
      reverso (bpot, center);
      normal (ypot, left);
      normal (rpot, right);
      setLed (LOW, LOW, HIGH);
      break;
    case 12:
      reverso (bpot, center);
      normal (ypot, right);
      normal (rpot, left);
      setLed (LOW, LOW, LOW);
      break;


    case 13:
      normal (bpot, left);
      reverso (ypot, center);
      normal (rpot, right);
      setLed (HIGH, HIGH, HIGH);
      break;
    case 14:
      normal (bpot, left);
      reverso (ypot, right);
      normal (rpot, center);
      setLed (HIGH, LOW, LOW);
      break;
    case 15:
      normal (bpot, right);
      reverso (ypot, center);
      normal (rpot, left);
      setLed (LOW, HIGH, LOW);
      break;
    case 16:
      normal (bpot, right);
      reverso (ypot, left);
      normal (rpot, center);
      setLed (LOW, LOW, LOW);
      break;
    case 17:
      normal (bpot, center);
      reverso (ypot, left);
      normal (rpot, right);
      setLed (LOW, LOW, HIGH);
      break;
    case 18:
      normal (bpot, center);
      reverso (ypot, right);
      normal (rpot, left);
      setLed (LOW, LOW, LOW);
      break;


    case 19:
      reverso (bpot, left);
      reverso (ypot, center);
      normal (rpot, right);
      setLed (HIGH, HIGH, HIGH);
      break;
    case 20:
      reverso (bpot, left);
      reverso (ypot, right);
      normal (rpot, center);
      setLed (HIGH, LOW, LOW);
      break;
    case 21:
      reverso (bpot, right);
      reverso (ypot, center);
      normal (rpot, left);
      setLed (LOW, HIGH, LOW);
      break;
    case 22:
      reverso (bpot, right);
      reverso (ypot, left);
      normal (rpot, center);
      setLed (LOW, LOW, LOW);
      break;
    case 23:
      reverso (bpot, center);
      reverso (ypot, left);
      normal (rpot, right);
      setLed (LOW, LOW, HIGH);
      break;
    case 24:
      reverso (bpot, center);
      reverso (ypot, right);
      normal (rpot, left);
      setLed (LOW, LOW, LOW);
      break;


    case 25:
      normal (bpot, left);
      normal (ypot, center);
      reverso (rpot, right);
      setLed (HIGH, HIGH, HIGH);
      break;
    case 26:
      normal (bpot, left);
      normal (ypot, right);
      reverso (rpot, center);
      setLed (HIGH, LOW, LOW);
      break;
    case 27:
      normal (bpot, right);
      normal (ypot, center);
      reverso (rpot, left);
      setLed (LOW, HIGH, LOW);
      break;
    case 28:
      normal (bpot, right);
      normal (ypot, left);
      reverso (rpot, center);
      setLed (LOW, LOW, LOW);
      break;
    case 29:
      normal (bpot, center);
      normal (ypot, left);
      reverso (rpot, right);
      setLed (LOW, LOW, HIGH);
      break;
    case 30:
      normal (bpot, center);
      normal (ypot, right);
      reverso (rpot, left);
      setLed (LOW, LOW, LOW);
      break;


    case 31:
      reverso (bpot, left);
      normal (ypot, center);
      reverso (rpot, right);
      setLed (HIGH, HIGH, HIGH);
      break;
    case 32:
      reverso (bpot, left);
      normal (ypot, right);
      reverso (rpot, center);
      setLed (HIGH, LOW, LOW);
      break;
    case 33:
      reverso (bpot, right);
      normal (ypot, center);
      reverso (rpot, left);
      setLed (LOW, HIGH, LOW);
      break;
    case 34:
      reverso (bpot, right);
      normal (ypot, left);
      reverso (rpot, center);
      setLed (LOW, LOW, LOW);
      break;
    case 35:
      reverso (bpot, center);
      normal (ypot, left);
      reverso (rpot, right);
      setLed (LOW, LOW, HIGH);
      break;
    case 36:
      reverso (bpot, center);
      normal (ypot, right);
      reverso (rpot, left);
      setLed (LOW, LOW, LOW);
      break;


    case 37:
      normal (bpot, left);
      reverso (ypot, center);
      reverso (rpot, right);
      setLed (HIGH, HIGH, HIGH);
      break;
    case 38:
      normal (bpot, left);
      reverso (ypot, right);
      reverso (rpot, center);
      setLed (HIGH, LOW, LOW);
      break;
    case 39:
      normal (bpot, right);
      reverso (ypot, center);
      reverso (rpot, left);
      setLed (LOW, HIGH, LOW);
      break;
    case 40:
      normal (bpot, right);
      reverso (ypot, left);
      reverso (rpot, center);
      setLed (LOW, LOW, LOW);
      break;
    case 41:
      normal (bpot, center);
      reverso (ypot, left);
      reverso (rpot, right);
      setLed (LOW, LOW, HIGH);
      break;
    case 42:
      normal (bpot, center);
      reverso (ypot, right);
      reverso (rpot, left);
      setLed (LOW, LOW, LOW);
      break;


    case 43:
      reverso (bpot, left);
      reverso (ypot, center);
      reverso (rpot, right);
      setLed (HIGH, HIGH, HIGH);
      break;
    case 44:
      reverso (bpot, left);
      reverso (ypot, right);
      reverso (rpot, center);
      setLed (HIGH, LOW, LOW);
      break;
    case 45:
      reverso (bpot, right);
      reverso (ypot, center);
      reverso (rpot, left);
      setLed (LOW, HIGH, LOW);
      break;
    case 46:
      reverso (bpot, right);
      reverso (ypot, left);
      reverso (rpot, center);
      setLed (LOW, LOW, LOW);
      break;
    case 47:
      reverso (bpot, center);
      reverso (ypot, left);
      reverso (rpot, right);
      setLed (LOW, LOW, HIGH);
      break;
    case 48:
      reverso (bpot, center);
      reverso (ypot, right);
      reverso (rpot, left);
      setLed (LOW, LOW, LOW);
      break;
  }
}



Step 3: Coisas Para Melhorar E Aperfeiçoar - Things to Improve and Perfect

  1. A função evaluate() pode ser ajustada para qualquer critério. Eu fiz uma versão que identificava se os três números eram ímpares e diferentes entre si.
  2. Também estou trabalhando numa versão com os ponteiros oscilando entre dois pontos extremos e que vai diminuindo a oscilação à medida que você vai girando o potenciômetro adequado.
  3. Música, usando a função Tone.
  4. Enxugar o código. Nunca é demais...
  5. Diminuir o tempo da rodada a cada etapa, ou ainda, fazer com que o tempo da rodada seja aleatório, dentro de uma faixa determinada.
  6. Adicionar mais potenciômetros (dois para cada VU) e atribuir funções a eles que compliquem o jogo (diminui o tempo da rodada, aumentar o volume do buzzer, etc...)

Você pode acompanhar esses e outros projetos na minha página: http://www.nicolaudosbrinquedos.com.br, ou até no Facebook: http://facebook.com/nicolaudosbrinquedos

===

  1. The evaluate () function can be adjusted for any criterion. I made a version that identified if the three numbers were odd and different from each other.
  2. I am also working on a version with the pointers oscillating between two extreme points and that will decrease the oscillation as you turn the proper potentiometer.
  3. Music, using the Tone function.
  4. Clean up the code. Never too much ...
  5. Decrease the time of the round with each step, or even, make the time of the round be random, within a certain range.
  6. Add more potentiometers (two for each VU) and assign functions to them that complicate the game (decreases the time of the round, increase the volume of the buzzer, etc ...)