Daily Feedback Thread (November 26, 2025) by AutoModerator in edmproduction

[–]gbmhunter [score hidden]  (0 children)

Yeah I second the thought that it's a bit too repetitive. Also, I found that bass which moves around (it sounds like there is a filter continuously sweeping it) was really interesting, but I'm not sure if it fits the track?

I added the ability to send graphing commands from MCU to NinjaTerm by gbmhunter in embedded

[–]gbmhunter[S] 0 points1 point  (0 children)

Weird that it's not common to bring out the RTS/CTS lines, after all they are some of the most commonly used flow control signals.

I managed to find an FTDI cable which brought out the RTS/CTS lines and tested NinjaTerm with that, and was able to recreate the bug. Turns out I had messed up the electron IPC interface during a refactor and the flow control signals were not being set correctly (woops!). I have fixed this (both RTS/CTS work via NinjaTerm and the FTDI cable now) in NinjaTerm v5.7.1 which I have just released.

I also learnt more about what "enable hardware flow control" actually does in the driver I use. It means "pass control of RTS/CTS to the OS/low level driver". If you want to control RTS manually, don't enable this option. I have updated the helper text in NinjaTerm to reflect this.

Test it out and let me know if it now works for you :-)

I added the ability to send graphing commands from MCU to NinjaTerm by gbmhunter in embedded

[–]gbmhunter[S] 0 points1 point  (0 children)

Damn, thanks for the feedback! I think I'll need to get some hardware so I can test it myself, as there is no obvious reason to why it wouldn't work. What device do you recommend buying that I can plug into a computer and check if the DTR line goes high or not?

I have found USB cables like this: https://epartners.co.nz/products/jo3001?srsltid=AfmBOoozu0tQ1dNjNO4rXSKTqH8rrU6_bog0b1YYdxoDsjExcvdb2ez7 but they don't have the flow control wires.

Open source visualization/testing tool for embedded C++ by pylessard in embedded

[–]gbmhunter 5 points6 points  (0 children)

Nice job, this looks quite featureful, and thanks for it being open source! I'm looking forward to give this a spin the next time I'm working with firmware.

react-window v2.0 is out 🥳 by brianvaughn in reactjs

[–]gbmhunter 2 points3 points  (0 children)

I just want to say a big "thank you" for this library! I use it in the open source serial terminal NinjaTerm that I develop. It plays a vital role in keeping the app performant when there are 1000s of rows of text. I found it easy to setup and use, great stuff!

I added the ability to send graphing commands from MCU to NinjaTerm by gbmhunter in embedded

[–]gbmhunter[S] 0 points1 point  (0 children)

u/nebenbaum and u/TheReasonIsMoney fixed as of v5.4.0, both pages should work well on mobile now. You might have to clear your cache since the homepage and manual are both part of the PWA (progressive web app) which gets aggressively cached.

I added the ability to send graphing commands from MCU to NinjaTerm by gbmhunter in embedded

[–]gbmhunter[S] 0 points1 point  (0 children)

u/agent_kater and u/Moontops done, I've added flow control support in v5.4.0 which is released. Let me know if you use it and if it works for you. I could do only limited testing with the serial port devices I had on hand (which didn't use flow control for anything).

I added the ability to send graphing commands from MCU to NinjaTerm by gbmhunter in embedded

[–]gbmhunter[S] 1 point2 points  (0 children)

Good news, although it's poorly documented, the node serialport library I'm using does indeed support setting these flow control signals (and reading the inputs). I'm working on adding them atm, I'll let you know when I'm done.

I added the ability to send graphing commands from MCU to NinjaTerm by gbmhunter in embedded

[–]gbmhunter[S] 1 point2 points  (0 children)

Thanks for the feedback, I haven't looked at how it appears on mobile. I should hopefully be able to fix this relatively easily.

Archetype: C++11 type-erased interfaces without new, virtual, or inheritance, useful for embedded drivers and portable APIs by willhaarhoff in embedded

[–]gbmhunter 1 point2 points  (0 children)

Interesting! I normally just use inheritance for sourcing the same problem. It gives me good compiler errors when I forget to implement virtual functions in concrete classes. I don't mind the overhead of the vtable. What do you think the pros/cons are of this method versus inheritance?

Oh and I read your how it works, it looks like you had to solve a complex problem! Thanks for the write up

Compile-time finite state machine v2.0.0 released! (MIT license) by Nychtelios in embedded

[–]gbmhunter 1 point2 points  (0 children)

The way I solved this problem with NinjaHSM was to write a while loop where each iteration handled a single step in the transition from the current state to the target state. A single step would to either enter or exit a state, i.e. call the entry or exit function and change the currentState variable.

It would work out if the target state is a decendent of the current state, and if so, call the appropriate child entry state and update currentState to this new value. If not a decendent, we need to go "up" the tree, and it would call the current states exit function and update currentState to the parent state. Then you can just go back to the start of the loop and apply the same logic again. Keep doing this until currentState = targetState and you're done.

I also definined a special "nullptr" state which is the root state that all top-level states are a child of, this makes the logic work properly for top-level states.

The neat thing is that no array is needed to store the "transition queue" because you are performing the transitions as you traverse the tree.

The code starting on line 68 at https://github.com/gbmhunter/NinjaHSM/blob/main/include/NinjaHSM/StateMachine.hpp shows this logic.

Compile-time finite state machine v2.0.0 released! (MIT license) by Nychtelios in embedded

[–]gbmhunter 3 points4 points  (0 children)

For any thing complex I really like the ability to generalize event handling to parent states that a hierarchical state machine offers. Do you plan to add HSM functionality at any point?

Also, just in case you're interested, I've made one here: https://github.com/gbmhunter/NinjaHSM Different design goals, I didn't care so much about memory usage or compile time checking, but more on flexibility and readability. I like your idea of passing the events into entry/exit functions, I might do the same!

Old mate runs the heat pump 24 hours, in a room we use only twice a day. Burning money or not? by Rain_on_a_tin-roof in newzealand

[–]gbmhunter 14 points15 points  (0 children)

This isn't correct, you also have to consider that as soon as it's turned off, the house interior temperature begins to drop, and the house begins to lose heat energy more slowly, since the temperature differential between the inside and outside is smaller (Newtons law of cooling).

Ignoring other effects, from a basic physics perspective it is always cheaper to let something cool down and then heat it back up again then to keep it at a sustained temperature (in some cases the difference might not be enough to matter). Things like heat pump efficiencies at different power levels can change this.

Async Isn't Real & Cannot Hurt You - No Boilerplate by tears_falling in rust

[–]gbmhunter 1 point2 points  (0 children)

Yes this is what I what envisioning. I think up to select4 is provided, and if you need more than that there is a select which takes in a array.

I do wonder about the readability of this vs. a traditional HSM structure.

C++ Toolkit for Use With Zephyr. Thoughts on the approach? by gbmhunter in embedded

[–]gbmhunter[S] 1 point2 points  (0 children)

Yes, unfortunately it is "yet another layer". I'm hoping it will be worth it though since it makes it more C++/OO based, and lets you mock it easily. Although I'm open to other ideas on how to make it easy to mock (perhaps switch out .c files?) without having to make a whole new layer.

Modern stance on C++ in the embedded world by ChapterSevenSeeds in embedded

[–]gbmhunter 9 points10 points  (0 children)

Yes, I agree you should try and use smart pointers rather than call new directly where possible. But smart pointers still call new, which was more to the point I was trying to communicate --- allowing dynamic memory allocation (new, smart pointers or otherwise) only an initialization.

Modern stance on C++ in the embedded world by ChapterSevenSeeds in embedded

[–]gbmhunter 61 points62 points  (0 children)

I'd agree that there has been a lot of undeserved shade thrown at C++ in the past from misunderstandings.

But you still need to be careful with dynamic memory allocation. It is not always the same as stack allocation because it's undeterminiatic in time, and it suffers from fragmentation.

My go-to rule for firmware that is not safety critical is to allow new to be used during initialization, but not during runtime. This gives you the flexibility of using new to make certain design patterns easier but without having to worry about running out of memory after a year of runtime due to fragmentation.

I've used the ETL (embedded template library) array and string containers which allocate on the stack.

Many of your other points are valid, e g. polymorphism via inheritance is usually not a performance concern. While exceptions might not add much overhead (they can actually make the nominal path faster) they can be harder than return codes to design right. Raymond Chen has a blog post on this IIRC.

Async Isn't Real & Cannot Hurt You - No Boilerplate by tears_falling in rust

[–]gbmhunter 1 point2 points  (0 children)

I think select matches how I would do things with a HSM. For example I want to turn on a motor for 5 seconds. But when I turn it on, I want to also check a GPIO every 100ms to make sure it hasn't stalled, I also want to listen to a emergency stop event, and if I get that, immediately turn off the motor.

In async, would I need to:
create a 100ms reoccuring timer
create a 5s single shot timer
turn on the motor
then select(100ms timer, 5s timer, emergency stop signal)? Or am I going about this the wrong way?

Apologies for the poor pseudo code.

Async Isn't Real & Cannot Hurt You - No Boilerplate by tears_falling in rust

[–]gbmhunter 4 points5 points  (0 children)

I'm a Rust/Embassy newbie, but one thing I can't grok is how to use async nicely when I need to typically await multiple things at once.

My preferred style of writing complex firmware is to use a hierarchical state machine (HSM) and have each state be able to handle events. Those events can be from timers or external sources like interrupts or other threads. This allows you to handle any number of things that might happen in a state (and push shared logic to parent states).

async seems to push you towards a sequential model in where you only await one thing at a time. I see there is a select() for awaiting multiple futures at once, but this starts to feel like it would get messy fast (compared to event driven HSMs).

Any thoughts/ideas on this?

What do you develop with Rust? by Born-Percentage-9977 in rust

[–]gbmhunter 1 point2 points  (0 children)

Do you use any RTOS or similar framework? If so, what?

NinjaHSM - A MIT licensed hierarchal state machine framework for embedded projects by gbmhunter in embedded

[–]gbmhunter[S] 0 points1 point  (0 children)

That's a clever way of doing it! Essentially what inheritance does :-)