Building an Arduino powered environment monitor and iOS app

Finished product
My apartment uses baseboard heaters and anyone who’s paid for hydro can tell you, they’re pretty inefficient. I wanted to collect some information about the inside conditions of my apartment so that I could better understand when and how to turn the heaters on. Normally a simple thermostat would do, or even a Nest, but my equipment is so basic, there is no read out available.

So I built my own. Here’s what I did.

In high level terms, I have an Arduino UNO using a WiFi shield and custom PCB connected to a DHT22 temperature and humidity sensor and photocell. This information is sent to data.sparkfun.com and is displayed in snapshot, table and graph form on my iPhone.

Setting up the Arduino

The components with the Arduino are all fairly well known, but I had not made anything with them together. Here are the parts and links to where to get them

I put them together on a breadboard and build the code. I can provide code if interested, but essentially I assembled individual modules in order to upload the data every 5 minutes. As far as the program goes, it’s laid out like this

  1. Include all libraries — this uses DHT, Timer, Wifi, SPI WifiClient, WifiServer and medianFilter
  2. Define base variables — Wifi shield configuration, website, pins, etc
  3. Create objects — Timer, client, server, filters
  4. run setup() — set pin modes, connect to Wifi and set the timers
  5. loop() only updates the timer
  6. Every 30 seconds all sensors are read and added to a filter
  7. Every 5 minutes the filtered data is sent to data.sparkfun.com

Creating a circuit

schematicA breadboard is fun for prototyping, but it wouldn’t look so good on a shelf, so I took the opportunity to test out a new PCB manufacturing website by building my own circuit. The pinouts of all components is fairly easily available online, or better yet, in EAGLE itself. The board doesn’t have many pieces, just some 0.1″ header holes, but the tricky bit is making sure that there are no pin conflicts with the Wifi shield.

Moving to a PCB

environmental_board
EAGLE provides a nice way to import a schematic to a board, and since I started with an Adafruit shield piece, there was a nice outline ready for me. At that point it was a matter of making sure that all traces have clean paths and there are 5V and GND planes.

1-IMG_7920
4-IMG_7930
3-IMG_7924
I tried a PCB service previously called OSHPark.com but was unhappy with the cost and lead time required. A friend pointed me towards dirtypcbs.com and that turned out to be a great choice. The name is basically entirely what you get: printed circuit boards at affordable prices, with a very reasonable 1 week lead time. I was also impressed with the shipping from China, as it was no more than an additional week with DHL. That’s 2 weeks for 10 custom boards.

Displaying it all on a phone

The data is sent to data.sparkfun.com, which provides a nice free way to store key-value data (eg. temperature=25,humidity=38, etc) and a way to retrieve it. During the day I work for a mobile software company, so building something to retrieve the data was fairly straightforward. I ended up with a way to view different properties in the latest data, table and graph form.
IMG_1565
This is the home page where the latest data point is displayed front and centre, along with the time it was retrieved. The time is relative, so a timer runs every second to indicate how old it is, but clicking the label shows the actual timestamp. Below that is some related information that might be useful: the 24 hour high value, 24 hour low value, and the current outside temperature according to forecast.io.
IMG_1569
Additionally the menu button at the top left presents a slide out “hamburger menu” that can switch between the different properties collected.
IMG_1570
The middle tab shows the last hour of data in table format and as you scroll downward, will load the next block from Core Data. In order to keep the actual internet request simple, the app retrieves the timestamp of the most recent datapoint and only requests points from Sparkfun that are after that. All points are stored in Core Data and loaded on demand.
IMG_1567
Finally the right most tab shows a graph of whatever property is displayed at the time, with options for last 4 hours, last day or last 4 days. At first I had last hour but I realized the data I was collecting wasn’t really changing in that time frame so it was largely useless.

For the most part the graphs are consistent, with my heater keeping the temperature at about 19-20C through the day. The light graph is very interesting because it clearly shows when the light goes off and how sunlight filters through the curtains in the morning.

Next plans

There’s one thing I’d change about the PCB design, and that would be to replace the fixed photo cell resistor with a potentiometer to adjust the threshold. Right now I’m using a 16k ohm (I think, something about 10k) and that produces a nice range between full bright and darkness, but it would be good to adjust as required.

With the data collected, I’d like to now make use of it somehow. You might notice how the board has 4 pins showing “relay” on it, which is so that I can connect an AC relay and control my lights or humidifier. Ultimately I’d like to work in some geocoding to my app so that I never come home to a dark apartment and have my light be smarter so that it doesn’t turn off while I’m still at my desk.

Posted in Arduino, iPhone Tagged with: , , ,

RBManager: an iOS library for Robot Operating System and ROSBridge

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.

Posted in Robot Operating System Tagged with: , , ,

Automate a basic humidifier with an Arduino, relay and simple sensors

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?

Posted in Arduino Tagged with: , , , ,

Introducing the Mass Page Maker Pro WordPress plugin

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.

Posted in Wordpress Tagged with: ,

Troubleshooting a custom computer build

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.

Posted in Windows

Twitter: wesgood