News:

Let's find out together what makes a PIC Tick!

Main Menu

Thinking ahead - of robots

Started by charliecoutas, Aug 28, 2026, 08:24 AM

Previous topic - Next topic

charliecoutas

While we were in Austria last month, we visited a museum dedicated to technology. A robot wheeled up to me and it was obvious that I had to type something on its keyboard. But before I could it made a strange lurch, turned 180 degrees and stopped with a funny noise then powered down. "It's always doing that" said a lady employee of the museum.

This gave me an idea and I would appreciate any input from you lovely forum members:

Make a robot, not too big, that wanders around our museum muttering to itself and, most importantly, farts now and then. A few ideas floated into my mind:

It must speak. I asked ChatGPT and many of the other AI's if they could simulate the voice of Prof Stephen Hawking. They all said they were not allowed to do that and I understand why. So I tried the voice of HAL from the film. Same result. Has anybody used a text-to-voice board/chip? I have seen one but it only speaks Mandarin Chinese!

It "might" listen: I have a little board that responds to a small number of programmable words. "Shut-up" and "go away" would be useful but something more sophisticated would be good. A built-in interface to ChatGPT would be amazing.

It must move: We have just had a large area of the roof replaced at the museum. I thought it was metal corrugated stuff but GPS can still be received everywhere, so that shouldn't be too difficult.

ELf and Safety: It was suggested that a robot could be a trip-hazard but I pointed out that it will have four ultrasonic distance measuring sensors so it would back away if you walked too close. This was accepted.

I know I am in the middle of the Colossus tape reader monitor but just thinking ahead....

Charlie

RGV250

#1
Hi Charlie,
I have looked for a descent TTS chip for ages and there is nothing in the price range I was prepared to pay. WinBond did a good one years ago but seems to have disappeared. I did see something for Raspberry Pi but it used google (I think) and needed an internet connection so no use really.

I did find one that sort of worked but that could have been me. I could send you it if I can find it (and the info) if you want.
I think it was this type https://www.aliexpress.com/item/1005008200612159.html?isdl=y&aff_fsk=_ol8w4bv&src=SalesoarUKgeneral&aff_platform=aff_feeds&aff_short_key=_ol8w4bv&pdp_npi=4%40dis%21GBP%2113.85%215.92%21%21%21%21%21%40%2112000044216102004%21afff%21%21%21&dp=CjwKCAjw48TUBhBREiwAK0GnQZxJZybU478QBOEAcjzEy9nTC60QxcTg0gWuXtPcMOKqZ82fYLumFxoCpHYQAvD_BwE%7C0AAAAA_4-1LnHhP0X_wRotNglLkU4Agita%7CCj4KCAjwwL_UBhBhEi4AyXnDrMRIiI10Aa_RjZN8CHy9XxCMxSHRsJrJT7q4PWGim_sn4GwPWGtP1PWYGgLX1w%7Cv1&cn=gb_a&gad_source=1

Bob

Stephen Moss

Quote from: charliecoutas on Aug 28, 2026, 08:24 AMThis gave me an idea and I would appreciate any input from you lovely forum members:

Make a robot, not too big, that wanders around our museum muttering to itself and, most importantly, farts now and then. A few ideas floated into my mind:
Sounds like you want to create your own version of Marvin the Paranoid andriod. Perhaps as well as general muttering it could mutter something specific about a small selection of exhibits to draw attention to them as it passes, for example...
"X was very important in helping crack the Enigma code" (Positive)
"Y seems basic now but was revolutionary at the time (Neutral)
"Z thinks it is so clever, too big for it's boots if you ask me" (Negative, perhaps not good for an inhouse exhibit but very Marvin)

Quote from: charliecoutas on Aug 28, 2026, 08:24 AMIt must speak. I asked ChatGPT and many of the other AI's if they could simulate the voice of Prof Stephen Hawking. They all said they were not allowed to do that and I understand why. So I tried the voice of HAL from the film. Same result. Has anybody used a text-to-voice board/chip? I have seen one but it only speaks Mandarin Chinese!
Although I have not used Text-to-voice hardware I have used web based ones to create MP3 files error messages in PC software because I got board of using message boxes, maybe you could use one of those or some voice changer software to create MP3 files you can playback, which I belive is something you are already familiar with doing.
Using MP3 files may not be as convienent as Text-To-Speach hardware that you can send a serial text string to when it comes making changes/additions but if the relevant hardware is hard to find/use then MP3 files could be a viable alternative.

charliecoutas

Stephen, I hadn't thought of the robot muttering stuff about the exhibits it was near! Good idea.

Yes, using online voice generators to mp3 is a possibility. I have done short mp3 sound files a few times, played from a micro-SD card in a DF-Player board. But I would love to do the text-to-speech method if I can find the right board.

Charlie

top204

That is an excellent idea Charlie, and a robot roaming around mumbling of "duurin the wowa", and things, would be excellent.

I wrote some code 8 years ago for an EMIC-2 board (where has the time gone?), and the Text To Speech is excellent, and the voices are really good, even making them sing!

There are several videos of them online, but most are from egotists and rarely allow the voices to be heard, just them chuntering on about 'not a lot' :-) But you may find one that I have not, that actually gives a real demo of the voices.

The simple Positron8 library for the EMIC-2 is listed below. It had to use the bit-bashed serial because the device was using the UART for coms, but either way will work with some code simple changes.

$ifndef _Emic2_Inc_
$define _Emic2_Inc_
'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Library routines for the Emic-2 Text to Speech synthesiser
' Written By Les Johnson for the Positron8 BASIC Compiler.
'
' Version 1.0 (30-06-2018)
' This is the first verion and does the standard commands in the Epson mode
' Uses the compiler's Rsin and Rsout commands, so any pins can be used for TX and RX
'
' Version 2 (01-07-2018)
' Added a song singing routine
' Added a ChangeLanguage() routine
'
' Version 3 (2018)
' Added warnings if the RX and TX pins have not been implemented
' Changes the Emic2_hWaitReady routine to also receive "?"
'
' Setup Rsout and Rsin
'
$ifndef Emic2_TX_Pin                                ' Has the pin used for Tx to the Emic2 been given in the _Emic2_Main__ program?
    Declare RsOut_Pin = PORTC.6                     ' No. So default to this pin
    $SendMessage "Using a default pin for Rsout. Make sure it is the correct pin for the application"
$else                                               ' Otherwise...
    Declare RsOut_Pin = Emic2_TX_Pin                ' Use the pin issued in the main program
$endif
$ifndef Emic2_RX_Pin                                ' Has the pin used for Rx from the Emic2 been given in the _Emic2_Main__ program?
    Declare RsIn_Pin = PORTC.7                      ' No. So default to this pin
    $SendMessage "Using a default pin for Rsin. Make sure it is the correct pin for the application"
$else                                               ' Otherwise...
    Declare RsIn_Pin =  Emic2_RX_Pin                ' Use the pin issued in the main program
$endif

    Declare Serial_Baud = 9600                      ' Set the Baud rate for both Tx and Rx to 9600
    Declare RsIn_Timeout = 10000                    ' Set a timeout of 1000ms
    Declare RsOut_Mode = 0                          ' Set the mode for Tx
    Declare RsIn_Mode = 0                           ' Set the mode for Rx
    Declare RsOut_Pace = 0                          ' Set the delay between bytes sent from Rsout
'
' Create some variables
'
    Dim Global_Emic2_tTimeout As Bit                    ' Set true if the Emic2 serial interface times out
    Dim Global_Emic2_tPaused  As Bit                    ' 0 if not paused, 1 if paused
    Dim Global_Emic2_tParser  As Bit                    ' Holds the parser being used. 0 = DECtalk, 1 = Epson

    Dim Global_Emic2_wTimeout As Word                   ' Used as a timeout counter when receiving from the Emic2
    Dim Emic2_wByteCount      As Global_Emic2_wTimeout  ' Counts the bytes sent when singing (because the Emic-2 only has a 1023 byte serial buffer)
    Dim Global_Emic2_bVoice   As Byte = 0               ' Holds the Emic2 voice. (0 to 8)
    Dim Global_Emic2_bVolume  As SByte = 0              ' Holds the Emic2 audio volume (in dB). (-48 softest to 18 loudest)
    Dim Global_Emic2_wRate    As Word = 200             ' Holds the speaking rate (words per minute). (75 To 600)
    Dim Global_Emic2_bLanguage As Byte = 0              ' Holds the language being used. 0 = US English, 1 = Castilian Spanish, 2 = Latin Spanish
'
' Setup constants for the Emic2
'
' Voices
'
$define cVoice_Paul   0                             ' The voice is Perfect Paul
$define cVoice_Harry  1                             ' The voice is Huge Harry
$define cVoice_Betty  2                             ' The voice is Beautiful Betty
$define cVoice_Ursula 3                             ' The voice is Uppity Ursula
$define cVoice_Dennis 4                             ' The voice is Doctor Dennis
$define cVoice_Kid    5                             ' The voice is Kit the Kid
$define cVoice_Frank  6                             ' The voice is Frail Frank
$define cVoice_Rita   7                             ' The voice is Rough Rita
$define cVoice_Wendy  8                             ' The voice is Whispering Wendy
'
' Languages available
'
$define cUS_English 0                               ' The language is US English
$define cCastilian_Spanish 1                        ' The language is Castilian Spanish
$define cLatin_Spanish 2                            ' The language is Latin Spanish
'
' Parsers available
'
$define cParser_Epson 1                             ' The parser is the Epson type
$define cParser_DecTalk 0                           ' The parser is the DECTalk type
'
' Emic-2 Commands
'
$define cCmd_Speech "S"                             ' Convert text-to-speech (1023 characters maximum)
$define cCmd_Demo "D"                               ' Play demonstration message: 0 = Speaking, 1 = Singing, 2 = Spanish
$define cCmd_Stop "X"                               ' Stop playback (while message is playing)
$define cCmd_Pause "Z"                              ' Pause/un-pause playback (while message is playing)
$define cCmd_Voice "N"                              ' Select voice:  0 to 8
$define cCmd_Volume "V"                             ' Set audio volume (dB):  -48 to 18
$define cCmd_Rate "W"                               ' Set speaking rate(words/minute):  75 to 600
$define cCmd_Language "L"                           ' Select language:  0 = US English, 1 = Castilian Spanish, 2 = Latin Spanish
$define cCmd_Parser "P"                             ' Select parser:  0 = DECtalk, 1 = Epson
$define cCmd_Default "R"                            ' Revert to default text-to-speech settings
$define cCmd_Setting "C"                            ' Return current text-to-speech settings
$define cCmd_Version "I"                            ' Return version information
$define cCmd_Commands "H"                           ' Return a list of available commands

$ifndef True
    $define True 1
$endif
$ifndef False
    $define False 0
$endif

'------------------------------------------------------------------
' Value reading defines
'
$define Emic2_Read_Paused() Global_Emic2_tPaused            ' Reads the current pause. False if not paused, True if paused
$define Emic2_Read_Parser() Global_Emic2_tParser            ' Reads the parser being used. 0 = DECtalk, 1 = Epson
$define Emic2_Read_Voice() Global_Emic2_bVoice              ' Reads the Emic2 voice. (0 to 8)
$define Emic2_Read_Volume() Global_Emic2_bVolume            ' Reads the Emic2 audio volume (in dB). (-48 softest to 18 loudest)
$define Emic2_Read_Rate() Global_Emic2_wRate                ' Reads the speaking rate (words per minute). (75 To 600)
$define Emic2_Read_Language() Global_Emic2_bLanguage        ' Reads the language being used. 0 = US English, 1 = Castilian Spanish, 2 = Latin Spanish

'------------------------------------------------------------------
' Helper routine to wait for the Emic2 interface to be ready after a command is sent
' Input     : None
' Output    : Global_Emic2_tTimeout is true if the waiting period timed out
' Notes     : Waits for the character ":" to be received
'
Proc Emic2_hWaitAck()
    Dim bTemp As Byte
    Global_Emic2_wTimeout = 30000                           ' Set the timeout for approx 30 seconds
    Global_Emic2_tTimeout = False                           ' Default to no timeout
    Repeat                                                  ' Create a loop
TimeOut:
        bTemp = RsIn, {TimeOut}                             ' Wait for a byte received from the Emic2 board
        If bTemp = ":" Then ExitProc                        ' If the byte received was ":", then exit the procedure
        Dec Global_Emic2_wTimeout                           ' Decrement the timeout value
    Until Global_Emic2_wTimeout = 0                         ' Loop until the timeout value is reached
    Global_Emic2_tTimeout = True                            ' If it got here, there was a timeout
EndProc

'------------------------------------------------------------------
' Helper routine to force a response, and wait for the Emic2 interface to be ready
' Input     : None
' Output    : Global_Emic2_tTimeout is True if the waiting period timed out
' Notes     : Sends a CR, then waits for the character ":" to be received
'
Proc Emic2_hWaitReady()
    Dim bTemp As Byte = 0
    Do
TimeOut:
        RsOut 13                                            ' Trigger a response
        bTemp = RsIn, {TimeOut}
        '
        ' Wait for a response
        '
        If bTemp = "?" Then Break
        If bTemp = ":" Then Break
        If Global_Emic2_tTimeout = True Then Break
        DelayMS 100
    Loop
EndProc

'------------------------------------------------------------------
' Alter the parser used in the Emic2 board
' Input     : pParser holds the parser. 0 = DECtalk, 1 = Epson
' Output    : None
' Notes     : The Epson parser is the default setting upon Emic2 power-up.
'
Proc Emic2_ChangeParser(pParser As Global_Emic2_tParser)
    Emic2_hWaitReady()
    RsOutLn cCmd_Parser, Dec1 Global_Emic2_tParser
    Emic2_hWaitAck()
EndProc

'------------------------------------------------------------------
' Stop playback (While message is playing)
' Input     : None
' Output    : None
' Notes     : None
'
$define Emic2_Stop() RsOutLn, cCmd_Stop                     ' Send the Stop command

'------------------------------------------------------------------
' Pause/Unpause playback (While message is playing)
' Input     : None
' Output    : Global_Emic2_tPaused is True if paused, False if unpaused
' Notes     : None
'
$define Emic2_Pause()  '
    RsOutLn cCmd_Pause '
    Toggle Global_Emic2_tPaused

'------------------------------------------------------------------
' Alter the volume of the Emic2 board
' Input     : pVolume (Global_Emic2_bVolume) holds the volume in dB (-48 to 18)
' Output    : None
' Notes     : None
'
Proc Emic2_ChangeVolume(pVolume As Global_Emic2_bVolume)
    Emic2_hWaitReady()                                      ' Wait for the Emic2 to be ready
    RsOutLn cCmd_Volume, SDec pVolume                       ' Send the volume change command
EndProc

'------------------------------------------------------------------
' Increase the volume of the Emic2 board
' Input     : None
' Output    : None
' Notes     : None
'
Proc Emic2_VolUp()
    Inc Global_Emic2_bVolume                                ' Increment the volume value
    Emic2_hWaitReady()                                      ' Wait for the Emic2 to be ready
    Emic2_ChangeVolume(Global_Emic2_bVolume)                ' Send the volume change command
EndProc

'------------------------------------------------------------------
' Decrease the volume of the Emic2 board
' Input     : None
' Output    : None
' Notes     : None
'
Proc Emic2_VolDown()
    Dec Global_Emic2_bVolume                                ' Decrement the volume value
    Emic2_hWaitReady()                                      ' Wait for the Emic2 to be ready
    Emic2_ChangeVolume(Global_Emic2_bVolume)                ' Send the volume change command
EndProc

'------------------------------------------------------------------
' Alter the rate of speech from the Emic2 board
' Input     : pRate holds the speaking rate (words per minute) (75 To 600)
' Output    : None
' Notes     : None
'
Proc Emic2_ChangeRate(pRate As Global_Emic2_wRate)
    If pRate >= 75 Then                                     ' Is the rate above the miniumum allowed?
        If pRate <= 600 Then                                ' Yes. So is the rate less than the maximum allowed?
            Emic2_hWaitReady()                              ' Yes. So wait for the Emic2 to be ready
            RsOutLn cCmd_Rate, Dec pRate                    ' Send the rate change command
            Emic2_hWaitAck()
        EndIf
    EndIf
EndProc

'------------------------------------------------------------------
' Change the language of speech from the Emic2 board
' Input     : pLanguage holds the language value 0 = US English, 1 = Castilian Spanish, 2 = Latin Spanish
' Output    : None
' Notes     : None
'
Proc Emic2_ChangeLanguage(pLanguage As Global_Emic2_bLanguage)
    Select pLanguage
        Case 0 To 2                                             ' Is the rate above the miniumum allowed and below the maximum allowed?
            Emic2_hWaitReady()                                  ' Yes. So wait for the Emic2 to be ready
            RsOutLn cCmd_Language, Dec pLanguage                ' Send the language change command
            Emic2_hWaitAck()
    EndSelect
EndProc

'-----------------------------------------------------------------------------------------
' Sends a message to the Emic 2 module to speak
' Input     : pMessage holds the string to say
' Output    : None
' Notes     : n-the-fly, dynamic changes of emphasis, pitch, voice selection,
'             and speaking rate to take place within a text using embedded mark-up control symbols:
'               \/ Decrease pitch
'               /\ Increase pitch
'               >> Increase speaking rate
'               << Decrease speaking rate
'               __ Emphasise the next word
'               ## Whisper the next word
'               : -)x Select voice (x = 0-8)
'
$define Emic2_Speak(pMessage)     '
    RsOutLn cCmd_Speech, pMessage '
    Emic2_hWaitAck()

'-----------------------------------------------------------------------------------------
' Sends an integer number to the Emic 2 module to speak
' Input     : pNumber holds the number to say
' Output    : None
' Notes     : None
'
$define Emic2_SpeakNumber(pNumber)    '
    RsOutLn cCmd_Speech, SDec pNumber '
    Emic2_hWaitAck()

'-----------------------------------------------------------------------------------------
' Sends a floating point number to the Emic 2 module to speak
' Input     : pNumber holds the number to say
' Output    : None
' Notes     : None
'
$define Emic2_SpeakFloatNumber(pNumber) '
    RsOutLn cCmd_Speech, Dec1 pNumber   '
    Emic2_hWaitAck()

'-----------------------------------------------------------------------------------------
' Changes the voice that is speaking
' Input     : pVoice holds the voice
' Output    : None
' Notes     : None
'
Proc Emic2_ChangeVoice(pVoice As Global_Emic2_bVoice)
    Select pVoice
        Case 0 To 8
            Emic2_hWaitReady()                          ' Wait for the Emic2 to be ready
            RsOutLn cCmd_Voice, Dec pVoice              ' Send the voice command
            Emic2_hWaitAck()                            ' Wait for command to be finished
    EndSelect
EndProc

'------------------------------------------------------------------
' Sings a song from data in a flash memory table
' Input     : pSongTableAddr holds the address of the flash memory table that holds the song data
' Output    : None
' Notes     : Waits for a response from the Emic-2 board before returning
'           : Sets the parser back to Epson when finished
'
Proc Emic2_Sing(BycRef pSongTableAddr As Word)
    Dim bTemp As Byte

    Emic2_ChangeParser(cParser_DecTalk)                 ' Change the parser to DECtalk for phonemes
    RsOut "S"                                           ' Start speech
    Do                                                  ' Create a loop
        bTemp = cPtr8(pSongTableAddr++)                 ' Read from the flash data table into bTemp
        If bTemp = 0 Then                               ' Is the song data finished?
            RsOut 13                                    ' Yes. So tell the Emic-2 that it is complete
            Break                                       ' Exit the loop
        EndIf
        RsOut bTemp                                     ' Send the song data to the Emic-2
    Loop
    bTemp = RsIn                                        ' Wait for it to finish before continuing
    Emic2_ChangeParser(cParser_Epson)                   ' Change the Emic-2, back to Epson parser
EndProc

'------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Output    : None
' Notes     : None
'
Proc Emic2_Init()
    Global_Emic2_tPaused = False
    DelayMS 3000
    Emic2_hWaitReady()
    Emic2_ChangeParser(cParser_Epson)                   ' Set the parser to Epson
EndProc

'------------------------------------------------------------------
'
_Emic2_Main__:

$endif      ' _Emic2_Inc_

And one of the demos I created of it being used is listed below:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Play all languages from the Emic-2 Text to Speech synthesiser.
'
' Written for the Positron8 compiler by Les Johnson.
' https://sites.google.com/view/rosetta-tech/home
'
    Device = 18F25K22                                               ' Tell the compiler what device to compile for
    Declare Xtal = 64                                               ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Auto_Heap_Arrays = On                                   ' Make all arrays "Heap" types, so they always get placed after standard variables
    Declare Auto_Heap_Strings = On                                  ' Make all Strings "Heap" types, so they always get placed after standard variables
    Declare Auto_Variable_Bank_Cross = On                           ' Make sure all multi-byte variables remain within a single RAM bank
'
' Setup TX and TX pins (These must be defined before the "Emic2.Inc" file is included
' So that it can see them, otherwise... It will used default pins
'
$define Emic2_TX_Pin PORTB.3                                        ' Setup the pin used for TX to the Emic2 board
$define Emic2_RX_Pin PORTB.4                                        ' Setup the pin used for RX to the Emic2 board

    Include "Emic2.inc"                                             ' Load the Emic2 library into the program

'------------------------------------------------------------------------------------------------
' The main program starts here
'
Main:
    Setup()                                                         ' Setup the program and any peripherals

    Emic2_ChangeLanguage(cUS_English)                               ' Choose the language of US English
    Emic2_Speak("This is U S English")

    DelayMS 2000
    Emic2_ChangeLanguage(cCastilian_Spanish)                        ' Choose the language of Castilian Spanish
    Emic2_Speak("This is Castilian Spanish")

    DelayMS 2000
    Emic2_ChangeLanguage(cLatin_Spanish)                            ' Choose the language of Latin Spanish
    Emic2_Speak("This is Latin Spanish")

    DelayMS 2000
    Emic2_ChangeLanguage(cUS_English)                               ' Back the language of US English
    Emic2_Speak("Back to U S English")

'------------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()
    Osc_64MHz()                                                     ' Set the microcontroller for internal 64MHz

    Emic2_Init()                                                    ' Initialise the Emic2 board
EndProc

'------------------------------------------------------------------------------------------------
' Set the microcontroller for internal 64MHz
' Input     : None
' Output    : None
' Notes     : For use with a PIC18F25K22 device
'
Proc Osc_64MHz()
    OSCCON = $70                                                    ' SCS FOSC. IRCF 16MHz_HFINTOSC. IDLEN disabled
    OSCCON2 = $04                                                   ' PRISD enabled. SOSCGO disabled. MFIOSEL disabled
    OSCTUNE = $40                                                   ' INTSRC disabled. PLLEN enabled. TUN 0
    Repeat: Until OSCCON2bits_PLLRDY = 1                            ' Wait for PLL to stabilise
EndProc

'------------------------------------------------------------------------------------------------
' Setup the fuses to use the internal oscillator on a PIC18F25K22 device.
' Pins RA6 and RA7 are general purpose I/O.
'
Config_Start
    FOSC     = INTIO67                                              ' Internal oscillator block
    PLLCFG   = Off                                                  ' Oscillator used directly
    PRICLKEN = On                                                   ' Primary clock enabled
    FCMEN    = Off                                                  ' Fail-Safe Clock Monitor disabled
    IESO     = Off                                                  ' Internal/External Oscillator Switchover mode disabled
    PWRTEN   = Off                                                  ' Power-up Timer disabled
    BOREN    = SBORDIS                                              ' Brown-out Reset enabled in hardware only (SBOREN is disabled)
    BORV     = 190                                                  ' Brown Out Reset Voltage set to 1.90 V nominal
    WDTEN    = Off                                                  ' Watchdog Timer is always disabled. SWDTEN has no effect
    WDTPS    = 128                                                  ' Watchdog Timer Postscale 1:128
    CCP2MX   = PORTC1                                               ' CCP2 input/output is multiplexed with RC1
    PBADEN   = On                                                   ' PORTB<5:0> pins are configured as analog input channels on reset
    CCP3MX   = PORTB5                                               ' P3A/CCP3 input/output is multiplexed with RB5
    HFOFST   = On                                                   ' HFINTOSC output and ready status are not delayed by the oscillator stable status
    T3CMX    = PORTC0                                               ' Timer3 Clock input is on RC0
    P2BMX    = PORTB5                                               ' ECCP2 B output mux is on RB5
    MCLRE    = EXTMCLR                                              ' MCLR pin enabled, RE3 input pin disabled
    STVREN   = On                                                   ' Stack full/underflow will cause Reset
    LVP      = Off                                                  ' Single-Supply ICSP disabled
    XINST    = Off                                                  ' Instruction set extension and Indexed Addressing mode disabled
    Debug    = Off                                                  ' Background Debug Disabled
    Cp0      = Off                                                  ' Block 0 (000800-001FFF) not code-protected
    CP1      = Off                                                  ' Block 1 (002000-003FFF) not code-protected
    CP2      = Off                                                  ' Block 2 (004000-005FFF) not code-protected
    CP3      = Off                                                  ' Block 3 (006000-007FFF) not code-protected
    CPB      = Off                                                  ' Boot block (000000-0007FF) not code-protected
    CPD      = Off                                                  ' Data EEPROM not code-protected
    WRT0     = Off                                                  ' Block 0 (000800-001FFF) not write-protected
    WRT1     = Off                                                  ' Block 1 (002000-003FFF) not write-protected
    WRT2     = Off                                                  ' Block 2 (004000-005FFF) not write-protected
    WRT3     = Off                                                  ' Block 3 (006000-007FFF) not write-protected
    WRTC     = Off                                                  ' Configuration registers (300000-3000FF) not write-protected
    WRTB     = Off                                                  ' Boot Block (000000-0007FF) not write-protected
    WRTD     = Off                                                  ' Data EEPROM not write-protected
    EBTR0    = Off                                                  ' Block 0 (000800-001FFF) not protected from table reads executed in other blocks
    EBTR1    = Off                                                  ' Block 1 (002000-003FFF) not protected from table reads executed in other blocks
    EBTR2    = Off                                                  ' Block 2 (004000-005FFF) not protected from table reads executed in other blocks
    EBTR3    = Off                                                  ' Block 3 (006000-007FFF) not protected from table reads executed in other blocks
    EBTRB    = Off                                                  ' Boot Block (000000-0007FF) not protected from table reads executed in other blocks
Config_End

And this demo:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Speech demo from the Emic-2 Text to Speech synthesiser.
'
' Written for the Positron8 compiler by Les Johnson.
' https://sites.google.com/view/rosetta-tech/home
'
    Device = 18F25K22                                               ' Tell the compiler what device to compile for
    Declare Xtal = 64                                               ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Auto_Heap_Arrays = On                                   ' Make all arrays "Heap" types, so they always get placed after standard variables
    Declare Auto_Heap_Strings = On                                  ' Make all Strings "Heap" types, so they always get placed after standard variables
    Declare Auto_Variable_Bank_Cross = On                           ' Make sure all multi-byte variables remain within a single RAM bank
'
' Setup USART1
'
    Declare Hserial_Baud = 9600                                     ' Setup the Baud rate of USART1
    Declare HRSOut_Pin = PORTC.6                                    ' Setup the pin used for USART1 TX
    Declare HRSIn_Pin = PORTC.7                                     ' Setup the pin used for USART1 RX
'
' Setup TX and TX pins (These must be defined before the "Emic2.Inc" file is included
' So that it can see them, otherwise... It will used default pins
'
'$define Emic2_TX_Pin PORTC.6                                       ' Setup the pin used for TX to the Emic2 board
'$define Emic2_RX_Pin PORTC.7                                       ' Setup the pin used for RX to the Emic2 board
$define Emic2_TX_Pin PORTB.3                                        ' Setup the pin used for TX to the Emic2 board
$define Emic2_RX_Pin PORTB.4                                        ' Setup the pin used for RX to the Emic2 board

    Include "Emic2.inc"                                             ' Load the Emic2 library into the program
'
' Create any global variables, Constants and aliases here
'
    Dim bCount As Byte                                              ' Used to count up the numbers to speak
'
' Create text in flash memory
'
    Dim HelloText As Flash8 = "/\/\Hello/\"

'------------------------------------------------------------------------------------------------
' The main program starts here
'
Main:
    Setup()                                                         ' Setup the program and any peripherals
'
' Dennis speaking
'
    Emic2_ChangeVoice(cVoice_Dennis)

    Emic2_ChangeRate(400)                                           ' Speed up the speech rate
    Emic2_Speak("She sells sea shells on the seashore")
    Emic2_ChangeRate(200)                                           ' Change the rate back to normal

    DelayMS 1000                                                    ' Wait between sentences
    Emic2_Speak("__Wow that was__fast")
    DelayMS 1000                                                    ' Wait between sentences
    Emic2_Speak("Over too__yew Betty")
'
' Betty speaking
'
    Emic2_ChangeVoice(cVoice_Betty)
    DelayMS 1000                                                    ' Wait between sentences
    Emic2_Speak("__Thankyou Dennnus")
    DelayMS 1000                                                    ' Wait between sentences

    Emic2_Speak("Here are some numbers")

    DelayMS 1000                                                    ' Wait between sentences
    Emic2_Speak("Here is__Floating Point")
    Emic2_Speak(Dec1 1234.5)                                        ' Speak the floating point number

    DelayMS 1000                                                    ' Wait between sentences
    Emic2_Speak("And here are__Intagers")
'
' Create a loop for the numbers
'
    For bCount = 100 To 110
        Emic2_Speak(Dec bCount)                                     ' Speak the numbers
    Next
    DelayMS 1000                                                    ' Wait between sentences

    Emic2_Speak("And__here is the alphabet")
    Emic2_Speak("A")
    Emic2_Speak("B")
    Emic2_Speak("C")
    Emic2_Speak("D")
    Emic2_Speak("E")
    Emic2_Speak("F")
    Emic2_Speak("G")
    Emic2_Speak("H")
    Emic2_Speak("I")
    Emic2_Speak("J")
    Emic2_Speak("K")
    Emic2_Speak("L")
    Emic2_Speak("M")
    Emic2_Speak("N")
    Emic2_Speak("O")
    Emic2_Speak("P")
    Emic2_Speak("Q")
    Emic2_Speak("R")
    Emic2_Speak("S")
    Emic2_Speak("T")
    Emic2_Speak("U")
    Emic2_Speak("V")
    Emic2_Speak("W")
    Emic2_Speak("X")
    Emic2_Speak("Y")
    Emic2_Speak("Z")

    DelayMS 1000
    Emic2_Speak("__Thank you and goodbye")

'------------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()
    Osc_64MHz()                                                     ' Set the microcontroller for internal 64MHz

    Emic2_Init()                                                    ' Initialise the Emic2 board
EndProc

'------------------------------------------------------------------------------------------------
' Set the microcontroller for internal 64MHz
' Input     : None
' Output    : None
' Notes     : For use with a PIC18F25K22 device
'
Proc Osc_64MHz()
    OSCCON = $70                                                    ' SCS FOSC. IRCF 16MHz_HFINTOSC. IDLEN disabled
    OSCCON2 = $04                                                   ' PRISD enabled. SOSCGO disabled. MFIOSEL disabled
    OSCTUNE = $40                                                   ' INTSRC disabled. PLLEN enabled. TUN 0
    Repeat: Until OSCCON2bits_PLLRDY = 1                            ' Wait for PLL to stabilise
EndProc

'------------------------------------------------------------------------------------------------
' Setup the fuses to use the internal oscillator on a PIC18F25K22 device.
' Pins RA6 and RA7 are general purpose I/O.
'
Config_Start
    FOSC     = INTIO67                                              ' Internal oscillator block
    PLLCFG   = Off                                                  ' Oscillator used directly
    PRICLKEN = On                                                   ' Primary clock enabled
    FCMEN    = Off                                                  ' Fail-Safe Clock Monitor disabled
    IESO     = Off                                                  ' Internal/External Oscillator Switchover mode disabled
    PWRTEN   = Off                                                  ' Power-up Timer disabled
    BOREN    = SBORDIS                                              ' Brown-out Reset enabled in hardware only (SBOREN is disabled)
    BORV     = 190                                                  ' Brown Out Reset Voltage set to 1.90 V nominal
    WDTEN    = Off                                                  ' Watchdog Timer is always disabled. SWDTEN has no effect.
    WDTPS    = 128                                                  ' Watchdog Timer Postscale 1:128
    CCP2MX   = PORTC1                                               ' CCP2 input/output is multiplexed with RC1
    PBADEN   = On                                                   ' PORTB<5:0> pins are configured as analog input channels on Reset
    CCP3MX   = PORTB5                                               ' P3A/CCP3 input/output is multiplexed with RB5
    HFOFST   = On                                                   ' HFINTOSC output and ready status are not delayed by the oscillator stable status
    T3CMX    = PORTC0                                               ' Timer3 Clock input is on RC0
    P2BMX    = PORTB5                                               ' ECCP2 B output mux is on RB5
    MCLRE    = EXTMCLR                                              ' MCLR pin enabled, RE3 input pin disabled
    STVREN   = On                                                   ' Stack full/underflow will cause Reset
    LVP      = Off                                                  ' Single-Supply ICSP disabled
    XINST    = Off                                                  ' Instruction set extension and Indexed Addressing mode disabled
    Debug    = Off                                                  ' Background Debug Disabled
    Cp0      = Off                                                  ' Block 0 (000800-001FFF) not code-protected
    CP1      = Off                                                  ' Block 1 (002000-003FFF) not code-protected
    CP2      = Off                                                  ' Block 2 (004000-005FFF) not code-protected
    CP3      = Off                                                  ' Block 3 (006000-007FFF) not code-protected
    CPB      = Off                                                  ' Boot block (000000-0007FF) not code-protected
    CPD      = Off                                                  ' Data EEPROM not code-protected
    WRT0     = Off                                                  ' Block 0 (000800-001FFF) not write-protected
    WRT1     = Off                                                  ' Block 1 (002000-003FFF) not write-protected
    WRT2     = Off                                                  ' Block 2 (004000-005FFF) not write-protected
    WRT3     = Off                                                  ' Block 3 (006000-007FFF) not write-protected
    WRTC     = Off                                                  ' Configuration registers (300000-3000FF) not write-protected
    WRTB     = Off                                                  ' Boot Block (000000-0007FF) not write-protected
    WRTD     = Off                                                  ' Data EEPROM not write-protected
    EBTR0    = Off                                                  ' Block 0 (000800-001FFF) not protected from table reads executed in other blocks
    EBTR1    = Off                                                  ' Block 1 (002000-003FFF) not protected from table reads executed in other blocks
    EBTR2    = Off                                                  ' Block 2 (004000-005FFF) not protected from table reads executed in other blocks
    EBTR3    = Off                                                  ' Block 3 (006000-007FFF) not protected from table reads executed in other blocks
    EBTRB    = Off                                                  ' Boot Block (000000-0007FF) not protected from table reads executed in other blocks
Config_End

As can be seen, the communication to the EMIC-2 board is very straightforward.

Regards
Les

top204

I have copied your post to here Charlie, because you seemed to have posted it in the wrong thread about the VGA or HDMI interface...

I think I have found a suitable Text-To-Voice unit:

https://www.ebay.co.uk/itm/178394474333?itmmeta=01M14J4MFM5Z8VFSMX9JTG75PG&hash=item298923a75d:g:aEoAAeSwXyBqelq~

I found a demo of it and it sounds good; you can vary the pitch, speed and other params to get a wide range of voices. It has a slight Chinese bias and that will be fine. Any suggestions for a Chinese sounding robot name (without offending the thought police)?

Charlie