If It's Worth Ranting About…

If It's Worth Ranting About…

Chris Seto's blog
RSS icon Email icon Home icon
  • Reboot

    Posted on April 4th, 2012 admin No comments

    I’ve decided to reboot this blog a bit. It’s been a long time since I started it, and things have grown a bit stale.

    Who I am
    My name is Chris Seto, I live in Rolla, MO studying computer engineering at Missouri S & T (called UMR many moons ago). I am currently involved in two separate military and civilian research projects, and I am also working as a freelance embedded software engineer with a focus on ARM and AVR as well. My hobbies include cross country cycling as well as all manor of things to do with fullscale/unmanned aircraft and flight.

    Quadcopters and flying
    I current own 2 flying quadcopters. Both utilize brushless motors and composite/aluminum frames. My primary aircraft is powered by an Openpilot CC and is fully FPV capable with a GoPro HD2, DragonOSD, and 500mW video transmitter allowing long haul flights. The other aircraft is an experimental test bed for self designed avionics. I have been flying RC aircraft in one form or another for about 8 years now, though as of 2 years ago, I pretty much only fly quadcopters due to the ease of setup and the ability to go out and fly just about anywhere.

    I also have a strong interest in fullsize aviation and have had many adventures in small GA planes. One of these can be read in a previous blog entry “Flying into Oshkosh 2010″. Speaking of Oshkosh, I do fly up every year and can usually be found in the LongEZ/canard aviation section of homebuilt camping.

    Biking
    Another one of my biggest passions is for cycling. I currently own a 2012 Giant XtC 29er which I have only logged ~120 miles on since I picked it up 4 weeks ago, replacing my aging 2008 Kona, which I had well over 4,000 miles on it by the time I bought the XtC. One of the nice things about Rolla is that it’s hilly and full of trails, so when it’s nice out I enjoy going out trail riding. Otherwise, I use cycling as a vital way of getting from one spot on campus to another extremely rapidly. Being able to keep up the speed of a bike while still being able to go up/down stairs and off ledges and low drop off saves me obscene amounts of time.

  • Flying into Airventure 2010

    Posted on August 3rd, 2010 Chris Seto No comments

    This is a piece I wrote for my local EAA chapter’s newsletter describing my trip up to Airventure with Art Zemon in his Piper Arrow.

    As with Oshkoshes past, I stay with one of my LongEZ friends in HBC. He was set to leave on Sunday and get in a few hours after I did. After hearing about the dismally wet field conditions, I called him on Saturday to see what he had to say. It turned out that he was completely unaware of the rapidly worsening situation at Oshkosh. All of Saturday, I was monitoring Twitter, KOSH ATC and the KOSH webcam trying to figure out what was going on and if we would be able to park until the EAA posted an update saying that they would be trying to park aircraft on Sunday morning. I called my LongEZ friend and told him the good news that night.

    Next morning, Art and I were stuck on the ground due to deteriorating field conditions at OSH. I called up my friend to see what was going on and learned that he was unable to land anywhere near Oshkosh. Appleton and Fon Du Lac were both saturated with traffic and closed, but he had found an alternative airport (KUNU) in Juneau, Wisconsin that allowed camping. He was going to stay there until KOSH opened and he could fly in.

    Meanwhile, Art and I were still watching the OSH parking status waiting for an opening which never came. By 3PM it became clear we would be spending that night at home.

    I got a text message at 6AM on Monday from Art saying he wanted to meet and get out to the airport by 9AM. The theory was that the field would be opened in the morning, and we would be prepared by having his plane loaded and ready to depart as soon as the EAA announced that GA planes were being parked. The first status update that was planned for 9AM was still pretty dismal. GA aircraft were still being turned away, but by 11AM we had a more optimistic report of field conditions maybe supporting GA parking later in the day. The page listed that a new update would be posted at noon.

    Noon came and left without a positive update. My friend sent me a text message saying that he made it into Oshkosh and had now had his LongEZ parked in HBC.

    Around this time, Art and I started talking about maybe starting on our way, hoping that KOSH would open and we could land, if not that day, maybe next. Reminded of my LongEZ friend’s success with staying at KUNU, I decided to see what Art thought of the idea of leaving for KUNU, in hopes that the airshow would end and we could finally get in. If it didn’t we could always camp at KUNU until it did. Art seemed to like this idea, and after filing our VFR flight plan and checking weather we were finally able to takeoff.

    After landing at KUNU two hours later, we found out that although the field was closed, it had been open earlier in the day and would open in two hours, after the airshow.

    KUNU was inundated with people using it as a stepping stone to Oshkosh in the same way we were. The staff had setup some free food and there were plenty of things to look at, including some prototype trikes parked out front.

    Half an hour before the airshow was over, we took off with the many others waiting and headed for Ripon. Flying the pattern took surprisingly little time and the controller actually only talked to us two or three times. At last, we were in Oshkosh!

    The field conditions were still pretty muddy, and as a result, we ended up taxiing on hard surfaces only, using a torn up taxiway along 18/36. A bigger surprise came when we were routed to an area of the field far from the North 40 (past the terminal, even) where no camping was allowed. We were expected to grab all of our camping gear and take a bus to the North 40 to camp there. At this, point, I split with Art since it was getting dark and I wanted to have my tent set up next to my friend’s LongEZ before it got too dark.

    I ended up walking to HBC, meeting my friend, and having my tent set up just as dark came.

    Oshkosh was surprisingly crowded this year, considering how few GA planes actually made it in. HBC and most of the show plane areas had filled up, however the North 40 only get marginally full at the end of our stay. Because of all of the standing water, mosquitoes were fierce this year. I had to be back in the tent by 9PM sharp to avoid being eaten alive by them. Other than those things, it was a pretty typical Oshkosh with all the usual vendors, aircraft noise and forums. My canard friends and I mostly stayed in the middle section of the field with the forums and vendor booths, although from what I hear Art seemed to like to stick with the South end of the field with his new found interest: ultralight aircraft.
    For the most part, weather was sunny and warm. We got a few small rain showers here and there, but nothing severe. At times it felt like autumn, which was not necessarily a bad thing, since it meant that nights were cool and the days were warm, but never uncomfortable.
    Art and I decided to stay an extra two days to make up for the delays in getting out. When the time came to finally leave on Saturday, we met up and started our flight planning when a new METAR came current indicating that the ceiling had dropped too close for comfort. We went off-field for a quick brunch and by the time we got back, the conditions had improved enough for us to take off and fly under the clouds until we found a crack, climbed out and activated an IFR flight plan. After flying in and around the clouds for close to two and a half hours, we landed at a very hot and humid KSET

  • In case someone ever finds this useful…

    Posted on May 9th, 2010 Chris Seto No comments

    I was playing a servo this evening, controlling it back and forth with my new FEZ Domino, and I had a really hard time getting the timing just right so that the servo’s control arm would move exactly 180 degrees around and be perfectly centered at 90 degrees.

    Servos are controlled with variable length high pulses sent every ~20ms. The length of the high pulse is inversely proportional to the position of the servos control arm. For example, If you are looking at the servo with the wire in front, the shorter the high pulse, the farther the control arm moves to the right.

    As long as the servo is being fed pulses, it will maintain the control arm’s position. If for some reason you need to, you can “disengage” the servo by pulling the signal line to ground for more than 20ms.

    There are a few graphs floating around the internet that supposedly give the correct pulse times to control servos, but I found all of the ones I looked at to be wrong. So, after some time with the oscilloscope, I was finally able to figure out what the correct timings were for the 3 control arm positions.

    0 degrees: .41ms
    Center (90 degrees): 1.269ms
    180 degrees: 2.141ms

    These timings are for the Futaba S3003. I don’t know if these will work as well (or at all) for other makes and models.

    Pulse wave at zero degrees

  • Sending magic packets with PHP

    Posted on April 12th, 2010 Chris Seto 1 comment

    When a “normal person” wants to remote into his or her home computer, they just leave their computer on and remote in when they need to.

    I am not a “normal person”. I don’t like to leave my home desktop on all the time for a number of reasons, but I still need to be able to remote in.

    The solution? Wake on LAN.

    I have a router that runs DD-WRT, which has a WOL control panel built in, but I didn’t want to dig through my router’s admin panel every time I wanted to turn my computer on.

    After a quick Google search, I found that sending a WOL request (magic packet) wasn’t too difficult. Someone had even already created a PHP script to send them.

    That script was a great starting point, but it was a little messy, so I went about reformatting, improving and object’izing it.

    The end result is this:

    <?php
    # Wake on LAN - (c) HotKey@spr.at, upgraded by Murzik
    # Modified by Allan Barizo http://www.hackernotcracker.com
    // Reformatted, improved and OO'ized by Chris Seto http://www.chrisseto.com
    
    class WOL
    {
    	private $broadcast   = '';
    	private $lastStatus  = 'NA';
    
    	/**
    	 * void __construct(string $network)
    	 * 	Start the WOL class and specify broadcast network
    	 *
    	 * @param $network				The network to broadcast on
    	 * @return void
    	 */
    	public function __construct($network)
    	{
    		// TODO: Verification
    		$this->broadcast = $network.'.255';
    	}
    
    	/**
    	 * string getLastStatus(void)
    	 * 	Get status of last wake up call
    	 *
    	 * @return string			Result of last wakeOnLan
    	 */
    	public function getLastStatus()
    	{
    		return $this->lastStatus;
    	}
    
    	/**
    	 * bool wakeOnLan(string $mac, int $socket_number)
    	 * 	Wake up a remote computer
    	 *
    	 * @param $mac				The MAC address of the remote computer to wake
    	 * @param $socket_number	The socket to wake on, usually port 7
    	 * @return true/false
    	 */
    	public function wakeOnLan($mac, $socket_number=7)
    	{
    		$addr_byte = explode(':', $mac);
    		$hw_addr   = '';
    
    		for ($a=0; $a <6; $a++)
    			$hw_addr .= chr(hexdec($addr_byte[$a]));
    
    		$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
    
    		for ($a = 1; $a <= 16; $a++)
    			$msg .= $hw_addr;
    
    		// Try to create socket
    		if (!$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))
    		{
    			$this->lastStatus = 'socket_create_fail';
    			return false;
    		}
    
    		// Try to set broadcast option
    		if (socket_set_option($s, 1, 6, TRUE) < 0)
    		{
    			$this->lastStatus = 'setsockopt_fail';
    			return false;
    		}
    
    		// Try to send magic packet
    		if (socket_sendto($s, $msg, strlen($msg), 0, $this->broadcast, $socket_number))
    		{
    			$this->lastStatus = 'OK';
    			socket_close($s);
    			return true;
    		}
    		else
    		{
    			$this->lastStatus = 'send_fail';
    			return false;
    		}
    	}
    }
    
    // Create the WOL object
    $wol = new WOL('192.168.15');
    
    // Wake up!
    $wol->wakeOnLan('00:XX:XX:51:XX:FC');
    
    // Handle the status for the last call to WakeOnLan()
    switch ($wol->getLastStatus())
    {
    	case 'OK':
    	echo 'Magic packet sent!';
    	break;
    
    	case 'NA':
    	echo 'No call to wakeOnLan() has been made...';
    	break;
    
    	case 'socket_create_fail':
    	echo 'Could not create socket!';
    	break;
    
    	case 'setsockopt_fail':
    	echo 'Could not set socket option!';
    	break;
    
    	case 'send_fail':
    	echo 'Could not send packet!';
    	break;
    
    	default:
    	echo 'I have no idea what happened.';
    	break;
    }
    

    It’s worth noting that WOL can be tricky. This is confimred to work on my desktop and ESXi server, both of which have Intel PRO/1000 GT network cards.

    You also may need to enable WOL in your computers BIOS. On some motherboards with built in network cards there may be a verbose option to enable WOL, and on others there may just be a “power up on PCI event” option. I used the latter option to enable WOL on my motherboard.

    EDIT: Corrected the problem with the getLastStatus() handler.

  • Using AutoHotKey with the MS Bluetooth Mouse 5000

    Posted on April 4th, 2010 Chris Seto No comments

    I have a Microsoft Bluetooth Notebook Mouse 5000 that I use with my tablet PC when I am on the run.

    The mouse has an extra side button (which I will refer to as SB [side button] from now on), that by default, is mapped to the back button in a web browser.

    To me, having that functionality is pretty useless. I have been clicking the back button on my web browser for a lot longer than I have had the mouse, so it feels far more natural to simply do that. Since I haven’t been able to train myself to use the mouse’s back button, I decided to see if I could change the button assignment to something more useful.

    Enter AutoHotKey.

    AutoHotKey (AHK) is a weird little scripting language that allows you to intercept and mouse events. For example, let’s say that you wanted to force the “a” key on your keyboard to behave like it was a “B” key. You could make an AHK script that would look something like this…

    a::B
    

    That may be useful, but only to a certain point. What really makes AHK great is it’s ability to send and receive “special” keys, like the ones on your media keyboard, or the buttons on your mouse. After some research (RE: trial and error) I found that SB was sending an XButton1.

    The first script I made was simply…

    XButton2::media_play_pause
    

    …Basically I just remapped SB to the play_pause hotkey, so if I tapped it Windows Media Player would play or pause. Certainly better than before, but I wanted to get a little more ambitious.

    At home, I have an MX Revolution with one button mapped to play/pause and two others for volume up and down. I have been using this mapping for years, and am very used to it. I decided my goal at this point was to simulate this functionality as best I could on my BT mouse, despite it being at least 2 buttons short of having enough for a dedicated button for each action.

    The solution was to use SB as a sort of “shift” button. The idea being that when I pressed and held SB, the scroll wheel would control volume instead of page scrolling. When I released SB, the scroll wheel would go back to the normal page scroll mode. I would trigger the play/pause hotkey by double tapping SB.

    AHK supports the AND operator in hotkey remappings, so remapping the scroll wheel was easy:

    XButton1 & WheelDown::
    	Send {Volume_Down}
    	return
    
    XButton1 & WheelUp::
    	Send {Volume_Up}
    	return
    

    …If XButton1 was held down and the wheel scrolled up/down, the volume would follow.

    Play/pause was a little harder to do….

    debounce := A_TickCount
    
    XButton1::
    	if (A_TickCount - debounce > 400)
    	{
    		debounce := A_TickCount
    		return
    	}
    
    	Send {Media_Play_Pause}
    	return
    

    …Every time we get an XButton2, check to see if it has been pressed less than 400 milliseconds ago. If it has, then we are dealing with a double tap.

    Put it altogether and you have….

    #NoEnv
    SendMode Input
    SetWorkingDir %A_ScriptDir%
    
    debounce := A_TickCount
    
    XButton2::
    	if (A_TickCount - debounce > 400)
    	{
    		debounce := A_TickCount
    		return
    	}
    
    	Send {Media_Play_Pause}
    	return
    
    XButton2 & WheelDown::
    	Send {Volume_Down}
    	return
    
    XButton2 & WheelUp::
    	Send {Volume_Up}
    	return
    

    AHK bundles a tool to compile AHK scripts into EXEs, so I compiled the final script and put it in the startup folder on my computer. As long as that EXE is running, SB is effectively remapped.

  • Using OpenVPN with DD-WRT

    Posted on March 11th, 2010 Chris Seto No comments

    A few months ago, I decided to see if I could get a VPN running on my home network so I could code while I was out of the house. I downloaded and installed DD-WRT VPN on my Buffalo WHR-HP-G54 and attempted to get OpenVPN working through the included WebUI.

    Unfortunately, nothing I did would result in a working VPN. No matter what I did, there was always some sort of problem. I spent hours troubleshooting to no avail, and eventually abandoned the project.

    About a week ago, I decided to see if I could get it working again, and this time I figured out a way of getting it to work, abet in a limited way.

    I talked with some people on a tech forum and found out that they too had trouble getting the WebUI to work for them, and one poster suggested that I try a little startup script to start OpenVPN with a static key, instead of the more error prone certificates.

    With that script, I was able to get everything working nicely, and I figured I’d document what I went through for anyone else out there who has also struggled with it….

    On the router…
    1. Disable OpenVPN server in the DD-WRT WebUI (I don’t know if this actually does anything. Mine appears to re-enable itself on reboot)

    2. On another machine with OpenVPN installed do:

    $ openvpn --genkey --secret static.key

    3. Get the content of static.key and paste it into the following script, replacing !STATIC.KEY HERE! with the contents of static.key (exclude the top —- BEGIN —- and bottom —- END —- in static.key):

    openvpn --mktun --dev tap0
       brctl addif br0 tap0
       ifconfig tap0 0.0.0.0 promisc up
       echo "
    -----BEGIN OpenVPN Static key V1-----
    !STATIC.KEY HERE!
    -----END OpenVPN Static key V1-----
       " > /tmp/static.key
       ln -s /usr/sbin/openvpn /tmp/myvpn
       /tmp/myvpn --dev tap0 --secret /tmp/static.key --comp-lzo --port 110 --proto udp --verb 3 --daemon
    

    4. Paste that command list into the Commands page of the DD-WRT WebUI and save it as “Startup”

    5. Paste the following into the Commands page and save as “firewall”

    iptables -I INPUT 1 -p udp --dport 110 -j ACCEPT

    6. Reboot your router.

    On the client
    1. Copy static.key off to where ever you want it. I put mine in C:\

    2. Create a a .ovpn configuration file in the OpenVPN configuration file directory (C:\Program Files\OpenVPN\config)

    3. Paste the following configuration directives in your .ovpn file:

    remote <Your IP/Domain>
    port 110
    dev tap
    secret C:/static.key
    proto udp
    comp-lzo
    

    4. You can now start OpenVPN with that configuration file.

    It’s worth noting that this isn’t going to work for multi-user environments. A static key pair will only work for one server and client. For me, this is perfect since I am only using this for my Tablet PC when I am on the run, but if for some reason you need more than that, you will need to figure out how to get certificates to work.

    There is also a speed limitation. Although I get a 30+ Mb/ps download rate, my upload rate is a slow 3Mb/ps, which I am able to saturate with almost no effort. I’m not actually sure what the speed bottleneck on the router is, but it is at least 3.12Mb/ps, since that is the fastest speed I have seen while copying files.

    Note: If you don’t want to use port 110, just replace all instances of 110 in the 3 commands/config directives above with your port of choice. The default is 1194.