Showing posts with label Arduino. Show all posts
Showing posts with label Arduino. Show all posts

Wednesday, 29 October 2025

Major Milestone

Hi all,

We did it, folks! After what felt like an eternity of juggling tiny wires, questioning all my life choices, and occasionally wishing I had a third hand, I hit a massive milestone on the DANI project yesterday. It's the kind of milestone where you realize your ambitious little Frankenstein monster might actually walk one day—or, at least, successfully power on without tripping a breaker in the garage.

Hardware Complete (Sort Of)

All the core pieces are finally tucked neatly into their places, which is a huge win. The only big-ticket item left on the bench is the RDK X5 for the LLM, but honestly, that’s like waiting for DANI to hit puberty; it’s an inevitable future problem that we’ll handle when the time comes.

For now, we got the essential life support hooked up:

  • The battery is snug and operational.

  • A dedicated temperature sensor is in place for fan control. We've got to keep DANI cool under pressure, especially when he starts wrestling with complex AI problems (or, you know, my shoddy early-stage code).

  • And the real game-changer: a voltage meter. This means DANI can now tell me when his battery is running low. This is a huge step up from the previous system, which was essentially "flicker dimly and then dramatically die mid-sentence."

Now for the slight confession: for the immediate future, he still needs me to play charger-daddy and physically plug him in. But fear not, the ultimate goal involves a glorious, automated self-charging station. DANI needs to learn to feed himself, after all—I can't be doing this forever!

Diving Into the Code Matrix

With the hardware stable, we pivot to the messy, beautiful, and sometimes existentially horrifying world of code. I've successfully laid the foundation for the majority of his core functions:

  • Sensor Input: He can now 'feel' the world around him.

  • Speech-to-Text and Text-to-Speech: He can hear me and talk back! Right now, his vocabulary is purely transactional, but it's a solid start. We're well past the awkward mumbling phase.

However, the more sophisticated stuff—the LSTM (that's the deep learning magic) and his memory structure—are currently just written out, waiting for their turn to be integrated. They’re functional pieces of code, but they're not yet plugged into DANI’s neural network. They’re basically that brilliant but currently unemployed friend crashing on your couch, waiting for the job offer to come through.

The Road Ahead: Vision, Brains, and APIs
For once, an actual photo of me working on DANI

My immediate to-do list involves a lovely date with an Arduino Nano to fully finalize all those sensor inputs. We need to make sure DANI has perfectly mapped out his surroundings before we give him eyes.

Once the senses are online, we move to the next critical developmental stage: vision! I’ll be coding up the K210 for the YOLO and FaceNet models. This is when he graduates from "blurry blob recognition" to "Wait, is that the mailman again?"—a crucial upgrade for home security and general social interaction.

Finally, the heavy lifting on the Raspberry Pi (which is essentially his main thinking engine) begins, and I’ll be firing up an API for the LLM on my home server. It’s a temporary solution until the RDK X5 arrives, but you use what you have.

Wish me luck—may my coffee stay strong and my bugs stay trivial! More updates soon!

Tuesday, 17 June 2025

Confessions of a Best Practice Hoarder


There are few tasks a developer enjoys more than writing documentation. It’s a thrilling journey into the exciting world of code formatting and variable naming conventions, right up there with untangling someone else’s regular expressions. So, you can imagine my sheer, unadulterated joy when I was asked to create a "Best Practice" document for my team's C# projects.

Okay, my sarcasm meter is now switched off. It was, in fact, a necessary and useful exercise. While C# isn't the language that sings me to sleep at night, it's a powerful tool (and a country mile better than Java). The goal was to create a shared map for our team, a guide to writing code that our future selves wouldn't want to travel back in time to prevent. The document covers the essentials: SOLID principles, consistent naming conventions, and key architectural patterns like Dependency Injection. It also provides guardrails for C#-specific features, like the right way to use async/await and how to query data with LINQ without accidentally DDOSing your own database.
C#
The result is a common language for quality. It makes our code reviews more productive and helps everyone, from senior to junior, stay on the same page.

Opening Pandora's Box
With the C# guide complete, a dangerous thought crept in over the weekend: "I wonder what this would look like for my other languages?" This was a classic case of a weekend project spiralling into a minor obsession. I fired up my editors and, in a fit of what I can only describe as productive procrastination, began creating similar guides for Lazarus/FreePascal, Go, Arduino C++, and Cerberus-X.
What started as a simple comparison turned into a fascinating exploration of programming language philosophy. The exercise proved that while principles like DRY (Don't Repeat Yourself) are universal, the "best" way to implement them is anything but.

A Tale of Five Philosophies
The way a language handles common problems tells you a lot about its personality. The differences are most stark in a few key areas.

Memory Management: From Butler Service to DIY Survival
How a language manages memory fundamentally changes how you write code.
  • C#: Has a garbage collector, which is like a butler who tidies up after you. It’s convenient, but you still need to know the rules. You have to explicitly tell the butler about any special (unmanaged) items using IDisposable, otherwise, they'll be left lying around.
  • Arduino/C++: This is the survivalist end of the spectrum. You have a tiny backpack with 2KB of RAM, which is less memory than a high-resolution emoji. Every byte is sacred. Heap allocation is a dangerous game of Jenga that leads to fragmentation and mysterious crashes. The Arduino String object is a notorious trap for new players, munching on your limited memory. Here, best practice isn't just a good idea; it's the only thing keeping your project from collapsing.
  • Go: Also has a garbage collector, but it’s more of a silent partner. The language and its idioms are designed in such a way that you rarely have to think about memory management. It just works.
  • Cerberus

    Cerberus-X:
    As another high-level language, Cerberus-X handles memory automatically. The developer's main responsibility isn't freeing memory, but ensuring its state is predictable. The most crucial best practice is to always use the Strict directive. This is the "no more mystery values" setting, as it enforces that all variables must be initialized before use , saving you from the bizarre bugs that come from variables defaulting to 0 or an empty string in non-strict mode.
  • Lazarus & FreePascal: The "Choose Your Own Adventure" Model
This is where things get really interesting. FreePascal offers a mixed model for memory management, letting you pick the right tool for the job.
    • The Classic Approach: This is pure manual control. Every object you create with .Create is your responsibility, and you must personally ensure it is destroyed with a corresponding .Free call. The try..finally block is your non-negotiable safety net to guarantee that cleanup happens, even when errors occur. It’s the ultimate "you made the mess, you clean it up" philosophy.
    • FreePascal cheetah

      The LCL Ownership Model: The Lazarus Component Library gives you a helping hand, especially for user interfaces. When you create a component, you can assign it an Owner (like the form it sits on). The Owner then acts like a responsible parent: when it gets destroyed, it automatically frees all the child components it owns. You should not manually .Free a component that has an owner.
    • The Modern Approach: To make life even easier, FreePascal supports Automatic Reference Counting (ARC) for interfaces. When an object is assigned to an interface variable, a counter is incremented. When that variable goes out of scope, the counter is decremented , and once it hits zero, the object is automatically freed. This brings the convenience of garbage collection to your business objects, drastically reducing the risk of memory leaks.
Concurrency: An Assembly Line vs. The Office Worker
  • C#: async/await feels like delegating a task. You ask a subordinate (Task) to do something, and you can either wait for the result (await) or carry on with other work. It's efficient and clean.
  • Go

    Go:
    Go's model is more like an automated assembly line. You have multiple workers (goroutines) and a system of pneumatic tubes (channels) connecting them. Workers perform their small task and send the result down a tube to the next worker, all happening simultaneously.
  • Arduino/C++: You're a solo act on a mission. There are no threads, so you can't do two things at once. The entire game is to never stop moving. You check a sensor, update a light, check a button, and repeat, all in a lightning-fast loop(). A delay() is your worst enemy because it brings everything to a grinding halt.
  • Lazarus/FreePascal: This is the classic office worker. To avoid freezing the UI during a long operation, you spawn a TThread to do the heavy lifting in the background. When the worker thread needs to update a label on the screen, it can't just barge in. It has to use TThread.Synchronize or TThread.Queue to politely tap the UI thread on the shoulder and ask it to make the change safely.
  • Cerberus-X: This is the resourceful indie developer. It doesn't have the fancy built-in machinery of async/await. To achieve non-blocking operations, it falls back on the fundamental tools, letting the developer build their own solution using threading or designing methods with callbacks.

Error Handling: The Town Crier vs. The Smoke Signal
  • C# & Friends: Languages like C#, Lazarus, and Cerberus-X prefer the "town crier" approach of exceptions. When something goes wrong, they shout about it loudly, and a try...catch block is expected to handle the commotion.
  • Go: Go has trust issues. It prefers you to look before you leap. Functions return an error value alongside their result, forcing you to confront the possibility of failure at every single step.
    Arduino C++

  • Arduino/C++: When your code is running on a chip in a field, how does it cry for help? It uses a smoke signal. There's no console, so robust error handling involves returning status codes or, in a critical failure, entering a safe state and blinking an LED in a specific pattern—a primitive but effective "blink of death" to signal an error code.

Up for Grabs
This dive into different programming paradigms was a blast. It’s a powerful reminder that there’s no single "best" language, only the right tool for the job, with its own unique set of best practices.

I’ve cleaned up all five documents and made them available for download. If you work in any of these languages, I hope they can be of some use to you. Now if you'll excuse me, I think I see a dusty corner of the internet where a language is just begging for a best practice guide. It's a sickness, really.


Grab them, use them, and happy coding!

Aiming for Jarvis, Creating D.A.N.I.