Project showcase

Valentine Blink: Voice Controlled LED Heart © GPL3+

Valentine week is almost here; it's a perfect time to build something for your special one and what else could be better than blinking LEDs?

  • 7,842 views
  • 0 comments
  • 21 respects

Components and supplies

Apps and online services

About this project

This write-up is a walk-through in which I'll explain how each component is designed and connected to each other.

This write-up is divided into 4 parts:

  • Electronics
  • Assembly
  • Code
  • Schematics

Let's get started!

Electronics

This section shows how everything is connected to each other. There are 3 major components: the speech module, Arduino Nano and TLC5947 LED board.

Speech recognition module:

The VR module I used is a SimpleVR module. It supports Speaker Independent(SI) recognition; that means it does not require any speech training and can recognize anyone's voice. The module has a USB port to flash commands using a PC software. The commands are stored in a text file and can be edited with any text editor.

A "Group number" is given to each text file. As you can see below, file "asrgrp1.txt" corresponds to Group number 1. The group number is what we will import in our code.

After "Downloading" commands on the module you can test it by connecting to Arduino via serial port. SimpleVR's library internally uses softwareserial for communication with Arduino, so any digital pin can be utilized as RX-TX pin.

Once powered, the module waits for voice activity above a certain threshold and returns the index of the recognized command. In reasonably quiet environments, accuracy is ~ 95%. Though it's not perfect, if you say any command/phrase that's not in the group list, it returns the index of the closet command that sounds similar.

Alternatives:

If you have VR module 2 or VR module 3.1, you can use them. The only drawback is that they need to be trained by speaking each command multiple times, that means they're Speaker Dependent. So, if you train the module and another person tries to speak the commands, it may not be able to recognize it and give you the wrong index/answer.

The LED Heart:

There are many options here; it really depends on what you want. For the LED chaser effect you can use shift registers, I/O expanders (MCP23017 chip). But if you want more control, then LED driver chips like TLC59x series or PCA9685 would be a good choice.

I used TLC5947 LED driver chip. It has 24 channels and 12-bit PWM resolution, so we get the range of 4095 steps. The chip is capable of sinking 30mA per channel which is more than enough for LEDs.

The chip comes in a Surface Mount (SMT) package, so you would either need a PCB or an SMT-to-DIP adapter board. I designed a custom PCB for my project. You can download the eagle schematic from my GitHub repo.

Here's the pinout for the LED board:

The circuit board is simple. The LEDs used are of SMD 1206 size. One resistor connected to pin IREF decides how much current each pin would sink. In this case, I used a 2.4k resistor so each pin sinks 20mA current. There are some standard resistor vs current values given in the datasheet.

The chip uses SPI protocol to communicate with Arduino. Although, it doesn't need to be hardware SPI, just clocked serial data (you would need hardware SPI if you're chaining many TLCs, but that's not the case here). (more info)

Alternatives:

TLC5940 chip comes in Through hole (DIP) package but only has 16 channels. Adafruit sells breakout bords for these chips. icstation.com even has a ready-made LED heart.

Power supply:

The Arduino Nano and VR module require 5v; the LED heart board requires two separate voltages for powering the LEDs and chip itself (V+ and Vcc). A 1200mAh Lipo battery is connected to a USB boost converter which provides a 5v supply to the Nano and the VR module. Supply for TLC5947 (Vcc pin) is taken from the Nano's 3.3.v out.

To power 24 LEDs, we need an external 5-30v supply connected to 'V+' pin. I used a 9v battery because I wanted to make it portable. Remember that 9v battery won't last long. If you don't want to make it portable you should use 12v external supply.

Assembly

Now that we are done with electronics, it is time to put everything into a case. I used a Ferrero Rocher chocolate box.It has a transparent lid, so you can color coat it with red spray paint or with glass color.

I glued the LED board to a binding post to give it some elevation. This is required to scatter LED lights equally through the lid.

And it's done!

Code

Voice controlled LED heart codeC/C++
/*
* Project:	Voice controlled LED heart
* Author:	  Aditya K.
* Date:		  1/10/2017
* License:	MIT
*
*/


#include <SoftwareSerial.h>
#include "SimpleVR.h"

#define MAX_PWM 4095
#define MIN_PWM 0

#define DATA  PD5 // 5 <-- IDE pins
#define CLOCK PD6 // 6
#define LATCH PD7 // 7

#define BLNK  PB0 // 8


//Define MACROS to toggle pins. 
//I am writing values direclty to the ports because DigitalWrite() is slow to //show LED chaser effect. This is the only difference between these TLC //functions and Adafruit's TLC5947 library.

// Toggle pin HIGH to turn off TLC
#define TLC_DISABLE() (PORTB |= bit(BLNK))

// Toggle pin LOW to turn on TLC
#define TLC_ENABLE()  (PORTB &= ~bit(BLNK))


#define DATA_HIGH()   (PORTD |= bit(DATA))
#define DATA_LOW()    (PORTD &= ~bit(DATA))

#define CLOCK_HIGH()  ((PORTD |= bit(CLOCK)))
#define CLOCK_LOW()   ((PORTD &= ~bit(CLOCK)))


#define LATCH_ENABLE()  ((PORTD |= bit(LATCH)))
#define LATCH_DISABLE() ((PORTD &= ~bit(LATCH)))

// Speech commands 

#define ILU     (0x1)    // I LOVE YOU
#define ILUT    (0x2)    // I LOVE YOU TOO
#define ME_TOO  (0x3)    // ME TOO
#define YES     (0x4)    // YES

#define ILUBAF  (0x6)    // I LOVE YOU BUT AS A FRIEND
#define SORRY   (0x7)    // I AM SORRY
#define INST    (0x9)    // I NEED SOME TIME

uint16_t pwm_buffer[24];
uint8_t receive[10];

static bool reply = false;
unsigned long start;
const uint16_t wait  = 8000;


VR Heart(2, 3); // 2:TX, 3:RX

//TLC5947 related functions
void init_tlc() {
  memset(pwm_buffer, 0, 24);
  pinMode(DATA, OUTPUT);
  pinMode(CLOCK, OUTPUT);
  pinMode(LATCH, OUTPUT);
  pinMode(OE, OUTPUT);
  LATCH_DISABLE();
  TLC_DISABLE();
}

inline void tlc_set_pwm(uint16_t chan, uint16_t pwm) {
  pwm_buffer[chan] = pwm;
}

inline void tlc_clear_buff(void) {
  for (uint8_t i = 0; i < 24; i++)
    pwm_buffer[i] = 0;
}


void tlc_write(void) {
  LATCH_DISABLE();

  for (int t = 23; t >= 0; t--) {
    for (int b = 11; b >= 0; b--) {
      CLOCK_LOW();
      if (pwm_buffer[t] & (1 << b)) {
        DATA_HIGH();
      } else {
        DATA_LOW();
      }
      CLOCK_HIGH();
    }
  }
  CLOCK_LOW();
  LATCH_ENABLE();
  LATCH_DISABLE();
}

// code reference: https://docs.micropython.org/en/latest/pyboard/pyboard/tutorial/fading_led.html
void heartbeat_effect() {

  uint16_t curr_steps = 0;
  uint16_t step_incr = 117; // total of 35 steps: 117*35  = 4095

  while (1) {
    for (uint8_t i = 0; i < 24; i++) {
      tlc_set_pwm(i, curr_steps);
    }
    tlc_write();
    delay(45);
    curr_steps += step_incr;

    if (curr_steps > MAX_PWM) {
      curr_steps = MAX_PWM;
      step_incr *= -1;
    }
    else if (curr_steps < MIN_PWM) {
      curr_steps = MIN_PWM;
      step_incr *= -1;
    }
  }
}


void heart_effect() {
  uint8_t left_led;
  uint8_t right_led;
  for (left_led = 0, right_led = 23; left_led <= 12 && right_led >= 12; left_led++, right_led--) {
    tlc_set_pwm(left_led, MAX_PWM);
    tlc_set_pwm(right_led, MAX_PWM);
    tlc_write();
    delay(45);
  }
}

void recognizer() {
  int ret;
  uint16_t voice = 0;
  ret = Heart.recognize(receive, 45);
  if (ret > 0) {
    voice += receive[0];
    voice <<= 8;
    voice += receive[1];
  }

  switch (voice) {
    case ILU:
      if (!reply) {
        // We're here for the first time.
        reply = true;
        start = millis();
        break;
      }
      else {
        // We've been here before, this means recognizer misinterpreted "I love you too" as "I love you"
        // so run LED effects
        heart_effect();
        delay(1000);
        heartbeat_effect();
        break;
      }

    case ILUT:
      if (!reply) {
        // We're here for the first time.
        // this time recognizer misinterpreted "I love you" as "I love you too"
        reply = true;
        start = millis();
        break;
      }
    case YES:
    case ME_TOO:
      if (reply) {
        heart_effect();
        delay(1000);
        heartbeat_effect();
      }
      break;

    case SORRY:
      if (reply) {
        // :( better luck next time.
      }
      break;
    case ILUBAF:
      if (reply) {
        // you just got friendzoned. :(
      }
      break;
    case INST:
      if (reply) {
        // we have some hopes
        tlc_clear_buff();
        tlc_write();
        heart_effect();
      }
  }
  if (reply) {
    if (millis() - start > wait) { // wait for 8 seconds
      reply = 0;
      // Timeout
      // TODO: What to do?
    }
  }
}

void setup() {
  Heart.begin(9600);
  Heart.setGroup(1);
  Heart.setEnable(true);

  init_tlc();
  tlc_clear_buff();
  tlc_write();
  TLC_ENABLE();
}

void loop() {
  recognizer();
}

Schematics

Schematic
Schematic ulgvhylwjb
Eagle schematic files for LED heart board

Comments

Similar projects you might like

2WD Voice Controlled Robot with Arduino and BitVoicer Server

Project tutorial by Marcio Tamagushi

  • 10,213 views
  • 11 comments
  • 32 respects

Valentine Blink: Wireless LED Hearts

Project showcase by AdiK

  • 4,658 views
  • 15 comments
  • 29 respects

Arduino Controlled Car with HC-SR04

Project showcase by VASILEIOS MOUGIOS

  • 7,746 views
  • 0 comments
  • 11 respects

Voice Controlled Car

Project tutorial by Yug_Ajmera

  • 5,096 views
  • 0 comments
  • 9 respects

Very First Hands On Arduino - Voice Activated LED

Project tutorial by Liren Yeo

  • 3,732 views
  • 2 comments
  • 18 respects

Rf controlled buggy

Project showcase by brzi

  • 3,002 views
  • 1 comment
  • 13 respects
Add projectSign up / Login