Shure SE215 Headphones

A few months ago, I began to wonder if I’d outgrown my Sennheiser CX200 earbuds. They were great when I purchased them a few years ago for around $20, but after going to the HD448 headphones, the CX200s simply didn’t get it done for me at work. Considering I was listening to mostly free Internet radio, I wasn’t super concerned, but I began browsing for a new pair of earphones. I eventually settled on the Shure SE215s, which were $90 on Amazon but had great reviews. I eagerly awaited their arrival.

I went to Maryland last week and they were waiting for me when I returned. The first thing I noticed was how well they were made. One of the “features” that concerned me the most was that each earpiece is removable from the cable, so you can replace the cable if it goes bad and the headphones don’t. I was worried that the cable wouldn’t stay in well, but it’s in so tightly that I haven’t been able to take it out (not that I have pulled very hard). The cable is very thick and the connector feels solid. Combined with the carrying case, the SE215s seem like they will stand up to teenage travelling abuse.

Shure SE215

My new earphones in their case.

The next impressive feature the SE215s have to offer is the huge number of earpiece options. There are three different sizes and each comes in a foam option and rubber option. The medium-sized foam pieces that are on by default seem to fit just fine, but I haven’t been able to remove them (for two reasons – I haven’t really had a reason to and the foam is rather aggravating - more on this later) to try others. The instructions say to wear the earbuds like you would ear plugs; this leads to some discomfort after long listening sessions. I wore these headphones for around 7 hours at work yesterday but I had to take breaks on occasion.

I mentioned that foam earpieces are aggravating. They are very nice and Shure isn’t kidding when they say to wear the SE215s like ear plugs – you can’t hear very much with them in and music off, and with music on, you can’t hear anything. I’m listening to music with them as I write, and I can’t hear my keystrokes, finger snapping right next to my ear, pounding on my desk, or hitting my phone against its dock. It’s scary – I don’t recommend these for dark, rainy nights. If you have a noisy office, these will be awesome. They don’t leak much sound, either. However, the foam earpieces also form to fit your ear canal. This is awesome when you put them in right, but if you mess up putting them in, you have to wait a few minutes for them to re-inflate before you can get good sound and have them stay in. Trying to take them off is also a death sentence for listening to music with them for a while – you have to smoosh the foam. It’s annoying but as I get better at using these earphones, I’m sure it will become a non-issue. Shure says you can freeze the headphones for 5-10 minutes to make the piece easier to take off.

The sound is so good, however, that the people around you probably wish they did leak some. As a teenager, I enjoy good bass response, and these deliver. I’m no audiophile, but for $90 I think these are amazing. All the other reviews of these that I’ve read seem to agree. Treble is also very good, as are the mids. Everything sounds very crisp – even with my iPhone set on its bass booster equalizer setting, nothing becomes muddy. I also enjoy how much punch the SE215s have on drum kicks. I listen to a huge variety of music from rock to pop to trance and these headphones do a great job on each.

Although I think these headphones were worth every penny and I plan on keeping them for a long time, I do have a few complaints:

  • As I mentioned before, comfort isn’t great.
  • Noise blocking is scary good. This is either a good thing or a bad thing depending on where you are, but I worry that I won’t be able to hear my phone ring.
  • Having to justify spending $90 on headphones to my friends. Yes, they are cheaper and better than Beats (bass can be equalized up to close to what they can produce which is great for my teenager side and the presence of the other two levels is good for my Sennheiser side) but they say SHURE in big letters on the side. How many non-audiophiles have heard of Shure? I hadn’t until I stumbled upon these in an Amazon search.
  • They are hardly stylish. They have a clear case that allows you to see the headphone internals which is kind of neat but they are very large and you have to wear them with the cord wrapped around the back of your ear. It doesn’t look as ridiculous as you might think but my friends are going to make fun of me:
    Shure SE215 In-ear Fit
  • Although the cord is very sturdy, it is a little bit stiff at the moment. I hope this works itself out but for now, I can’t get a very good ear wrap and the cord touches my neck. I think part of the problem with the ear wrap is that the ends of the cords are shrinkwrapped. This adds to quality but I suppose it also adds to break-in time.

Overall, I am extremely pleased. These headphones offer excellent audio quality at a reasonable price. Buy these, put on some high-bitrate music, and enjoy. 9/10.

Cloning ThinkGeek’s Annoy-a-tron with a BASIC Stamp Homework Board

I’m working on a course at work right now that aims to get people (high school students in particular) interested in electronics. The project uses a BASIC Stamp homework board for projects, and one of the ideas I had for a project was a copy of ThinkGeek’s Annoy-a-tron. The kit I bought came with a piezo buzzer and PBASIC (the language used to program the Stamp) just so happens to have a FREQOUT command that you can use with it. I quickly got to work, coming up with this schematic:

Pin 11 is connected to the anode of the piezo buzzer. The cathode (which should cross the center of your homework board’s breadboard) is connected to Vss (the ground). Here’s what it actually looks like once it’s wired up:

With the (extremely simple) wiring complete, we can change our attention to the (almost equally simple) code. The Annoy-a-tron beeps once every 2-8 minutes at a frequency of either 2kHz or 12kHz. The speaker that came with the kit seems to perform best at around 4.5kHz so we’ll use that. As for the time, we have a problem. Why not just randomize a variable with time in it, pause for that long, then loop back again?

The trouble is that the largest data type that the Stamp I have supports is a 16-bit word, which has a maximum unsigned value of 65,535. The PAUSE command accepts an argument in milliseconds. Now what? Loop.

The solution I devised is able to replicate the Annoy-a-tron’s 2-8 minute random interval quite well. Here’s how it works:

  • The RANDOM command is used to obtain a random 16-bit value.
  • We then convert it to a value between 10,000 and 40,000 (in intervals of 10,000). How? The modulo (mod) operator, which is // in PBASIC. The modulo operation finds the remainder when one number is divided by another. A // N can have any value from 0 to N-1, so (A // N) + 1 can have any value from 1 to N. If that gets multiplied by 10,000, the result is any number from 10,000 to N(10,000).
  • Therefore, to get a random number from 10,000 to 40,000 in intervals of 10,000, we use the modulo operator on the random with an “N” value of 4, add 1 to it, and multiply by 10,000.
  • This number is used in a PAUSE command.
  • This pause command is looped 12 times.
  • The result can be 2, 4, 6, or 8 minutes.
After the delay, a beep is played for a enough time to be annoying but not long enough to be discovered. I decided on 1.5 seconds (1500ms). The code was easy to write once I figured out how the loop would work:
' {$STAMP BS2}
' {$PBASIC 2.5}
DEBUG "Running." ' Avoid error on some PCs' debuggers.
time VAR Word ' Used to store time interval.
i VAR Nib ' Used for the FOR...NEXT loop.
FREQOUT 11, 1500, 4500 ' I like having a startup beep.
  RANDOM time ' Store a random 16-bit value in time
  time = ((time // 4) + 1) * 10000 ' Get the random interval. Will be between 10 and 40s
  FOR i = 1 TO 12 ' We start at 1 because 12 is included; this will be executed 12x.
    PAUSE time ' We pause for the same 10-40 second interval 12 times to yield 2-8 min.
  FREQOUT 11, 1500, 4500 ' Play the annoying tone.
LOOP ' Start the whole thing over.

There you have it! Run this code on your BASIC Stamp, hide your enormous board, and hope nobody smashes it! I have not used this long enough to know how long a 9v battery can power it, but I am sure it is a more-than-adequate amount of time to get your point across. The biggest issue I have seen with this code is that the Stamp’s pseudo-random number generator isn’t very good. In fact, it generates numbers in the same exact order every time. You’ll never be surprised. Still, for being so simple, this circuit is a heck of a lot of fun. Happy annoying!

Multiple File Upload Made Easy!

Uploading one file to a server is beyond easy with the help of ASP.NET, but when you add more than one file to the mix, things start getting tricky. I ran into multi-upload related issues on a recent in-company project at RMC, and rather than using a plugin, I decided to see if I could come up with something quick-and-dirty with minimal effort.

My project involved migrating a single upload to multiple uploads, so the my first step was to update my server code. Using an HttpFileCollection to retrieve files from a request will work when there is a single .NET file uploader or multiple HTML file input boxes. Here’s how you do it:

HttpFileCollection files = Request.Files;

It’s that easy. The next step is to loop through the uploaded files and save them. You can put the following in a submit button event handler:

HttpFileCollection files = Request.Files;
for(int i = 0; i < files.Count; i++)

The server-sided piece is done. Next comes the client side. For that, we will use jQuery. I realize the way I have gone about doing this isn’t the best jQuery-wise, but it is simple and it works. We will have two helper methods: one to add a file upload box and one to remove it. When we add a file upload box, we just append the relevant HTML to a parent element. When we remove a file element box, we remove the p element from its parent div. Simple enough, right?

    function AddBox(parent){
        // Add HTML for another file upload box to the DOM
        parent.append('<p>input type="file" runat="server" /><a onclick="RemoveBox(this);" href="#">Remove</a></p>');
    function RemoveBox(aContext) {
        // Get jQuery instance of "this" from the link, get its parent element
        // and remove that parent from the DOM.

Note the ‘runat=”server”‘ in AddBox. When I tested this, the files did not show up on the server without the ‘runat=”server”‘ in the input box.

All that is left now is to plug the JavaScript into your ASPX page. You’re good to go with almost no code! The only real issue with this is that if your page has to do a postback to validate, the boxes will not persist (and neither will the selected files) – this could be a big annoyance to your users. The upload will not be asynchronous, either. However, this does the trick if you need a quick, easy solution.

Here’s an example to get you started:

<div id="upload">
    <input type="button" onclick="AddBox($('upload'));" value="Add File Box" />

Unlose Yourself!

In the app I’m working on this summer, I am using GPS functionality pretty extensively. The now-web-standard JavaScript interface is the same as it is in PhoneGap (now Apache Cordova), so I have been able to test on my desktop PC (and you can too). The problem is that your GPS can’t tell you what town you’re in or much more than your latitude and longitude. I needed more than that for my app, so it was jQuery to the rescue.

I apologize in advance for some of my coding practices – writing JavaScript feels a lot like writing Spanish to me, so feel free to alert me of any bad habits I have. Remember what I said in my first post!

Now then, the first thing I did was to write a method to get location XML from PlaceFinder. But how? Yahoo’s documentation has the answer with this example request:,+-77.035974&gflags=R&appid=[yourappidhere]

Easy enough, right? All we have to do is register for an app ID, get our coordinates, build the request, and use AJAX to do the rest of our bidding. We will also have a success callback so the resulting XML can be parsed – you’ll see in a moment.

var lat, long;
var appid = 'YOUR APPID HERE';
function getLocationXML(successCallback) {
    // Get the position
    // Build URL
    // AJAX

Now we have to start coding. To get the current position, just call navigator.getlocation.getCurrentPosition, which can take three possible arguments. We will use the first two, which are the success callback and the failure callback. The success callback takes a position as an argument and the error callback takes the exception as an argument.

function getLocationXML(successCallback) {
    navigator.geolocation.getCurrentPosition(function(position) {
        lat = position.coords.latitude;
        long = position.coords.longitude; // Cordova documentation might be helpful here
        // Build URL
        // AJAX
    function (error) {
        $.error('GPS error (' + error.code + '):' + error.message); // Throw the exception to be handled elsewhere

Right, now we need to build the URL. We will just get string versions of our latitude and longitude and plug them into a variable called URL. This step is simple enough that I feel like I can also cover the AJAX request here. We will use a HTTP GET request (jQuery’s get() method makes this a breeze) to get the data from the Yahoo servers. The AJAX request needs a success callback, for which we will make an anonymous function that calls the successCallback getLocationXML was called with and passes it the data from the AJAX request.

function getLocationXML(successCallback) {
    navigator.geolocation.getCurrentPosition(function(position) {
        lat = position.coords.latitude;
        long = position.coords.longitude; // Cordova documentation might be helpful here
        var url = '' + lat.toString() + ',+' + long.toString()
            + '&amp;gflags=R&amp;appid=' + appid; // Create formatted URL that we can use for AJAX
        // Now we get PlaceFinder data
        $.get(url, function (data) {
            successCallback(data); // call successCallback with what we got from Yahoo
        }, 'xml');
    function (error) {
        $.error('GPS error (' + error.code + '):' + error.message); // Throw the exception to be handled elsewhere

Great, we’re done with the hard part. Now we just have to interpret what Yahoo gives us. First, we will write an XML parser method that takes the XML document Yahoo sends us and retrieve the value of a node:

function xmlParse(xml, node) {
    var d = $(xml); // jQuery version of our XML document
    return d.find(node).text(); // Grab the node text and return.

This may seem overly simplistic to you, but when you look at what Yahoo PlaceFinder sends back (in this case, for 1600 Pennsylvania Avenue), you don’t need anything more complex:

No error
38.898717, -77.035974
1600 Pennsylvania Ave NW
Washington, DC 20006
United States
Pennsylvania Ave NW
District of Columbia
District of Columbia
United States

We’re pretty much done. Here’s some example usage in the head of an HTML document:

$(document).ready(function () {
    var sCallback = function(data) {
        console.log(xmlParse(data, 'city')) // Get information from city node
                                            // In above XML, prints "Washington" in console log.
    getLocationXML(sCallback); // Get the XML and then run the callback when that's done.

That’s it! You can figure out the name of your location with your phone and a little JavaScript. That’s pretty cool.

Introducing Myself

Little is more important than a first impression, and this post is exactly that – a giant “Hello, World!” I’ve begun several blogs in the past and have written some articles that based on the occasional comments have proven useful to a few (lucky) people. I aim to do better this time. This blog will be updated regularly with interesting, relevant information about a wide variety of my musings, from what I am doing at work to code to electronics to robotics. Who knows, I might throw in the occasional sports or car post. My interests are varied enough that there ought to be something on this blog for everyone (once I’ve written it). Heck, I even play golf.

I hope you will enjoy what I write here and provide feedback on my projects. Constructive criticism never hurts; no one ever improved by being told he is great when in reality he is not. As much as I want to help the Internet community, I would like the Internet community to help me.

Now, a little about me. In my biography on this site, I wrote about how I am an information technology intern at RMC Research Corporation in Portsmouth, New Hampshire. I worked there in the summer of 2011 and I decided to come back to do more. Last year, I worked on two main projects:

  1. Student Voice, a jQTouch-based mobile web application to improve communication between teachers and students. In hindsight, jQuery Mobile would have been a much better idea to use due to jQTouch’s bugs and lack of active development. Both the teacher portal and mobile web app are currently in in-house alpha stage and we will be seeking feedback on our prototype soon.
  2. SendTo, a small C#-based web application that makes sending large files over email an easier task for RMC employees. Before SendTo, people in the company used FTP to send files that were too big to attach to emails, which would have been fine were it not for the non-technical background of most RMC employees. File transfer support calls have been cut significantly.

One of the best parts of my internship at RMC is that it is meant to be as beneficial for me as it is for the company. That is, I am free to work on personal projects as well as work-related projects and I have been tasked with finding company-benefiting tasks that are interesting to me. Thus, I also worked on many small, side projects last summer.

This year, I will be developing a course about a BASIC Stamp microcontroller, working on a PhoneGap app built with jQuery Mobile, completing day-to-day tech department tasks, and continuing to work on personal projects.