Home

Awesome

micropython-SYN6988

MicroPython library for the YuTone VoiceTX SYN6988 text to speech module.

Demo

https://github.com/scruss/micropython-SYN6988/assets/425706/bf107dc3-3db7-4eb7-90a4-6cfe5986529f

or demo audio download: <a href="images/syn6988-micropython-demo.mp3">syn6988-micropython-demo.mp3</a>

which "reads" the following text:

[g2]Hello! [g1]你好![g2]
I can speak in English, and also in Chinese:
[g1]千里之行,始于足下。[g2]
which means: a journey of five hundred kilometres starts with the first step
[s1]I can speak slowly, [s9] and I can speak very fast[s5]
[v5]I can be [v10]loud or [v1]very quiet. [v5]
I can use [t1]low tones [t5]or [t8]high tones[t5]
[d][g0]my work here is done [x1]soundy[d]

Introduction

<img src="images/syn6988-front.webp" width="628" height="600" alt="blue circuit board with central processor chip and audio outputs" />

The SYN6988 is one of several speech synthesizer / text-to-speech (TTS) modules available inexpensively on AliExpress and other vendors. It's impressive because:

Of course, there are downsides:

Where to buy

It's hard to recommend a vendor, as I can't guarantee they are selling a board with a SYN6988 on it. Check that the vendor description says SYN6988 (there are similar chips SYN6288 and SYN6658 with different capabilities) and the board has a chip with a clear SYN6988 silkscreen. I've seen a few boards for sale that say SYN6658 on the PCB silkscreen, but have a SYN6988 in the image and description.

Interfacing

The SYN6988 is a 3.3 V device for both logic and power. It requires a two-wire UART connection plus an additional digital input pin to monitor the busy status of the TTS.

    SYN6988        MicroPython Board     Raspberry Pi Pico
   =========      ===================   ===================
   
        RDY            Digital Input         GPIO 2
	RXD            UART TXD              GPIO 0 (UART 0 TX)
	TXD            UART RXD              GPIO 1 (UART 0 RX)
	GND            Ground                Any GND pin
	3V3            3V3 supply            3V3(OUT)
	

The SYN6988 uses a fixed serial port rate defined by the arrangement of resistors in the serial speed selection block. Mine is hard-wired for 9600 baud.

For a Raspberry Pi Pico, these connections might be supported in code with:

ser = machine.UART(0, baudrate=9600, bits=8, parity=None, stop=1)
busyPin = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)

Audio output is either through the headphone / line out jack or via the speaker pins. This output is unamplified. I can drive a very small oval speaker at a comfortable volume from the speaker pins, but large heaphones can be very quiet.

The board I have is not remotely breadboard-friendly. I solved that by taking two 6-pin Arduino stacking headers, bending the pins out and back in at right angles, then gluing the two headers back to back. This gives a header block that bridges the central trough in a breadboard, allowing the SYN6988 board to sit centrally.

<img src="images/syn6988_pico.jpg" width="1045" height="1045" alt="SYNC6988 with Raspberry Pi Pico and small speaker" />

Operation

If the board is connected correctly, the red Ready LED will be lit when the TTS is not speaking. This LED will go out when the TTS is speaking, and the RDY pin will go low shortly (about 0.1 to 0.7 s) after the speech starts, and go high when speech is finished.

If the initialization code above is used, the following MicroPython will speak a rather quiet "Hello" from the board:

import syn6988

s = syn6988.SYN6988(ser, busyPin)
s.speak("[v1]hello")

There are very few methods and properties to this module:

Embedded text commands

The SYN6988 is controlled by commands surrounded by []. There are many of these, and I don't understand them all. I've put a few of them in test-syn6988.py with I hope clear meanings of what they do. In brief:

Internals

The SYN6988 accepts a wide range of input encodings, none of which are supported by MicroPython. It does, however, support UTF16-BE (two bytes per char, no BOM, high byte first; eg: "hello" => b'\x00h\x00e\x00l\x00l\x00o') which can be fairly easily fudged to work. If our UTF-16BE encoded data is in data_bytes and we define

tx_len = len(data_bytes) + 2

the SYN6988 will accept the following byte stream over the serial port and attempt to speak it:

0xFD, tx_len // 256, tx_len % 256, 0x01, 0x04, data_bytes

The data string shouldn't be too long: something under 4096 characters, perhaps. The board can take up to 700 ms to process text, and hence we pause for that long to make sure text is all spoken.

Author

Stewart Russell - scruss.com - aka @scruss@xoxo.zone

Licence

MIT. If you improve on this, though, please let me know so I can make this better.

To do

References