Tag Archives: Text to Speech

AI on the Edge LESSON 34: Project Combining TTS, STT, Face Recognition and Servos on Pi 5

In our previous lessons, we built individual components. We got our machine to listen locally using Speech-to-Text (STT), we got it to talk back cleanly with Text-to-Speech (TTS), and we learned how to manipulate physical hardware using precision servos. Today, we bridge the gap between software and the physical world. We are building a multi-threaded, autonomous edge system that tracks humanoids in real time.

The Engineering Mindset: Concurrency & Threading

If you try to build a system like this sequentially—running camera capture, object detection, audio listening, and audio speaking in a single while True: loop—your project will fail completely. Why? Because tasks like waiting for a voice command (stt.listen()) or synthesizing a voice line are blocking operations. If your code is stuck waiting for you to finish speaking a command, your camera frames freeze, your servo adjustments drop to zero, and your humanoid target escapes.

To solve this, we architect our software using Multi-threading. We spawn independent execution paths that run concurrently, passing data back and forth safely using thread-safe Queues:

  • The Main Thread: Handles the high-speed Picamera2 video capture loop, executes Haar Cascade face/eye calculations, and updates the servo angles via mathematical error tracking.
  • The Speak Thread: Idles quietly in the background until a message lands in the speakQ, instantly triggering the local Piper TTS engine without stalling our camera frame rate.
  • The Command Thread: Keeps a continuous ear open via our local STT engine. When it parses a voice command like “track”, “release”, or “quit”, it safely pops that token into the commandQ for the main loop to execute on its next pass.

The Complete Fusion Architecture Code

Below is the complete Python pipeline developed in today’s lesson. Make sure your hardware connections for the pan-and-tilt servos match pins 2 and 3 on your expansion setup, and verify your fusion_hat software stack is completely updated.

Breaking Down the Math & Logic

Pro-Tip on State Debouncing: Notice how we handle messages using the cnt variable and the msgOld buffer. If we simply asked the system to say “Humanoid Detected” every single time the frame loops, the TTS engine would crash from queue overflow, stuttering continuously. By checking if msgOld != msg, we ensure the system speaks a notification exactly once upon transition. The 25-frame hysteresis buffer ensures that a single missed frame doesn’t cause a false “No Humanoid” trigger.

Proportional Error Tracking

Look carefully at how the servo angles are adjusted:

We are calculating the error vector—how many pixels the center of the bounding box (xBoxC) is from the absolute center of our camera stream (xFrameC). Instead of moving the servo by a fixed step, we move it proportionally to the size of the error. Big error? Fast movement. Small error? Gentle, microscopic correction. Dividing by 50 dampens our proportional gain loop so our servos don’t violently oscillate and throw our camera system completely out of alignment.

Your Homework Assignment

You have the system reading frames, listening asynchronously, and adjusting angles proportionally. Now it’s time to earn your stripes as an edge systems designer.

Your Assignment: Look at our msg tracking logic. Right now, if a humanoid is detected, it simply asks, “Shall I track?”. Your task is to tie our speech input directly to this state. Modify the control flow so that the tracking logic requires verification. If a humanoid is detected, the system must wait until the commandQ yields a verified verbal confirmation—like “execute” or “yes”—before the proportional servo tracking begins. If it hears “abort”, it must break off and look away.

Drop your custom implementation script in the comments section below, explain the logic behind your state modifications, and let’s see how you optimize your loop efficiency. Go get ’em!

AI on the Edge LESSON 9: Make Your Raspberry Pi Talk with TTS

In today’s lesson, we’re going to make a huge leap forward in giving our Raspberry Pi some real personality. We’re going to teach it how to talk using Text-to-Speech (TTS). Instead of just blinking LEDs or printing text to the screen, our Pi will now speak out loud with a clear, natural-sounding voice.

This is a really fun and important lesson because one of the main goals of this class is to build intelligent systems that can interact with us in more human ways. Being able to make your Raspberry Pi speak opens up all kinds of exciting possibilities — whether you want your robot to tell you what it sees, have your AI assistant read sensor data out loud, or just add some personality and humor to your projects.

In this video, I show you how to use the TTS capabilities on the SunFounder Fusion AI Hat. You’ll learn how to install and set up the TTS engine, speak simple sentences, change voices, and control when the Pi talks. We’ll also look at how to make the speech sound more natural and how to integrate it smoothly into your programs without freezing everything else.

By the end of this lesson, your Raspberry Pi will be able to speak clearly and confidently — which is going to make the rest of our AI on the Edge journey a lot more exciting. Voice output combined with voice input (which we’ll work on soon) is what turns a simple circuit into a real interactive AI companion.

So go ahead and grab your Fusion AI Hat, plug in a speaker, and let’s give your Raspberry Pi a voice! As always, I encourage you to code along with me in the video and then experiment. Try making it say funny things, read temperatures, announce when it detects a face — whatever sparks your creativity.

This is where your projects start to feel truly alive.

I’m really excited for you on this one — let’s make your Raspberry Pi talk!

This is the schematic we are using on these projects;

Fusion Hat Circuit Diagram
This is the circuit we will use moving forward in the class

This Schematic is explained in detail in LESSON #5.

Then this is the code we developed in today’s lesson.