2010
03.31


mwcrTrestleSouthNotchRoad032710

Originally uploaded by ka1kjz

For roughly 40 years, I had been aware of, and even played on, an abandoned rail line in Central CT. Of the parts that still had tracks, I merely assumed it was a siding off of the New Haven / Hartford & Springfield line, or simply Amtrak. Of the parts that had the tracks ripped up, I simply assumed it to be a power or gas right of way. Turns out, this was the long abandoned Meriden, Waterbury and Connecticut River Railroad.

The MW&CR was one of the last to be built in Connecticut, 1888, and one of the first to be abandoned, 1924 officially, but had been in disuse since 1898. It has left very little trace of its existance, except one 5 mile stretch near a quarry which was abandoned in 1969 or so. The Quarry kept the stretch to connect with the Amtrak line should they ever need it, they never used it.

One night, on the way home from work, I took a different route and discovered this bridge. I knew then that I had to document this railroad and find archeological remains of it before it was lost to history forever. There are only 2 or 3 reference works on this line and very little information where it ACTUALLY ran.

My work in progress can be found at http://www.w1xbs.com/cms and on Flickr, http://www.flickr.com/ka1kjz

2010
03.22

I’m getting too good at this, to help my boss out of a jam, I tossed up 4 new websites on my cloud server.

It was pretty simple and straight forward, and a major case for doing your own hosting. I shudder to think how tough it would be to point these new domains at a shared hosting site, without buying four hosting accounts. It took me about 2 hours to do, but only because I had forgotten much of what I did to get this site, hamopensouce.com and ronaldcbarnes.com working on my host. Also I don’t have any tidy scripts or templates, everything was edited by hand.

I only need to serve up about 5 static pages per site, very low traffic, I probably wont even notice the hits. A homepage, privacy statement, contact us page, and little else.  This is what it took:

DOMAIN REGISTRATION:
The domains www.wsah-tv.com, www.wmfp-tv.com, www.khiz-tv.com and www.kcns-tv.com,were all available for about $11 / year.  I snatched them up through my registrar, GoDaddy.com

NAME SERVER:
I pointed my new domains at my name server with the tools provided by GoDaddy.

DNS:
I created the necessary A, CNAME and MX records on my DNS server at my host provider.  I made CNAME entries for www.domain.tld, and mail.domain.tld.  I don’t believe we’ll be hosting a SMTP or POP server, but it’s there just in case and may be needed by the sendmail daemon.

DIRECTORY STRUCTURE:
Off my home directory is a directory where I keep all my websites.  From there, a standard web directory structure of “public”, “private”, “log”, “cgi-bin” and “backup” were created.

PERMISSIONS:
The directory and file permissions were set to 755 and owner was set to also include www-data.  (See your Linux documentation on how to do this, your mileage will vary from version to version).

VHOSTS:
A VHOSTS file was created in the /etc/apache2/sites-available directory which looks something like this (sensitive parts redacted).  The alias was used on this site for its wiki, and the FollowSymLinks reference was used as part of the WordPress permalinks and has since been remarked out.  They are there in case they are needed in the future.

# Place any notes or comments you have here
# It will make any customisation easier to understand in the weeks to come

# domain: wsah-tv.com
# public: /home/*****/*****/wsah-tv.com/public/

<VirtualHost *:80>

# Admin email, Server Name (domain name) and any aliases
ServerAdmin ka1kjz@ka1kjz.com
ServerName  wsah-tv.com
ServerAlias www.wsah-tv.com

# Index file and Document Root (where the public files are located)
DirectoryIndex index.php index.html
DocumentRoot /home/*****/*****/wsah-tv.com/public

#  <Directory /home/*****/*****/wsah-tv.com/public>
#    Options Indexes FollowSymLinks
#  </Directory>

<Directory /home/*****/*****/wsah-tv.com/public/cgi-bin/>
Options ExecCGI
AddHandler cgi-script cgi pl
</Directory>

# Custom log file locations
LogLevel warn
ErrorLog  /home/*****/*****/wsah-tv.com/log/error.log
CustomLog /home/*****/*****/wsah-tv.com/log/access.log combined

#Alias /wiki /home/*****/*****/wsah-tv.com/public/w/index.php

</VirtualHost>

A2ENSITE:
The script, a2ensite was run on each domain. It pretty much just sets up a symbolic link between /etc/apache2/sites-available and /etc/apache2/sites-enabled.

CONTENT UPLOADED:
I found a suitable template on the Open Source Web Directory, a repository of HTML templates released to the open source community.  The index.html, css and images folders were uploaded via Filezilla FTP (actually FSTP, SSH file transfer, I never bothered to set up FTP).

Thats it, after the DNS records had enough time to propagate through the internet, I had 4 new sites ready to go.  Content will be completed tomorrow, but the sites are up and the templates are in place.

FOR THE FUTURE:
I’d like to split these four domains out of my personal GoDaddy account and place them into something I can provide access to.  The corporate IT guy, my boss, my replacement should something happen to me, etc.

Also KHIZ has a nice shared hosting account already paid for by the company.  I am going to investigate pointing these domains at that.  If this proves problematic (I really cannot justify buying 4 separate hosting accounts for what we will be serving) I will sell the concept of the cloud server to the bosses.

2010
03.22

AtlanticAvenueTunnelEntrance04
Originally uploaded by ka1kjz

As part of Atlas Obscura Day 2010 I had the opportunity to tour the abandoned Long Island Railroad, Atlantic Avenue Tunnel, in Brooklyn NY.

This is not the LIRR you are familiar with, but rather, its predecessor, a railroad that tried to bring connectivity between NY Harbor and Boston. In the 1840s it was too difficult to do a land route through Connecticut, so they ran the railroad out over Long Island, went via steamboat to New London, then picked up the railroad again there to Boston.

When the LIRR went out of business in the 1850s, they filled in some of the tunnel, sealed it off, and forgot about it until 1916. They rediscovered the tunnel then, and promptly forgot about it again.

In 1982, it was rediscovered through careful research of newspaper articles of the time, old city plans, and pestering city officials and utility companies.

More details can be found at the Brooklyn Historic Railway Association site.

2010
03.19

I’ve made up a simple thermostat for the Jeenode, using the TMP421 temperature sensor, and just using my standard LED status indicator to see it in action.  This will be the basis of the Attic Fan Control.

Thermostats are not simple on/off devices, if they were, your furnace or airconditioner would sit there and “chatter” at the setpoint.  Thermostats have a deadband, called “differential”, where it is unresponsive between the setpoint and the difference caused by the differential setting.  Check out this article by The Lowell Center for Sustainable Production, UMass Lowell, and The Maine Department of Environmental Protection regarding how heating and cooling thermostats work.

A heating thermostat will turn off immediately at the setpoint, but not come back on until it falls differential degrees below the setpoint.  Same is true of cooling thermostats, they will turn off once the setpoint is reached, but will not turn back on until the temperature rises differential degrees.

Differentials vary widely from manufacturer to manufacturer but fall within the range of 2 to 4 degrees.  I have made the differential a #define in the sourcecode so that a it can be recompiled at any time with a new one, should my choice of 3 degrees prove inadequate somehow.

Beware, this sourcecode makes heavy use of the #define directive, to conditionally compile.  The TMP421 sensor is connected to port 1, and my standard status light is connected to port 3.  As always, source code is available here

Read More >>

2010
03.18

In some of my work with the Arduino, I connect a bicolor LED to a couple of I/O pins and use it as a standard status indicator.  Green, red and yellow, flashing or steady, etc… shows me various conditions in the program execution.  Here is a standard LED status indicator for my work with the JeeNodes. More of tool really, I plug this into a port, and have my LED back!

Code to light the LEDs is pretty simple… simply define the two ports as outputs, and bring them high depending on what you would like..  Green, Red or both to make Yellow.

2010
03.16

Unknown to me, while I was doing massive work on this blog, breaking it many times (more on that later), I was getting an uptick in traffic.  Seems my work with the Jeenodes has been discovered by Caleb Kraft over at Hack A Day.   Here is the linky goodness to the article, and repeated below..

It is basically a nice compact layout for an Atmel Atmega 328 with a wireless module.  Fully compatible with the Arduino IDE.  The JeeNode is available in kit form, but also all schematics and CAD files are available to download. It looks like they are mainly using it for home monitoring and control.  So far we’ve seen them put a temp sensor, power metering, and IR LED modules on their flickr set.

2010
03.14

Just playing around with some assorted plugins for this blog.  Over on the right you will find a media player for my station, Sublime Geek Radio.  Have fun.

2010
03.12

File Downloads Fixed

I review the log files for the site every day or so and had noticed some file not found errors.  Seems I forgot to move the download directory over from my old host…. So, that’s fixed.

2010
03.10

I had picked up a Grayhill 61C11-01-08-02 optical encoder quite awhile ago but never got around to interfacing it with a microcontroller.  With my recent purchase of a Sparkfun AD9835 breakout, it’s finally time to get to work and make something of these two items and an LCD.

Encoders are in use notably on higher end radios and tuners.  If your volume control has no stops and feels “steppy”, chances are that’s an encoder.  From the Arduino Playground page on encoders…

A rotary or “shaft” encoder is an angular measuring device. It is used to precisely measure rotation of motors or to create wheel controllers (knobs) that can turn infinitely (with no end stop like a potentiometer has). Some of them are also equipped with a pushbutton when you press on the axis (like the ones used for navigation on many music controllers). They come in all kinds of resolutions, from maybe 16 to at least 1024 steps per revolution…

I’m also thinking of making use of this in my OpenXX, Syntor X controller project.  No, the Sparkfun AD9835 won’t be used in the Syntor, point is, I’ll be doing something radioesque with this.

Connection was very simple, as you can see, only 3 wires to the microcontroller (one is for the pushbutton function and the 4th for a LED) and two to power and ground.

Code on the Arduino playground worked on the first try, notably the interrupt driven code, but I found it susceptible to bounce.  I incorporated a quick and dirty delay loop to calm things down a little, and now, spinning the encoder is smooth and reliable.

Hookup was simple, encoder pin 1& 2 to ground, 3 to Arduino pin 4, 4 to Arduino pin 3, 5 to Arduino pin 2 and 6 to +5V.   What you do with it, is entirely up to you.

Here’s the sourcecode, with plenty of comments…

#include <Bounce.h>  // import debounce library

#define encoder0PinA 2  // encoder pin A on pin 2
#define encoder0PinB 3  // encoder pin B on pin 3
#define button 4  // shaft button on pin 4
#define RED 5  // red LED on proto shield on pin 5

volatile unsigned int encoder0Pos = 0;  // scratchpad within ints
volatile unsigned int x = 0;  // delay loop counter

boolean ledValue = LOW;  // LED on/off flag

// Instantiate a Bounce object with a 5 millisecond debounce time
Bounce bouncer = Bounce(button, 5);  

void setup()
{
  Serial.begin (9600);
  delay(1000);

  pinMode(encoder0PinA, INPUT);
  digitalWrite(encoder0PinA, HIGH);
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinB, HIGH);
  pinMode(button, INPUT);
  digitalWrite(button, HIGH);
  pinMode(RED,OUTPUT);

  // encoder pin on interrupt 0 (pin 2)
  attachInterrupt(0, doEncoderA, CHANGE);

  // encoder pin on interrupt 1 (pin 3)
  attachInterrupt(1, doEncoderB, CHANGE);
}

void loop()
{
  if (bouncer.update())
  {
    if ( bouncer.read() == HIGH)
    {
      if ( ledValue == LOW )
      {
        ledValue = HIGH;
      }
      else
      {
        ledValue = LOW;
      }
      digitalWrite(RED,ledValue);
    }
  }
}

void doEncoderA()
{
  // detach interrupts to not interrupt the interrupts
  detachInterrupt(0);
  detachInterrupt(1);

  // a quick and dirty delay to let things settle
  // as delay() doesnt work within interrupts
  for(x=0; x<100; x++)
  {
    asm("nop\n");
  }

  // look for a low-to-high on channel A
  if (digitalRead(encoder0PinA) == HIGH)
  {
    // check channel B to see which way encoder is turning
    if (digitalRead(encoder0PinB) == LOW)
    {
      encoder0Pos = encoder0Pos + 1;  // CW
    }
    else
    {
      encoder0Pos = encoder0Pos - 1;  // CCW
    }
  }

  else   // must be a high-to-low edge on channel A                                       
  {
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinB) == HIGH)
    {
      encoder0Pos = encoder0Pos + 1;  // CW
    }
    else
    {
      encoder0Pos = encoder0Pos - 1;  // CCW
    }
  }
  // use for debugging - remember to comment out
  Serial.println (encoder0Pos, DEC);          

  // reattach interrupts
  attachInterrupt(1, doEncoderB, CHANGE);
  attachInterrupt(0, doEncoderA, CHANGE);
}

void doEncoderB()
{
  // detach interrupts to not interrupt the interrupts
  detachInterrupt(1);
  detachInterrupt(0);

  // a quick and dirty delay to let things settle
  // as delay() doesnt work within interrupts
  for(x=0; x<100; x++)
  {
    asm("nop\n");
  }

  // look for a low-to-high on channel B
  if (digitalRead(encoder0PinB) == HIGH)
  {
    // check channel A to see which way encoder is turning
    if (digitalRead(encoder0PinA) == HIGH)
    {
      encoder0Pos = encoder0Pos + 1;         // CW
    }
    else
    {
      encoder0Pos = encoder0Pos - 1;         // CCW
    }
  }
  // Look for a high-to-low on channel B
  else
  {
    // check channel B to see which way encoder is turning  
    if (digitalRead(encoder0PinA) == LOW)
    {
      encoder0Pos = encoder0Pos + 1;          // CW
    }
    else
    {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
  }
  // use for debugging - remember to comment out
  Serial.println (encoder0Pos, DEC);          

  // reattach interrupts
  attachInterrupt(0, doEncoderA, CHANGE);
  attachInterrupt(1, doEncoderB, CHANGE);
}
Encoder photo and datasheet diagram copyright Grayhill Inc.
2010
03.10

I have managed to write a suite of programs to effectively tether an Arduino to a computer, and have it interract with the internet, as if it had an ethernet shield attached to it.  This may seem like a step backwards, and in some ways it is, but the reasoning for doing this was as follows.

  • Eliminates the ethernet shield (a $30-45 USD value)
  • Eliminates many ethernet connections to several Arduinos in close proximity. (My basement will have at least 3 monitoring things).
  • For remote sites that do not have high speed ethernet, this allows use of dialup or internet connection sharing.  (For example remote radio/television transmitter sites).
  • Computers are a dime-a-dozen, we dont need speed or huge drives here.  A DOS machine could work!

The programs are not pretty, so complete source is not available yet, but the basic concepts are described below.  This is an ongoing development, but here is the block diagram of the concept.

A very simple serial protocol was developed, essentially a letter and a channel number, followed by an equal sign, then the value, delimited by a pipe.  The raw data, minus the delimiter, forms the argument to the perl script on the server.  This also has the added benefit of making it somewhat human readable.  I plan to add a simple checksum or CRC to the end, to guard against corrupt data.

A fully implemented Arduino tether, with no fancy sensors, serial stream to the computer would look something like:

A0=123|A1=456|A2=789|A3=876|A4=543|A5=210|
D0=0|D1=1|D2=0|D3=1|D4=0|D5=1|D6=0|D7=1|
D8=0|D9=1|D10=0|D11=1|D12=0|D13=1<CR><LF>

Letter assignments, so far, for this protocol are as follows:

  • A = analog (0-5) integer 0-1024 (raw analog data)
  • B = battery (0-n) float 0 – max voltage (formatted voltage data)
  • D = digital (0-13) boolean (raw digital port state)
  • H = humidity (0-n) (format to be determined)
  • I = current (0-n) float 0 – max current (formatted amperage data)
  • L = light level (0-n) (format to be determined)
  • M = motion (0-n) boolean (there is or is not motion)
  • R = rotations per minute (0-n) 0 – max RPM (formatted RPM data (1/4 RPM a-la OBD-II?))
  • S = speed (0-n) 0 – max speed (any unit)
  • T = temp (0-n) (min max determined by sensor) float  (degC or degF)
  • U = latitude (0) [cant be in 2 places at once] float (degrees)
  • V = longitude (0) [cant be in 2 places at once] float (degrees)
  • W = altitude (0) [cant be in 2 places at once] float (height ASL)
  • X = x position (0) [cant be in 2 places at once] (to be determined)
  • Y = y position (0) [cant be in 2 places at once] (to be determined)
  • Z = z position (0) [cant be in 2 places at once] (to be determined)

A simple Arduino sketch was formulated to send temperature readings (using the Modern Devices TMP-421 temp sensor) via the serial port to the computer. In this example, T0=XX.XX, forms the exact argument and will be placed into the http GET statement, by the computer, verbatim.

#include "Wire.h"
#include <LibTemperature.h>

LibTemperature temp = LibTemperature(0);

float tempF;

void setup()
{
  Serial.begin(9600);
  delay(1000);
  for (int x=0; x<5; x++)
  {
    float y = temp.GetTemperature();
  }
}

void loop()
{
  // convert to degF
  tempF = (temp.GetTemperature() * 9 / 5) + 32;  

  Serial.print("T=");
  Serial.println(tempF);
  delay(10000);
}

On the computer, a very rudimentary Processing script was written, to open a web connection to my server, write out a http GET, and close the connection.  Everything was hardcoded to make the example work, but it does work.  The business end of that script (sensitive bits redacted) looks like this;

void serialEvent(Serial p)
{
  // Connect to server on port 80
  c = new Client(this, "www.xxxxxx.com", 80); 

  // grab incoming string off of serial port
  inString = p.readString();

  // inform us we have one and are sending
  println("writing to host");

  // start building HTTP GET statement
  c.write("GET /XXX-XXX/XXXX_XXXXXX.pl?");

  // chop off CR/LF
  outString = inString.substring(0, inString.length() -2); 

  // pass on the serial input to HTTP GET
  c.write(outString);

  // close up the HTTP GET
  c.write(" HTTP/1.1\n"); 

  // needed for apache2's vhosts, same as above
  c.write("Host: www.xxxxxx.com\n\n");
}

I simply used another copy of the perl script used in the temperature graphing application to write to the mySQL database.

The meat of that script looks like this;

# PERL DBI CONNECT
$connect = DBI->connect($dsn, $user, $pw) or
  die "Unable to connect: $DBI::errstr\n";

$vtime = time()*1000;

# PREPARE THE QUERY
$query = "INSERT INTO TETHER_001(Temp0, Time)
  VALUES ($currentvalue,$vtime)";
$query_handle = $connect->prepare($query);

# EXECUTE THE QUERY
$query_handle->execute();

As you can probably see, the database table names are hard coded into the mySQL queries. I hope to eliminate this, and also make the script a bit more bullet proof, adding table creation if it doesn’t exist, field creation if it doesn’t exist, error handling and so forth.

Click to embiggen / get the latest

And finally, I simply made another copy of my flot php script to display the temperature data in a browser.