The Wires Are Out Of Control

You have to start by admitting you have a problem

OK, it looks like I’m on the right track.

But, that made things worse in other ways.

Really?

Let’s make some progress on the power.

Having a lab assistant is awesome

Finally…

You can see:

  1. My new work Windows laptop
  2. My personal Mac
  3. A 4K display that is switched with a KVM under the desk
  4. The Jetson Nano that I am currently working on
  5. The Thunderbolt hub connected to my Mac
  6. A beautiful antique magnifying glass
  7. A Weller soldering iron
  8. An amazing Leica microscope
  9. My Linux box (under the desk).  It is attached via display port to the monitor – but it is mostly logged into via the network
  10. A paper protractor that my daughter made when she was little
  11. A paper Go Dad flag made by my daughter when she was little
  12. UK (BSEE) & Georgia Tech (MSEE) Diplomas
  13. Part of my photojournalism portfolio
  14.  My new work phone on the wireless charger
  15. A pack of post-it-notes
  16. A paper tracing of my Katana done with the NBTHK Hozon

Stupid Python Tricks: Implementing a c-switch

Summary

A discussion of a simple method in Python to implement the equivalent of a c programming style switch.

Story

Recently, I was working on an example where I would have used something like this if I was programming in C (emphasis on like)

And, as you know, I am not a real Python programmer.  I tried switch… obviously to no avail.  So now what?  Well in the example above I have

  • A list of keys, the enumerated opcode_t
  • That have a values e.g. “opcode 0” etc.

Sounds like a dictionary.  Here is the equivalent code in Python:

But what happens if a key is missing?  The bracket[] method of a dictionary is equivalent to the dictionary method “get”.   The “get” method has a default case if they key is missing from the dictionary.  Here is the example code:

What if you want to do something?  Values in dictionaries can be “function pointers” (is what I would call them in C).  They are probably properly called references in Python.  Regardless, here is some absurd code that demonstrates the example.

My mDNS Example

The example that lead me to this problem was decoding mDNS headers which have 8 fields of different lengths and possible values.  Here is what I actually did:

PSoC 6 SDK OneWire Bus (Part 5): Round out the OWB driver

Summary

This article shows the completion of the PSoC 6 SDK One Wire Bus library.  It shows the test apparatus for evaluating DS18B20 sensors.

Story

If you remember from the previous articles, I created the one wire bus library by looking at the function calls in the DS18B20 library and reverse engineering the function prototypes.  And, as I said in the earlier article, it would have been way better to just look at the David Antliff “OWB” library.  But that is not how it went down.  I wonder how much time in the world is wasted by programmer re-implementing code that already exists?

After the first four articles, I had three functions which the DS18B20 library defined, but I had not yet implemented.

I had not implemented them because I was not totally sure how they worked.  So, I decided to go back to GitHub and see what David had done originally.  When I got to the GitHub site, https://github.com/DavidAntliff/esp32-owb/blob/master/include/owb.h, there were actually quite a few functions in his owb library that I had not implemented.

Here is the list:

In this article I will create and/or copy the missing functions.  As I look through his implementation I also notice that we have some style differences that I will discuss.  In general I will say that his implementation is very good and any place that I did something different was just a matter of programming taste.

I was originally planning on this article taking you linearly through how I did the changes, but in reality I jumped around while I was doing the changes, that approach won’t work.  Here is the list of what I did:

  1. Add Doxygen Function Headers
  2. Move Logging Function to Library
  3. Change Commands to Enumerated Type
  4. Change Const Bus Pointer
  5. Pack the Structures
  6. Pass Structures as Pointers
  7. Driver Functions
  8. Test the Search
  9. Test the Parastitic Power

Doxygen Headers

I like using documentation that has been generated with Doxygen.  Specifically I like that the documentation is written “at the point of attack”.  But I have never actually used or generated it using Doxygen.  To make the documentation you need to put comments into your c-header files in the right format.  Here is an example from owb.h

In this case, David had done most of the work already and all I needed to do was copy/modify his headers in the few places where we had differences in the public interface to the library.  After that, I ran doxygen.  When I first did this I got an absolute boatload of warnings about places where I had not documented with comments.  If Hassane is reading he will say … “Really Alan didn’t write comments, imagine that”

Now I have some documentation

I will say that I wish I had a few days to really learn Doxygen as there are many many many options which I have no idea what they do.  Oh well.

Fix the Logging Function

David built the library on top of the ESP32 libraries.  This included calls to the ESP32 logging library “log.h/.c“.  All through his library he calls “ESP_LOG” like this.

When I first looked at this I decided to just do this to make the error messages go away.  This is just a trick that will use the c-preprocessor to replace the function call to “ESP32_LOGE” with NOTHING

After I sorted everything else out I went back to decide what to do.  My choices were

  1. Clone the Espressif library and “fix it”
  2. Implement the functions that David used in the OWB library
  3. Find another library

I decided to use option 3 – a logging library that I found on GitHub called “log.c” (which is a very unfortunate name when you clone it).  It is really simple and works well.  Since the Tour de France is going as I write this article I will say “chappeau rxi”.  This library is written in C99 (just normal C) and has functions which can easily replace the ESP_LOG functions.  I add it to my project with “git clone git@github.com:rxi/log.c.git”

This means that I just replace “ESP_LOGE” with “log_error”.  In reality rxi did something very nice by using a feature of the compiler to insert the file/line numbers.

This only left me with the function

Which I decided to do something cheap to solve.  The original code was:

And I replaced the two uses with:

and

I know it isn’t beautiful what I did, but it works.

Enumerated Command Type

When I examined the original source code, the one-wire commands were defined using #defines.

When I did the implementation originally I chose to make the #defines into an enumerated list.  I suppose that it doesn’t really matter.  But, by enumerating the values it lets the compiler help you in situations like a switch or a function call.

Const Bus pointer

Through out the original one wire bus library, the bus pointer is defined as const.  Like this:

But, I wanted to use the OneWireBus structure to also store some context.  By context I mean variables (which can change) but hold state for the bus.  This included the semaphore that I used to fix the delay functions.

ROM Code Structure Packed

In the original library the ROMCode is a union that allows access to individual bytes, or the actual data.

The problem is there is no guarantee that the compiler will pack the family, serial number and crc.  You should tell it to with the __PACKED macro.  I would say that I think that David got luck that there was not a bug.

C-Programming: Passing Structures as Function Arguments

In the original library David passed the rom_code structure as an argument on the stack.  But, because I started programming in the days before it was legal to pass a structure as a function argument when I did the implementation I passed a pointer.

I wrote

Which meant that he could write

but I had to write

In this case it doesn’t really matter as the structure is small.

Driver Functions

If you look at the original implementation the author has a “driver”

Which is a structure with function pointers to talk to bus.

Which meant that he did this:

In my implementation I wrote functions for those things.

I don’t really think that it helped abstract the hardware because he also did this.

Perhaps a driver with function pointers would have made the original port easier if I had started there?  But if so, it would have required more adherence to the original  architecture.

Test Search

A nice thing that came with his library was an implementation of the search feature which allows multiple devices to be attached to the bus.  To test this I added two sensors.

Then made a command in my console to run the test.

Which worked perfectly.

Parasitic Power

I would like to test the functionality of the parasitic power.  Here is a schematic from the data sheet of how it work.  But I don’t have that transistor so that will be left for another day.

What is Next?

There are several things that I should do.

  1. Fix up the libraries to use the manifest files so they are available all of the time
  2. Fix up the libraries to use the dependency scheme
  3. Test the parasitic power
  4. Test the actual DS18B20 library (the original point of this whole thing)

I have found myself in the middle of a bunch of other problems, so these things will need to happen another day.