Screenshot 2014.01.30 20.57.11As part of my 2014 challenge to become proficient at robotics, I’m building a robot. I’ll be documenting whatever I can here to share what I learn, and to start I’m looking at control systems. Since my day job is developing iOS applications, it was natural to look at ways of using my iPhone to control and monitor the robot and to do that I developed a library for communicating between iOS and ROS.

Robot Operating System (ROS) is an open source software package that works above the core operating system to provide communication and processing for the different components a robot might have. It has a very large user community and is used by a variety of robots in many different industries. It was also mentioned in the job description I was targeting.

ROS uses “nodes”, which are independent software blocks that connect to the ROS subsystem and communicate with each other. Many different nodes have been contributed by users in the community, from PID controllers to GPS signal analyzers, and one of those is ROSBridge. ROSBridge, like the name suggests, creates an interface to ROS using an industry-standard JSON format inside a websocket. This provides a very easy way for a variety of platforms to create robot controllers.

My library, called RBManager (the RB is for ROSBridge), is a wrapper for the SocketRocket websocket library in iOS. I’ve followed the standard publisher/subscriber/service call architecture to send packets compatible with the ROSBridge Protocol and make it easy to send packets and control your robot. The GitHub page provides a general overview of the structure, but I wanted to take this point to provide a more detailed example project.

To follow along, you’ll need to have a reasonable grasp of ROS concepts and know your way around Xcode and the iOS SDK. We’ll be using the standard turtlesim node. Some things I’ll skip through so it’s probably a good idea if you’ve built an iOS app before.

Prerequisites

Download RBManager on GitHub

Installation

Open Xcode and create a new empty application, with a single view controller. We’ll keep it simple and contain everything into one view. Add the RBManager files to the project, along with the SocketRocket library and import RBManager.h to the header file of your view controller.

Set up header variables and methods

How the view is laid out is up to you, but below are some of the RBManager related objects and methods that should be added to the header file. UI objects are suggestions for outputting the subscriber data.

The labels are largely self explanatory — they will be updated with the current position/velocity of the turtle simulator. The RBSubscriber and RBServiceCall objects are provided by the library and provide access to make those calls to ROSBridge.

Introduction to Messages

Messages are the core object that ROS returns from subscribers and RBManager has an RBMessage type that you override to be able to send and receive data in an object-oriented way. There are lots of messages included in ROS but you can also create your own. To see how to do that in RBManager, take a look at the header file VectorMessage.h

VectorMessage, which has the form std_msgs/Vector3 in ROS, is a basic object with properties for the keys that ROS expects. By doing it this way, it’s very easy to use Key-Value-Coding to populate a message object inside each subscriber. Some of the standard messages are included already but creating your own type is as easy as specifying the property type and name. You can even use nested messages like TwistMessage, which is what turtlesim uses and is shown below.

By calling publish, you can get back the NSDictionary representation of the message object. This method is included in the top level RBMessage object and uses KVC to get the property list.

If your message object includes additional properties that are not in the ROS message type, you should override publish directly.

Connecting and Disconnecting

RBManager behaves as a singleton, by referencing [RBManager defaultManager]. This prevents multiple instances from being created. To connect to ROSBridge, it’s as easy as calling

where ws://robot.local:9090 is the IP of your robot. The default port of ROSBridge is 9090, but that can be changed. Disconnecting is just as simple, by calling

Adding Publishers and Subscribers

Handling the publishing process is RBPublisher. After this object is added to the manager, it is automatically advertised to ROS and you can push messages through. To create the object, in the case of turtlesim, use the following method

In this case, the topic is /turtle1/cmd_vel and the message type is geometry_msgs/Twist, which are both expected by ROS. The label property is just a handy way of differentiating multiple publishers, if you have more than one created. Put this declaration inside the view controller init method and they will be automatically advertised when you connect the socket. If you want to manually un/advertise the publisher afterwards, you would use these methods

Subscribers behave in a similar fashion. They are added to the manager and subscribed automatically when the socket is opened. The primary difference is that subscribers also take a callback to receive messages that ROS publishes. In the case of turtlesim, that would look like this

Here turtlePoseUpdate: is the method in the view controller that will receive the message update, and it only has one parameter. The ROS topic of /turtle1/pose is generated by turtlesim and it provides a message of type PoseMessage. By providing the class type, RBManager can create and populate the correct message. As seen by the ROSBridge specification, the throttleRate is the interval at which ROS will send a message, in milliseconds. This is to prevent overloading the receiver.

Here is what a valid init and subscriber method would look like inside the view controller

Sending Messages

Using an iPhone with ROSBridge is advantageous because the iPhone has an abundance of sensors that are great for controlling robots. That means sending and receiving messages are a very important component. Doing that with RBManager is fairly straightforward. After connecting and advertising a publisher, create a new message object and submit it.

In this case, xAngle and zAngle are calculated from the accelerometer. If everything is connected after this, you’ll start to see the turtle move.

Using Service Calls

Service calls are important components for monitoring and updating robot configurations. In the case of turtlesim, this includes changing the background, changing the colour of the pen and killing and spawning turtles. You can think of service calls like publishing a message without content, although some calls do return data. RBManager handles both cases, but doesn’t require adding the object to the queue.

The calls are not sent immediately because this allows you to assign additional parameters, like the id. The first example shows sending a call without any parameters. The selector is the callback when the response is returned. When there is no data expected back, the most useful thing to get from the response is a success true/false.

Related to service calls is the process for assigning parameters. These are essentially wrapped service calls that call directly to the ROS API. In turtlesim, this is used to change the background colour

Although the actual service call uses arrays, it’s unfortunately not possible to include more than one parameter at a time so you have to make 3 separate calls.

That is a detailed, but still pretty open example about integrating RBManager into an iOS application. With the touchscreen and motion sensors, it’s pretty easy to now direct your robot to follow a path on the map or move in relation to the accelerometer position. Hopefully this library can make developing and building robots more efficient so please show me what you build with it! If you find an issue, create a ticket on GitHub or comment below and I’ll look into it. I’ll be continuing to develop it over time, particularly when my robot project actually makes use of it.

{ 0 comments }

Arduino, PowerSwitch Tail 2, humidifierMechatronics is described as the intersection between mechanical, electrical and computer engineering, and it covers just about anything that uses electronic signals to act on mechanical systems. It’s what I went to school for, and it’s where my hobby interests lie. The Arduino is a fantastic example of how people with limited experience can jump right into mechatronics projects. I’ve been tinkering with them for a few years, and decided to put the components I had to good use by taking a timid step to home automation.

Indoor humidity can affect the comfort level of a home pretty dramatically. Since warm air can hold far more moisture than cold air, the humidity inside during the winter falls dramatically. This drop can cause an increase in static electricity, sickness and dry, itchy skin. Too dry and a home can just feel downright uncomfortable. Too much humidity when the outside temperature is low can also cause condensation on the windows and mould growth. Some humidifiers have a built in control system to maintain the proper level of humidity, but what if yours doesn’t?

By combining an Arduino with a basic humidity sensor and relay, you can trigger your simple humidifier to only come on when needed.

Bill of Materials

With these pieces combined together, you can find the indoor temperature and humidity, and adjust the humidifier’s set point manually to achieve the proper moisture level.

Assembly

Complete breadboardHere are some links about connecting the different components that make up the system.

Additionally I have a few bonus status LEDs for displaying when the correct humidity has been reached (although you’ll be able to tell from whether the humidifier is on or off). The great part about the Arduino community is that most of the major components have libraries dedicated to their functions, so you can spend less time figuring out how the hardware works and more time thinking of projects.

Control System

The control system is the set of governing equations and parameters that determine what behaviour the system’s output should have. In this case, it takes in the current level of moisture in the air and tells the relay to switch the humidifier on or off. For that reason, it’s a type of control system called “closed-loop”, because turning the humidifier on will increase the sensor value and trigger it off.

There are many other different types of control systems but we’re fortunate that the main type in use here is called an “on-off controller” for its inability to adjust output values. Like a furnace, the humidifier can be either on or off, with the time in each state determining the magnitude of change. Compared to a PID controller, which uses error correction to maintain a system, the on-off controller is far simpler.

The complete source code is available to download below, but I’ll go through some of the important parts here.

Temperature and humidity outputEven in a relatively simple system such as this, it’s important to follow proper coding patterns. This means using the Model-View-Controller paradigm to retrieve sensor data and output to the screen and relay. In even simpler terms, it means storing the inputs as variables and refreshing the screen rapidly with those variables. For that, it’s a good idea to use something like a Timer class to handle running specific methods at an interval without blocking the main program.

With the button, I’m able to toggle between two states: normal and setting. Doing that is easy with enumerations.

Each time the button is clicked, the state of systemMode is changed, and the display is updated accordingly.

Toggling display modesThe ModeSetting value is where a new setpoint for the control system is entered. When TARGET is displayed on screen, the encoder LED flashes (again with another timer) and turning the encoder updates the value.

While the above links show a clear way of entering the new encoder value, here’s my function.

You only want to update the target value if the current mode is Setting and the new encoder value is different from the previous.

Whenever the system mode returns to normal, the controller checks if the current value is where it needs to be and updates the relay accordingly. However, it’s not as simple as turning the relay on when humidity is below the target and turning it off when it goes above. If that was the case, there would be far too much cycling. That means as the error approaches 0 (humidity reaches the target), the actual value could repeatedly go across the threshold and cause the humidifier to cycle on and off quickly. I’ve set the refresh rate to be 1 minute, but even that would be annoying if it cycled that quickly. To fix the problem, we need to introduce a control system property of hysteresis, which in simplified terms means making the humidifier stay on until it passes the target by a few percent, and not turning on until it’s a few points below the target. This way it cannot rapidly switch between the on and off states. In code, that might look something like this.

Here, the variable correct is the value of whether the system is currently at the desired level, and hysteresis is the percent of padding (2% here).

What this block is essentially saying, then, is “if the humidity is currently above the desired value, don’t turn on again until the humidity is below target – 2″ or “if the humidity is currently below the desired value, stay on until the humidity rises to target + 2″. In this way, the system won’t turn on and off in quick succession.

Connect the PowerSwitch relay pins to ground and an Arduino 5V output, and set the state of the pin according to correct. Then sit back and listen to the satisfying click of the relay as computers do your job for you.

Controller and humidifier together

What’s next?

Since this current version requires you to set the target point on the humidifier manually, it’d be nice to make that automatic, too. But how? The problem is that indoor humidity is linked to outside temperature, as I mentioned above, so that means you need to find out the local temperature and adjust the humidity accordingly. That can be done any number of ways, like adding a WiFi or ethernet shield to the Arduino.

This is something I’m planning on doing, but I’m going a slightly different route so that I can build on it for more advanced home automation. By building an Xbee network, I can make nodes that act as sensors or outputs and connect them all to a central computer. Since I already have Ubuntu server, that part is taken care of. I can log data to the server and have it request local weather and tell this Arduino whether the humidifier should be on or off.

But the fun wouldn’t even need to stop there. By designing the network right, suddenly you can add other components to do things like turn lights or appliances on or off or alert you when a window is left open at night. Where will you take it?

{ 10 comments }

Since starting this blog, some of my post popular posts have been about the WordPress plugins I’ve written. Built as I started learning about PHP, they’ve received hundreds of comments and often generate a spike of pageviews when new versions become available. The most practical of these plugins, Mass Page Maker, has seen multiple iterations as I learned more about the WordPress API. Many people were very happy about the ability to import data using a CSV file, but conversely that generated lots of comments about having difficulty getting the format right.

After many months of struggling to improve it, I’ve buckled down enough to offer a new version, called Mass Page Maker Pro that is now available for sale at $10 (Limited time only!).

There is a reason that I’m charging for this version. After I neglected the plugin for long enough, it was dropped from the WordPress plugin repository. When I approached the staff about getting it reinstated, I was told that the plugin could be abused and cause someone to import too many pages into a WP installation. This is true, but like most useful tools, there will always be a small subset of users who abuse its capabilities. After having an email conversation with one of the plugin users, I made the decision to offer a free and Pro version of the plugin, to hopefully earn a little money for the time I’ve invested in developing it. The free version will not allow CSV importing, and will be limited to 10 pages at a time, so hopefully those restrictions will allow it to be listed in again in the repository so that existing users can receive the update and learn about the situation.

Now that that’s out of the way, let me explain some of the new features in more detail.

duplicate content category

Customized CSV Format

As mentioned, a big problem with the original version was the stiff nature of the CSV format, making it difficult to match the required format the plugin is expecting. I decided to solve this by offering both the default format and allow a totally custom format to leaves out data that is not important. To create a custom format, choose “Custom” from the menu and click the Add Column button. From there, it’s easy to define the order of the columns you want to use. The nice part is that the plugin will merge your data against the default format, meaning you can concentrate on your data.

For example, if you define only a post title and post content column, properties like post type (post), comment status (open) and post date (current date) are added automatically. Drag and drop the columns as required. I think this will be a very well used feature.

CSV form screenshot

Improved Web UI

Since starting this plugin, I’ve learned a lot more about Javascript and jQuery technology and have incorporated a lot of that in this new version. It uses the jQuery UI accordion plugin to display either the CSV input or web form and makes it easy to add tags and custom meta values.

Duplicate and update existing posts with CSV data

Through some user feedback, I added a new column to the CSV format that allows you to update existing pages or duplicate them and overwrite the content. Choose the respective column in the dropdown, and supply either a post title or post ID and the plugin will overwrite that data with what you supply. For example, in the first photo above, that is the correct layout for duplicating pages, overwriting the post content and adding new categories. Those three values should be the first 3 columns in the CSV text.

I’m hoping that this version of the plugin contains all of the properties users might want when importing posts. I spent lots of time testing the plugin, but of course if you run into an issue, use one of these contact methods. There are also example CSV files on that page available for downloading. Please consider purchasing the plugin if you’ve been helped at all by the original version, and I’ll continue to offer new features and bugfixes.

{ 2 comments }

ASUS P8Z77-M Pro MotherboardRecently I decided to take some leftover computer parts and add them to a few new ones to create a small computer I can use for an upcoming projection project and also use later as a home theatre PC. I went to the local computer store and picked out the required items: Z77 motherboard, graphics card and case. It took part of a Saturday afternoon, and by the evening I had Windows 7 booted.

That’s where I ran into trouble.

Intel i5-3330 CPU and thermal pasteThere’s a delicate balance between hardware and software in a computer, and sometimes the two sides fight each other. That’s what started happening to me. After installing the motherboard drivers from the included DVD, I started getting freezes a few minutes after startup that would last anywhere from 30 seconds to 3 minutes. They would repeat again and again, and it was almost impossible to predict. After updating some software, and testing different applications, I had two breakthroughs: first was a blue screen of death that returned an anodlfx.sys error and the second was a taskbar notification that the graphics driver had halted but recovered again. Armed with those data points, I combed Google for information, but came up largely empty. So to find a solution, I began troubleshooting individual components and systems, which are documented below.

Remove/reseat RAM

Computer memory can sometimes cause random software behaviour under certain conditions. To try to pinpoint if any of the chips you’re using have problems, install only one DIMM at a time and boot the computer to check for an error. You have to make sure the slot used is the one the motherboard needs when only one chip is present. I swapped out the two chips I was using at the time, but the problem continued. Installing them both again, I ran MemTest86+ but that came back clean, so memory was not the problem.

Remove the dedicated graphics card

Since the popup warning seemed to indicate a graphics problem, I tried removing the dedicated graphics card. The Z77 chipset motherboard I’m using has support for integrated graphics, should the CPU support them, so I was running Intel HD2500 from the motherboard itself. Unfortunately the problem persisted, so yet again I had to go down a different road.

Change the hard drive

A problematic main storage unit can display problems in unique ways, so one of the things to try is to use a new drive. Originally I was using a 64GB OCZ Vertex 4 SSD, so I substituted in a spare 2.5″ HDD I had in another enclosure. After reinstalling Windows, along with the different hardware drivers, I continued to get the errors, so obviously that couldn’t be it.

Change out the motherboard

The original motherboard I used was an open box, so after going through each of the steps above, I decided that the only logical problem was the one part that had stayed the same throughout: the motherboard. Be warned this is not for the faint of heart, as it involves removing and collecting nearly every piece loaded into the case already. Nevertheless, I put everything into the box and replaced it with a brand new one. Reinstalling it into the case and booting up the same installation of Windows (it doesn’t care if the hardware model doesn’t change), I was rather frustrated to see that same graphics warning after a few minutes of use.

Use different drivers

At that point I decided to change things up completely and reinstall Windows, along with all of the drivers. This time, however, I went directly to the different manufacturer’s websites and downloaded the files directly. Incredibly, after multiple reboots from the installations, I didn’t get a freeze or blue screen. Somehow changing up the driver versions had aligned everything properly and the parts were playing nice together. Since the main errors were about the graphics driver failing, it’s not particularly surprising that changing up the software might fix the issues.

IMG_0824After getting gigabytes of software updates, the system continues to operate properly and I’m pretty happy with it. At this point most of the challenges I’ve experienced with computer setup deal with driver software; this computer POSTed every time. Hopefully by documenting my challenges here, it will help me in the future, and also anyone else who might have a similar problem.

{ 0 comments }

Electronic tinkering and building have become a bigger hobby for me as I finished my university degree. The Arduino development platform is quite a remarkable system, and the online community of users is growing every day. The problem with many of the projects that I do is that many systems require more power than the 50mA or so the Arduino can provide. You could use different AC-DC wall adapters, but that becomes unwieldy.

The DIY solution, as many Arduino users have discovered, is to repurpose a used computer power supply unit for cheap, regulated 3.3V, 5V and 12V DC power. I decided to build my own based on some other examples, while adding things that I need for my projects. I documented the procedure in an Instructable but thought I would expand on the design and build process here a little more.

Design Requirements

I did lots of planning before cutting any sheet metal because I wanted to follow the engineering procedure. The major requirement for this is to decide what features the final system needs to be successful. I chose the following:

  1. Ability to remove the 24 pin ATX cable to power other projects
  2. Access to all available PSU voltages (3.3V, 5V, 12V)
  3. Different connectors to make powering different components easy
  4. Fuses to prevent powered systems from breaking
  5. Keep some external cables for future expansion
  6. Connectors on the top of the PSU

Bill of Materials

With the requirements in hand, I started browsing for and collecting components. One of the things I noticed right away is that any power supply with a top mounted fan would not useable. This means that my system is limited to about 300W or less, which for desktop projects is completely fine. Older, cheaper and lower power units were the first place I looked, but I quickly discovered another requirement: a 24 pin ATX connector instead of the older 20 pin standard. This limitation meant that I had to build a new one from Newegg instead of on the used market. The cost worked out to be the same.

After waiting a few weeks for delivery, the following parts were on my table:

The ATX breakout board handles the operation of the PSU by properly shorting the on/off wire and providing indicator LEDs. It also breaks out each of the voltages on the cable to a useful screw terminal pad. If you choose to use a different method, turning the power supply on is as easy as shorting the green wire with a common ground. The other parts I found on eBay or various electronics retailers on the internet (try Adafruit, RobotShop, Sparkfun or OddWires).

Design Process

My first step was to measure and replicate each part as accurately as possible using a 3D CAD package. If you’re looking to do something similar, take a look at Solidworks, Autodesk Inventor, SketchUp or Pro/Engineer and decide which to learn. They all perform the same functions, although SketchUp is less about dimensions and more about sculpting 3D objects.

With the components in my system, I was able to lay out all of the holes on the PSU shell to confirm space. I was able to fit 5 2.1mm DC barrel jack connectors, the power distribution block and ATX board on the top surface, with the fuses moved to the side. The software made it very easy to print templates for the hole locations on each surface.

One of the things I needed to look out for was preventing interference between the barrel jacks on top and the internal heat sinks. That meant modelling additional components inside the shell, but doing that extra step prevented numerous hangups further down the process.

As a quick note, please keep in mind that this is a record of my procedure and by no means a complete step-by-step instruction manual for hacking power supplies. These units produce an evil amount of electricity and can be dangerous when misused. Remember that before breaking open the tool box and realize that it’s entirely your choice to void the warranty.

Drilling and installing the components

Cutting into the sheet metal container can’t be done by hand, of course, so here’s a list of tools I used:

  • Power drill
  • Assorted drill bits
  • Step drill (with 3/16″, 3/8″ and 1/2″ sizes)
  • Round file
  • Dremel deburring tool
  • Assorted screw drivers
  • Wire stripper
  • Diagonal cutters
  • Multimeter

If or when I build another unit, I’ll add a center punch to that list in order to accurately dent the material to start drilling. Without it, I needed a finishing nail and hammer, which reduced accuracy somewhat.

Start by ignoring the warranty labels and cracking open the PSU shell.

Inside you’ll find a semi-organized collection of wires, circuit boards, capacitors, MOSFETs and heat sinks.

Now is a good time to tape the hole template paper to the shell, if you’ve prepared one. For the most part the holes aren’t for accuracy relative to the shell, but more for proper spacing between the individual holes.

Drill the 1/2″ holes for the fuses with the step drill. The thin sheet metal will produce burrs on the underside that you’ll need to clean up for the fuse holder to sit flat.

Do the same for the 3/8″ holes for the DC barrel jacks. Both of those components can then be loaded into their respective locations because they’ll need to be installed in order to solder the wires.

Wiring and soldering the connections

Routing the cables from the bottom PCB to the fuses and on to the barrel jacks was somewhat of a challenge because of the arrangement of the heat sinks and bottom components. I cut the external connectors and passed the wires inside to test for length. The overall path for the positive cable of each voltage would be PCB – Fuse – barrel jack and the associated ground wire went directly to the barrel jack. Be careful not to pull too hard on the PCB because tracing the wire back to the soldering pad can be a real pain.

Generally the fuse to barrel jack wire was soldered first, because it was the easiest to trim and arrange. The fuse holder only has two pads, but the barrel jack has three, which means before soldering anything you’ll have to learn the pinout configuration. The most common barrel pinout is center positive, so that’s what I used. Finding which pad was which meant connecting a wire to the jack and checking continuity with a multimeter. Not difficult by any means, but it can be time consuming.

After reinstalling the shell, I soldered on the screw terminals to the ATX board and connected the 24 ATX cable. The brass standoffs are used on the ATX board to raise it from the metal shell, so those were installed next.

Testing the entire unit was a simple matter of connecting the multimeter to the screw terminals and barrel jacks.

After testing, how you use the power supply is completely up to you. The easiest way to incorporate the power is to feed lines from the screw terminals to a branch on a solderless breadboard. Saving the cut off internal wires is a great way to wire them together.

This was a great project for me to test design principles and following through with a project from start to finish. It now opens the doors to building systems with motors, thermoelectric coolers or any number of other sensors.

{ 0 comments }