Today’s project is an Arduino talking clock. Whenever one moves its hand in front of the proximity sensor, the clock will talk the current time. As for the hardware, I will use one Arduino Mega with a MikroElektronika Arduino Mega click shield, and three click boards: Proximity, RTC2, and Text-To-Speech click. All three click boards were configured for 5V operation by placing the PWR_SEL jumper in the 5V position.

I chose Arduino Mega for several reasons: first is that I needed three mikroBUS sockets for the click boards, and the MEGA Click shield was a perfect choice. Second, the S1V30120 IC onboard the Text-to_Speech click needs a large chunk of data to be uploaded in the initialization phase. The Mega has 256kb or FLASH memory, so plenty of space to store that data.

Another reason for choosing the Arduino Mega is that both RTC2 and Proximity click boards use I2C communication. The VCNL4010 onboard the Proximity click is not fussy regarding I2C communication. As the datasheet specifies, “The stop condition between these write and read sequences is not mandatory. It works also with a repeated start condition”. On the other hand, the DS1307 serial real-time clock (RTC) is more strict regarding I2C communication, and it requires repeated start conditions to be sent over the I2C bus as part of its communication protocol.

Unfortunately, the I2C libraries for Arduino Due (and its cousin Flip & Click) are still flawed, and a repeated start condition cannot be issued on the SAM3X8E. Ironically, this problem is at least three years old. In that time there were a few updates of the Arduino IDE, including the major jump to 1.8.0 version just after the two Arduino teams came back together as one. Still, no one cares about fixing the I2C communication on the SAM boards.

So, three click boards, three problems to solve: getting the distance, setting and keeping the current time, and doing all the talking. Luckily, all three problems were already solved. Code libraries for VCNL4010 and DS1307 are already written, and I’ve covered the basics of S1V30120 text-to-speech in another blog post. Parsing the time into words is also solved, I’ve done it before in my PIC18F45K22 “ word clock “ with GLCD display.

As usual with MikroElektronika click boards, building the hardware is just like playing with Lego bricks. The Text-to-Speech click board is placed in the first socket of the Mega Click Shield, the Proximity click stays in the second socket, and the RTC2 click occupies the third mikroBUS socket. As both Proximity click and RTC2 click boards use I2C communication, their position can be swapped and the project will still work.

Arduino Mega talking clock with S1V30120, VCNL4010, and DS1307

As for the software, I used the libraries provided by Adafuit, as over the course of time I found their libraries are second to none. The link for the VCNL4010 library is https://github.com/adafruit/Adafruit_VCNL4010. You can get the code for DS1307 from https://github.com/adafruit/RTClib.

The Text-to-Speech click board uses SPI communication, plus three dedicated control lines. So, leave it in the first socket (or you will have to change the pin definitions yourself). The code is largely based on my previous tutorial.

Arduino: Talking clock code

As a prerequisite, running the code examples from the libraries is a good idea, so you’ll know everything works fine. Also, running the code example for VCNL4010 helps to find the right threshold. Mine is 2400, for a detection distance of about 6–7cm. This is what you should get on the serial monitor for the VCNL4010 example:

VCNL4010 test

Found VCNL4010

Ambient: 516

Proximity: 2185

The DS1307 example produced the following output:

2003/2/10 (Monday) 17:37:34

since midnight 1/1/1970 = 1044898654s = 12093d

now + 7d + 30s: 2003/2/18 6:7:40

Setting the time can be done by uncommenting the line:

// This line sets the RTC with an explicit date & time, for example to set

// January 21, 2014 at 3am you would call:

rtc.adjust(DateTime(2017, 2, 9, 15, 28, 1));

Much to my dismay, nothing happened at first. I found that the battery was dead, although this is a brand new RTC2 click board. OK, a new CR3032 battery, and things were back to normal:

2017/2/9 (Thursday) 3:33:48

since midnight 1/1/1970 = 1486611228s = 17206d

now + 7d + 30s: 2017/2/16 16:3:54

Finally, the Text-To-Speech code example. Here I’ve changed some pin definitions to match the Arduino Mega pinout:

#define S1V30120_RST 49

#define S1V30120_RDY 10

#define S1V30120_CS 53

#define S1V30120_MUTE A0

I also moved the S1V30120 initialization data into FLASH memory, to work with the ATMEGA 2560. For this, in the file text_to_speech_img.h I have changed the variable definition

const char TTS_INIT_DATA[] =

to

const char TTS_INIT_DATA[] PROGMEM =

and also I’ve updated the following function to work with the data stored in FLASH:

bool S1V30120_load_chunk(unsigned short chunk_len)

{

// Load a chunk of data

char len_msb = ((chunk_len + 4) & 0xFF00) >> 8;

char len_lsb = (chunk_len + 4) & 0xFF;

digitalWrite(S1V30120_CS,LOW);

SPI.beginTransaction(SPISettings(750000, MSBFIRST, SPI_MODE3));

SPI.transfer(0xAA); // Start Message Command

SPI.transfer(len_lsb); // Message length is 2048 bytes = 0x0800

SPI.transfer(len_msb); // LSB first

SPI.transfer(0x00); // Send SC_BOOT_LOAD_REQ (0x1000)

SPI.transfer(0x10);

for (int chunk_idx = 0; chunk_idx < chunk_len; chunk_idx++)

{

//SPI.transfer(TTS_INIT_DATA[TTS_DATA_IDX]);

SPI.transfer(pgm_read_byte_near(TTS_INIT_DATA + TTS_DATA_IDX));

TTS_DATA_IDX++;

}

SPI.endTransaction();

digitalWrite(S1V30120_CS,HIGH);

return S1V30120_parse_response(ISC_BOOT_LOAD_RESP, 0x0001, 16);

}

Notice how I use the pgm_read_byte_near macro instead of just reading from the array.

With all those changes, the code example should run fine on the Mega, and you should hear some words from the text-to-speech click.

And now it’s time to put all together and write the final code: