Thursday, December 01, 2016

The Mind of a (low level) Systems Programmer

I'm a systems programmer... an obsolete term, indeed.  But that is what I am.  It's not about coding in assembly (fun!) or squeezing out every drop of optimization in C (double fun!), but it is about wanting to "make" systems.

Compare this with an "application programmer" (another archaic term).  They love the domain.  I love the innards, the thing that runs the application.  My work should be silent and never seen. My stuff needs to just "work".

I like watching my front loading washing machine run. It is a complete system, but no fancy UI or IoT interface to be seen. It has sensors, it has actuators, it spins.... that's it.
Most of the time it works (it's getting old so there are a few faults here and there).  But it is successful because no one thinks about it. It lies in the background of our lives, silently do its job.

A year ago I had to replace the logic board in my HVAC. It was expensive ($700 list -- but I got mine new from ebay for around $400).  The complexity (and wonder) of that board is that it has to be as solid as NASA system.

My HVAC uses natural gas.  A lot of the components on that board (and the logic / program) are there to make sure my house doesn't blow up.  No fancy interface. No operating system. No complex 32-bit floating point math (I assume... I mean, my house shouldn't blow up do to a rounding error, right?).

I installed the Hunter ceiling fan, in my bedroom, over 15 years ago. It runs every night and mostly through the day. It has never failed. It is still silent. I wonder what kind of motor it has built in and how it is commutated (must be AC since brushless DC wasn't widely available back then -- I think).

That was a good design... a systems design.

Sunday, November 27, 2016

Excessive Portability and Embedded Development

Which is better?


/* Read the angle register (ANGLECOM) */
angle = spi_write(0xFFFF);

or

/* Read the angle register */
angle = spi_write(A_READ | A_PARITY_1 | A_ANGLECOMREG);

Now, you don't have to understand exactly what's going on here (and the actual process of reading an angle from the AS5147 rotary position sensor is a little bit more complicated), but I am trying to make a point.

I would argue that the second code snippet is a waste of time. (Some presumptions here: You had to define A_READ, A_PARITY_1 and A_ANGLECOMREG).

But, why would I advocate the hard coded version?

  1. The chip (AS5147) isn't going to change SPI command structure anytime during its production cycle.
  2. If you choose a new chip, you are going to have to study it and figure out the hard coded values anyway.
  3. The abstraction in the 2nd code snippet is going to only work for this exact chip.
  4. You have to work out the bit twiddling anyway (to come up with A_READBIT, etc)
  5. 0xFFFF is what you will see in your debugger
  6. It is *always* 0xFFFF 
  7. Ease of modification doesn't work here. If you go "oh, that should be A_PARITY_0" and change it (without verifying the actual resulting write value, it is going to cause a lot of debugging woes).
This is sort of an argument between "ease of writing" vs "ease of debugging" and in embedded development, "ease of debugging" is what you are really shooting for (or maybe call it "ease of validation").

I see the same thing happening with STM32's HAL or StdPeriph.  There is a focus on making it easier to load up registers (often taking 1 line of register loading code and stretching it into multiple lines of structure loading using verbose enums/types you have to look up).

To be honest, when I work in Forth on the STM32, I don't have such luxuries and my program is full of well documented hex and binary register banging.

Monday, November 14, 2016

Attack At Dawn


This is a painting on display at The Walters Museum in Baltimore Maryland. (http://art.thewalters.org/detail/4911/the-attack-at-dawn/).   It is by "Attack At Dawn" by Alphonse de Neuville.  

I am not particularly a fan of military battle scenes, but there is something about this painting that I can't get the image out of my head. 
This photo does it no justice.  The somber, winter setting, the lighting, the mastery of painting techniques. It is not a famous painting, but it does so many things that resonate with me: The distant foggy morning sky, the snow, the dim light sources (e.g. dawn, the lamp post, the doorway on the left, the rifle fire), the sparse brush strokes, the sense of desolation.
Go see it, if you can.


Literate Programming... A Revisit

For someone reason (nostalgia?) I've been re-visiting Donald Knuth's concept of Literate Programming.

(For a quick intro, critique and discussion on this approach see this blog entry and the responses.)

I first discovered Literate Programming via looking at TeX sources in the 1980s.  Then I became somewhat obsessed with the approach around 1992 with the publication of Literate Programming by Knuth. This is still one of my favorite books on programming.

I still like to thumb through TeX: The Program (likely the largest Literate Program ever written).

Perhaps I am starting to revisit Literate Programming because of my full-time-deep-dive into embedded programming (again).  Still stuck with C and code that is supposed to work (I deal more with "firmware" than software these days -- code that can't just be frequently updated, is hard to unit test and must be very, very reliable).

Literate Programming doesn't fit well in today's rapid development, big team, fastest-time-to-market culture.  But, when I am writing control systems with little instructional software/literature available (e.g. learning how to spin a BLDC motor using sinusoidal waves), I start thinking about approaching it in a literate style.

Shhh... don't tell my partners, but I am definitely thinking about using cweb  or perhaps cwebx for this ;)


Tuesday, November 08, 2016

SPLAT Logic Analyzer

Found: A Logic Analyzer written in Tachyon Forth on a Parallax Propeller chip.
This is insane.  I love it.
https://docs.google.com/document/d/1vszFLwzIfwMEqe2vWA0y4HwVIc4uVpxyjmApKNlY8QQ/pub

Somewhere, in a box, at my last job, is an "over the air" (GSM/SMS) remote control device that I developed using the Propeller chip and Tachyon Forth.  It was a prototype I  put together in less than 2 months and "field tested".  It was an interesting (and fun) experience. I would have love to have used this logic analyzer during development.

Tuesday, October 04, 2016

Spinning a motor is hard

I'm trying to spin a 3 phase motor really, really slow.   For this I have chosen Sinusoidal Commutation.  Just a few sine calculations and I'm good, right?

Ugh.

Sinusoidal commutation of BLDC motors is hard.  Even so-called "open loop" commutation (which still expects feedback -- is it still really "open"?) is difficult.

You can find a google load of papers on how to perform (6 step) trapezoidal commutation and then some that kind of talk about sinusoidal.

It's all maddening and the reason why motors are its own field of study.  Lots of physics. Lots of math. Lots of stuff you can't shortcut.  Jerk, torque ripple, back EMF.  Don't get me started on rotors and pole count.  How about Phase finding?  Know how to do that?

To spin, you must have feedback!  Don't Hall effect sensors? How about with angular magnetic encoders? If you are man (or woman) enough, you venture into FOC.

I'm spending weekends and some weeknights learning how to spin a motor so me and my partners can build a killer robotic application. (Killer may be a bad choice of words....)

I'm really learning how much I don't really know.

Spinning a motor is hard...



Tuesday, May 24, 2016

Taking a SIP from the VoIP fountain....

Bad metaphorical post title aside (ouch),  I am currently investigating "cutting the Vonage cord" (another bad metaphorical allusion).

I haven't had a proper land line in 10 or so years. Vonage has served me well.  But, I find that with everyone in my family owning a smartphone, we rarely use our home phone line.  As anyone who has called us will know, sometimes we can't find our "wireless" phone(s) -- is it buried in the couch cushions again?  We are also horrible about retrieving voice mail (even though we have Vonage forward transcripts to our smartphones).

Really, outside of having a number "for our house", we don't use it much.  But our monthly bill for this convenience is over $30 per month!  I know, I know... why don't we just find a lower cost VoIP provider?  But that still requires us having to swim in someone else's pool (sorry about that, there I go again).

But, hey... wait a minute!  I am a software engineer who specializes in communication.  There must be something I can do here.  All I need is some way of getting my home phone number to forward to a PBX under my own control.  Think of the things I could do!

I could...

  • Have the call ring to any smartphone that is registered on my Wi-Fi (i.e. mine and my wife's phones when we are home)
  • Forward the call to voice mail immediately if we aren't home.
  • Register another "business" phone number that does something similar... basically track me down (e.g. smartphone or home number or voicemail)
..and so much more!

So, I start looking at FreeSWITCH and Asterisk.  Wow!  I need a book, or two, and a lot of time.
(Another variation of swimming in someone else's pool).

Okay, so do I really need a full blown PBX to do this?  Nope. I can do most of this with a cheap DID (Direct Inward Dialing) provider that could forward to a SIP proxy (of my own configuration or design).  (I won't go into details about SIP here... just know that it is the standard Internet way of locating and setting up calls. It is pretty complex too, but it is fundamentally a protocol specification.)


So, I start looking at OpenSIPS and over SIP server solutions.  It looks like all the pieces are there to do what I need. I just need to write a script....

Okay. My engineer senses start pulsing again (sort of like Spiderman's senses but rather than danger it warns me that I am about to use a complex system to do what seems so simple in my head).  I don't want to solve my problem with a simple OpenSIPS configuration... I want to intimately understand what is going on inside of SIP and implement just enough to do what I want.  How better to learn a system than to dive right in and try to build one yourself?

By learning OpenSIPS, I'll become an OpenSIPS expert but I won't really know how SIP works.   Sure, they take care of the plumbing, but I am interested in the plumbing.

So, I start with the SIP RFC .  Well that's over 200 pages!  Okay, Todd.. slow down. What do I minimally need to let two VoIP user agents (i.e. phones or smartphone apps) talk to each other?

I start from there.... and here I am today.  I've got some primordial code handling SIP registrations over UDP.  I have a long way to go, but I am going to have fun with it and I am going to learn a lot. 

Maybe I'll finish enough of it to put it out there as open source. Not an OpenSIP competitor, but a super simple, super hacky way of creating your own lightweight home VoIP system.

Note: Currently using LuaJIT and Copas socket server to play around with SIP and I as I mentioned above, I've got Registration working.  Ooooh... so much fun!

Saturday, April 09, 2016

Hackable (Software) Things

I like hackable things. I'll keep that vague, because I am in a vague mood.
See if you can spot the common theme:

  1. Emacs
  2. TeX / LaTeX
  3. Forth (interactive on an MCU)
  4. Snabb Switch
  5. Smalltalk  (Squeak)
  6. Unix command line (awk, sed, kornshell, bourne shell, maybe bash, etc)

Okay... why?

They are worlds at my fingertips.
They don't use XML.
They are extensible.
I can make them do useful things.
With the exception of #3 (Forth), none really manipulate the "physical world".

Speaking of Forth... having shipped a few professional devices built with Forth, I still haven't found anything nearly as useful or fun for MCU work.

Something I would love to have for embedded MCU work:

A nice REPL / Editor environment (host side, please) for manipulating/deploying eLua on MCUs. 
eLua has poor interactivity support, but I wonder if remotely instrumenting it is a better approach... maybe via ZeroBrane or Emacs?