Tal O
Published © MIT

My twist on the Twister game

uno, mpr121, addressable led and Serial mp3 player and some aluminum foil

BeginnerFull instructions provided1,554
My twist on the Twister game

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Capacitive Touch Sensor Breakout - MPR121
Adafruit Capacitive Touch Sensor Breakout - MPR121
×1
mp3 serial player
×1
addressable led
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

Fritzign file

Code

BIG_simon.ino

Arduino
This is the main INO, you will need the seria_mp3.h as well.
/*
 *  Code by Tal Ofer  - talofer99@hotmail.com
 *  
 *  
 */
#include <FastLED.h>
#include <MPR121.h>
#include <Wire.h>
#include "serial_mp3.h"

#define NUM_LEDS 4
#define DATA_PIN 3
#define NUM_BUTTONS 12

// Define the array of leds
CRGB leds[NUM_LEDS];

// Define the array of leds
#define COLOR_BLUE 0
#define COLOR_GREEN 1
#define COLOR_YELLOW 2
#define COLOR_RED 3

// Define system state
#define SYS_STATE_START 0
#define SYS_STATE_WIN 1
#define SYS_STATE_FAIL 2



CRGB colour[] = {CRGB::Blue, CRGB::Green,  CRGB::Yellow, CRGB::Red};
byte buttonColor[NUM_BUTTONS] = {COLOR_BLUE, COLOR_BLUE, COLOR_BLUE, COLOR_GREEN, COLOR_GREEN, COLOR_GREEN, COLOR_YELLOW, COLOR_YELLOW, COLOR_YELLOW, COLOR_RED, COLOR_RED, COLOR_RED};

byte currentColor[NUM_LEDS];
byte currentColorIndex = 0;
byte systemState;

void setup()
{
  Serial.begin(115200);
  Serial.println("System started");
  randomSeed(analogRead(A0) + analogRead(A1) + analogRead(A2) + analogRead(A3));
  Wire.begin();

  // 0x5C is the MPR121 I2C address on the Bare Touch Board
  if (!MPR121.begin(0x5A)) {
    Serial.println("error setting up MPR121");
    switch (MPR121.getError()) {
      case NO_ERROR:
        Serial.println("no error");
        break;
      case ADDRESS_UNKNOWN:
        Serial.println("incorrect address");
        break;
      case READBACK_FAIL:
        Serial.println("readback failure");
        break;
      case OVERCURRENT_FLAG:
        Serial.println("overcurrent on REXT pin");
        break;
      case OUT_OF_RANGE:
        Serial.println("electrode out of range");
        break;
      case NOT_INITED:
        Serial.println("not initialised");
        break;
      default:
        Serial.println("unknown error");
        break;
    }
    while (1);
  }

  // pin 4 is the MPR121 interrupt on the Bare Touch Board
  MPR121.setInterruptPin(2);

  // this is the touch threshold - setting it low makes it more like a proximity trigger
  // default value is 40 for touch
  MPR121.setTouchThreshold(40);

  // this is the release threshold - must ALWAYS be smaller than the touch threshold
  // default value is 20 for touch
  MPR121.setReleaseThreshold(20);

  // initial data update
  MPR121.updateTouchData();

  // start fast led
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

  serialmp3_init();
  delay(200);
  serialmp3_set_vol(15);
  delay(200);


  setSystemState(SYS_STATE_START);
}

void loop()
{
  mp3_SerialProcess();


  if (MPR121.touchStatusChanged() && systemState == 0) {
    MPR121.updateTouchData();
    for (int i = 0; i < NUM_BUTTONS; i++) {
      if (MPR121.isNewTouch(i)) {
        
        if (buttonColor[i] == currentColor[currentColorIndex]) {
          addColor();
          break;
        }
        else
        {
          setSystemState(SYS_STATE_FAIL);
          break;
        } //end if

      } else if (MPR121.isNewRelease(i)) {
        
        for (byte z = 0; z < currentColorIndex; z++) {
          if (currentColor[z] == buttonColor[i]) {
            setSystemState(SYS_STATE_FAIL);
            break;
          } //end if
        } //end for
        
      } //end if
    } //end for
  } //end if
}

void addColor() {
  currentColorIndex++;
  if (currentColorIndex < NUM_LEDS)
  {
    currentColor[currentColorIndex] = getRandomColor(currentColor[currentColorIndex - 1]);
    Serial.println(currentColor[currentColorIndex]);
    leds[currentColorIndex] = colour[currentColor[currentColorIndex]];
    FastLED.show();
  }
  else
  {
    setSystemState(SYS_STATE_WIN);
  }

}


void setSystemState(byte newState) {
  //set newState
  systemState = newState;
  switch (newState) {
    case SYS_STATE_START:
      currentColorIndex = 0;
      currentColor[currentColorIndex] = getRandomColor(99);
      Serial.println(currentColor[currentColorIndex]);
      leds[currentColorIndex] = colour[currentColor[currentColorIndex]];
      for (byte i = 1; i < NUM_LEDS; i++)
        leds[i] = CRGB::Black;
      FastLED.show();
      break;
    case SYS_STATE_WIN:
      serialmp3_play(5);
      blinkSuccess();
      setSystemState(0);
      Serial.println("system state  - success");
      break;
    case SYS_STATE_FAIL:
      serialmp3_play(6);
      blinkFail();
      setSystemState(0);
      Serial.println("system state  - fail");
      break;

  } //end switch
}

byte getRandomColor(byte avoidColor) {
  byte newColor;
  do {
    newColor = random(0, 4);
  } while (avoidColor == newColor);
  serialmp3_play(newColor + 1); // play color name
  return newColor;
}



void blinkSuccess() {
  for (byte z = 0; z < 3; z++) {
    for (byte i = 0; i < NUM_LEDS; i++)
      leds[i] = CRGB::Green;
    FastLED.show();
    delay(500);
    for (byte i = 0; i < NUM_LEDS; i++)
      leds[i] = CRGB::Black;
    FastLED.show();
    delay(500);
  }
}

void blinkFail() {
  for (byte z = 0; z < 3; z++) {
    for (byte i = 0; i < NUM_LEDS; i++)
      leds[i] = CRGB::Red;
    FastLED.show();
    delay(500);
    for (byte i = 0; i < NUM_LEDS; i++)
      leds[i] = CRGB::Black;
    FastLED.show();
    delay(500);
  }
}

serial_mp3.h

Arduino
#include <SoftwareSerial.h>
#include <Arduino.h>


//should connect to TX of the Serial MP3 Player module
#ifndef ARDUINO_RX
#define ARDUINO_RX   9
#endif
//connect to RX of the module
#ifndef ARDUINO_TX
#define ARDUINO_TX   8
#endif


#define CMD_SEL_DEV 0X09
#define DEV_TF 0X02

#define CMD_SET_DAC 0X1A
#define DAC_ON  0X00
#define DAC_OFF 0X01

#define CMD_VOLUME_UP 0X04
#define CMD_VOLUME_DOWN 0X05
#define CMD_SET_VOLUME 0X06

#define CMD_PLAY 0X0D
#define CMD_PLAY_W_INDEX 0X08
#define CMD_PLAY_W_VOL 0X22
#define CMD_PLAY_FOLDER_FILE 0X0F
#define CMD_STOP_PLAY 0X16
#define CMD_PAUSE 0X0E
#define CMD_SINGLE_CYCLE_PLAY 0X08
#define CMD_SINGLE_CYCLE 0X19
#define SINGLE_CYCLE_ON 0X00
#define SINGLE_CYCLE_OFF 0X01

#define CMD_NEXT_SONG 0X01
#define CMD_PREV_SONG 0X02

#define CMD_SLEEP_MODE 0X0A
#define CMD_WAKE_UP 0X0B
#define CMD_RESET 0X0C

#define CMD_FOLDER_CYCLE 0X17
#define CMD_SHUFFLE_PLAY 0X18

#define CMD_GROUP_DISPLAY 0X21

SoftwareSerial mp3_serial(ARDUINO_RX, ARDUINO_TX);


static int8_t Send_buf[8] = {
  0
}
;

byte serialmp3_incomingPointer = 0;
String serialmp3_answer = "";


void serialmp3_sendCommand(int8_t command, int16_t dat) {
  delay(20);
  Send_buf[0] = 0x7e; //starting byte
  Send_buf[1] = 0xff; //version
  Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
  Send_buf[3] = command; //
  Send_buf[4] = 0x01; //0x00 = no feedback, 0x01 = feedback
  Send_buf[5] = (int8_t)(dat >> 8);//datah
  Send_buf[6] = (int8_t)(dat); //datal
  Send_buf[7] = 0xef; //ending byte
  for (uint8_t i = 0; i < 8; i++) {
    mp3_serial.write(Send_buf[i]) ;
  }
}

void serialmp3_init() {
  mp3_serial.begin(9600);
  //Wait chip initialization is complete
  delay(500);
  //wait for 200ms
  serialmp3_sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card
  delay(200);

  serialmp3_answer.reserve(50);
}

void serialmp3_set_vol(byte vol) {
  serialmp3_sendCommand(CMD_SET_VOLUME, vol);
}

void serialmp3_play(byte folder, byte track) {
  //play the first song with volume 15 class: 0X0F01
  // serialmp3_sendCommand(CMD_PLAY_W_VOL, int(volume<< 8) | track);
  serialmp3_sendCommand(CMD_PLAY_FOLDER_FILE, folder << 8 | track); //>>>
}

void serialmp3_play(byte track) {
  serialmp3_play(1, track);
}

void serialmp3_stop() {
  serialmp3_sendCommand(CMD_STOP_PLAY, 0);
}

void serialmp3_pause() {
  serialmp3_sendCommand(CMD_PAUSE, 0);
}

void serialmp3_resume() {
  serialmp3_sendCommand(CMD_PLAY, 0);
}

void serialmp3_next() {
  serialmp3_sendCommand(CMD_NEXT_SONG, 0);
}

void serialmp3_prev() {
  serialmp3_sendCommand(CMD_PREV_SONG, 0);
}


// serial event - for incoming data


// answer buffer
static uint8_t serialmp3_ansbuf[10] = {0};
// send buffer
static int8_t serialmp3_Send_buf[8] = {0};
// flag for playing
boolean serialmp3_isPlaying = false;


String serialmp3_sbyte2hex(uint8_t b)
{
  String shex;
  shex = "0X";

  if (b < 16) shex += "0";
  shex += String(b, HEX);
  shex += " ";
  return shex;
}



void mp3_SerialProcess() {
  if (mp3_serial.available()) {
    uint8_t b = mp3_serial.read();
    if (b == 0x7E) {
      serialmp3_incomingPointer = 0;
      serialmp3_answer = "";
    }
    serialmp3_ansbuf[serialmp3_incomingPointer] = b;
    serialmp3_incomingPointer++;
    serialmp3_answer += serialmp3_sbyte2hex(b);
    if (b == 0xef) {
      switch (serialmp3_ansbuf[3]) {
        case 0x3A:
          serialmp3_answer += " -> Memory card inserted.";
          break;

        case 0x3D:
          serialmp3_isPlaying = false;
          serialmp3_answer += " -> Completed play num " + String(serialmp3_ansbuf[6], DEC);
          break;

        case 0x4C:
          serialmp3_answer += " -> Playing: " + String(serialmp3_ansbuf[6], DEC);
          break;

        case 0x41:
          serialmp3_answer += " -> Data recived correctly. ";
          break;
      } //end switch


      Serial.println(serialmp3_answer);
    } //end if
  } //enf if 
} //end void serialevent2

Credits

Tal O

Tal O

20 projects • 55 followers
Maker @ heart

Comments