Raspberry Pi garage door opener: Part 3

I finally submitted my order for prototype PCBs for my Raspberry Pi ‘HAT’ that I’ll be using for my Raspberry Pi garage door opener. In the end I wound up with this:

  • 2 relays, used to activate the doors. These are driven by relay drivers.
  • 2 rotary encoder inputs (A and B for 2 encoders), to allow my FreeBSD rotary encoder driver to determine the position of the doors.
  • 2 closed door switch inputs. I’m using Honeywell magnetic switches here.
  • 2 pushbutton inputs. I want to be able to activate the garage doors when standing in front of my garage door unit (inside the garage near the doors).
  • 4 LED outputs. I’m using a tricolor panel-mount LED indicator for each door, which will show green when the door is closed, flashing yellow when the door is moving, steady yellow when the door is open but not moving, and will flash red whenever the door is activated.

I’m using anti-vandal pushbuttons for the door activation buttons. Not because I need the anti-vandal feature, but because they are flat and not easy to push accidentally. The ones I’m using have blue ring illumination.

I’m using Apem Q-Series indicator LEDs.

The enclosure I’m using at the moment is a Hammond translucent blue polycarbonate box. Probably larger then I need, but it’ll let me house a POE splitter to power the whole thing via power over ethernet.

I still need to finish the mechanical stuff… mainly the mounting and connection of the rotary encoders. I have a drawing for part of it for FrontPanelExpress, but I don’t really need to go that route for myself. The main issue I’m still debating is whether I can come up with something cheaper and lighter than Lovejoy couplings to connect them to the garage doors.

In any event, I believe I have fully functioning backend software and the web interface works fine. Everything is encrypted, and authentication is required to activate the doors.

Raspberry Pi garage door opener: part 2

I have a fully functioning software suite now for my garage door opener. I have been using a small simulator program on the Raspberry Pi to pull the pins up and down (using the pullup and pulldown resistors). Tonight I plugged in one of the actual rotary encoders, and it works fine. And now that I think about it, I don’t really need the optocouplers on the inputs, since I’m using encoders with NPN open collector outputs. All I need to do is enable the pull-up resistors. This is also true for the garage door closed switches. Hence I am going to draw up a second board with a lot fewer components. The component cost wasn’t significant for the board I have now, but it’ll save on my effort to populate the board. By dropping the optocouplers, I will eliminate 15 components. And technically I could probably eliminate the filtering capacitors too since the encoder cable is shielded. That would eliminate 4 more components.

I hate the amount of board space required for the relays, but I need them. I considered using MOSFETs or Darlingtons, but I decided it was just a bad idea to tie the Raspberry Pi ground to my garage door opener’s ground pin. It’d be a recipe for ground loop disasters. The relays keep the Raspberry Pi isolated. I am using relay drivers to drive the relays, which just saves on component count and board space.

I have a decent web interface now, which runs on my web server and communicates with the Raspberry Pi (encrypted). I have yet to implement the separate up/down logic, but since the web interface shows the movement of the door, it’s not strictly necessary. Door activation works, and I can see whether the door is opening or closing.

My code on the Raspberry Pi will learn the door travel from a full open/close cycle, so the graphic in the web interface is very representative of the amount the door is open.

Site Health page now shows UPS status and history

I am now collecting UPS status data from my UPS, and there is a new plot on the Site Health page that displays it. I still need to make these plots work more like those on the Site Traffic page, but having the UPS data for battery charge level, UPS load, expected runtime on battery and power consumption is useful to me. I currently have 3 computers plus some other gear running from one UPS, but soon will move a few things to a second UPS to increase my expected on-battery runtime a bit.

Measuring TCP round-trip times, part 5: first round of clean-ups

I added the ability to toggle a chart’s y-axis scale between linear and logarithmic. This has been deployed on the Site Traffic page.

Code cleanup… when I added the round-trip time plot, I wound up creating a lot of code that is largely a duplicate of code I had for the traffic plot. Obviously there are differences in the data and the presentation, but much of it is similar or the same. Tonight I started looking at trickling common functionality into base classes, functions and possibly a template or two.

I started with the obvious: there’s little sense in having a lot of duplicate code for the basics of the charts. While both instances were of type Wt::Chart::WCartesianChart, I had separate code to set things like the chart palette, handle a click on the chart widget, etc. I’ve moved the common functionality into my own chart class. It’s likely I’ll later use this class on my Site Health page.

Measuring TCP round-trip times, part 4: plotting the data

I added a new plot to the Site Traffic page. This is just another Wt widget in my existing Wt application that displays the traffic chart. Since Wt does not have a box plot, I’m displaying the data as a simple point/line chart. There’s a data series for each of the minimum, 25th percentile, median, 75th percentile and 95th percentile. These are global round-trip time measurements across all hosts that accessed my web site. In a very rough sense, they represent the network distance of the clients of my web site. It’s worth noting that the minimum line typically represents my own traffic, since my workstation shares an ethernet connection with my web server.

Clicking on the chart will display the values (in a table below the chart) for the time that was clicked. I added the same function to the traffic chart while I was in the code. I also started playing with mouse drag tracking so I can later add zooming.

Measuring TCP round-trip times, part 3: data storage classes

I’ve completed the design and initial implementation of some C++ classes for storage of TCP round trip data. These classes are simple, especially since I’m leveraging functionality from the Dwm::IO namespace in my libDwm library.

The Dwm::WWW::TCPRoundTrips class is used to encapsulate a std::vector of round trip times. Each round trip time is represented by a Dwm::TimeValue (class from libDwm). I don’t really care about the order of the entries in the vector, since a higher-level container holds the time interval in which the measurements were taken. Since I don’t care about the order of entries in the vector, I can use mutating algorithms on the vector when desired.

The Dwm::WWW::TCPHostRoundTrips class contains a std::map of the aforementioned Dwm::WWW::TCPRoundTrips objects, keyed by the remote host IP address (represented by Dwm::Ipv4Address from libDwm). An instance of this class is used to store all round trip data during a given interval. This class also contains a Dwm::TimeInterval (from my libDwm library) representing the measurement interval in which the round trip times were collected.

both of these classes have OrderStats() members which will fetch order statistics from the encapsulated data. I’m hoping to develop a box plot class for Wt in order to display the order statistics.

Measuring TCP round-trip times, part 2: the throwaway

I previously posted about measuring TCP round-trip times from my web server to its clients. Last night I quickly added code to my existing site traffic monitor to perform this task, as the experimental throwaway to validate my design idea. I have not yet designed the data store, only the collection of round-trip times. To see what it’s doing, I syslog the rtt measurements. It appears to be working fine. Here’s some data from Google’s crawlers prowling my site:


May 2 21:37:23 www sitetrafficd[2318]: [I] 66.249.66.43:45825 rtt 123.2 ms
May 2 21:38:49 www sitetrafficd[2318]: [I] 66.249.66.57:38926 rtt 123.6 ms
May 2 21:38:49 www sitetrafficd[2318]: [I] 66.249.66.43:38085 rtt 123.5 ms
May 2 21:40:16 www sitetrafficd[2318]: [I] 66.249.66.143:39725 rtt 137.8 ms
May 2 21:40:16 www sitetrafficd[2318]: [I] 66.249.66.143:37657 rtt 126.2 ms
May 2 21:41:25 www sitetrafficd[2318]: [I] 66.249.66.204:47961 rtt 160.9 ms
May 2 21:41:25 www sitetrafficd[2318]: [I] 66.249.66.143:45623 rtt 121.1 ms
May 2 21:41:47 www sitetrafficd[2318]: [I] 66.249.66.60:36603 rtt 142 ms
May 2 21:42:15 www sitetrafficd[2318]: [I] 66.249.66.204:48875 rtt 123.6 ms
May 2 21:43:15 www sitetrafficd[2318]: [I] 66.249.66.43:56275 rtt 125.8 ms
May 2 21:44:42 www sitetrafficd[2318]: [I] 66.249.66.57:49966 rtt 124.1 ms
May 2 21:44:42 www sitetrafficd[2318]: [I] 66.249.66.204:53209 rtt 122.9 ms
May 2 21:45:59 www sitetrafficd[2318]: [I] 66.249.66.238:46595 rtt 123.8 ms
May 2 21:47:27 www sitetrafficd[2318]: [I] 66.249.66.60:60241 rtt 142.2 ms

I believe I can call the raw measurement design valid. It’s a bonus that it was not difficult to add to my existing data collection application. It’s another bonus that the data collection remains fairly lightweight in user space. My collection process has a resident set size just over 4M, and that’s on a 64-bit machine. My round-trip time measurement resolution is microseconds, and I’m using the timestamps from pcap to reduce scheduler-induced variance. Since I’m not using any special kernel facilities directly, this code should port fairly easily to OS X and Linux.

May 3, 2012
I added the ability to track SYN to SYN ACK round-trip time, so I can run data collection on my desktop or gateway and characterize connections where I’m acting as the TCP client.

sitehealth repaired

I finally got around to hunting down and squashing a bug on my Site Health page. It was one of those bugs that wasn’t easy to reproduce, but I happened to catch it occurring repeatedly on Sunday.

One of the benefits of having C++ code using Wt for this kind of page: I can attach to a running process with the debugger (gdb) and debug a multithreaded process live. The problem was the allocation of an extra data series in the filesystem plot, without assigning header data to that data series. The header data is needed when rendering the legend. If it’s not there… one of the threads either causes a seg fault or hangs.

I fixed the problem and the Site Health page is working again. I will need to update Randy’s server when he is connected at his new location.

Site Calendar work done, for now

I’m done tweaking the functional aspects of the Site Content Calendar for now. It functions in webkit browsers (Safari, et. al.), Mozilla browsers (Firefox and friends) and Opera.

I like it, it’s useful to me. It will probably be largely useless to visitors, but I enjoyed creating it.

is not completely unlike Qt, and that’s a good thing. It’s nice to be able to write sane C++ code for web development.