Thursday, January 23, 2014

American Morse KK2 Paddle

This Christamas had a special treat for me. I told my wife that all I wanted for Christmas was an American Morse KK-2 CW paddle, because in 2014 I have a goal to learn CW. She worked with Santa, and the two of them came through for me!

Background: American Morse is a US-based manufacturing company which builds CNC-shaped precision products. They can be found at www.americanmorse.com Their approach is to keep it simple and build a few things really well. I was looking for a solid base station iambic paddle, and the KK-2 seemed like just the thing. It is!

The folks at American Morse build everything as a kit, and can ship kits or built product. I wanted the kit, of course. "I build, therefore I am..." Assembly was a snap--took about 15 min to prebuild, after which I disassembled, sanded out burrs, and did final assembly. This is the final product:

American Morse KK-2 paddle kit, assembled

The paddle arms are machined brass. It's not visible in the picture, but the arms are actually hollowed. The paddle tips are nylon. Everything else is high grade steel. As you can see, I've done nothing to "protect" the steel base--there are some rust spots appearing. I'm tempted to brush the base with my grinder and put a quick clear coat on it. That would look cool, but of course have no effect on the paddle's performance.

The paddle does not ship with a cable. I was toying with building one from scratch but when I got to Radio Shack and priced options, buying a stereo cable turned out to be cheaper vs buying wire and plugs and building it. In keeping with the garish color scheme of the Hendricks PFR3, I bought a lime green cable.

 American Morse KK-2 with cable

Wiring was simple -- first I cut one end off (leaving a couple inches of factory wire, in case I ever need that tip), then I made sure which wires went where on the plug, then I wired them up based on iambic paddle wiring guides online. The outcome is rather nice, I believe:

KK-2 cable wiring

The black wire holder fit the factory cable perfectly. Everything feels solid.

The real question is, how does it work? I'm an absolute beginner when it comes to CW, so all I can say is that it's been a joy to use during my CWOps "CW Academy" training class. The rubber feet you see in the photo leave something to be desired when using the paddle on a Formica desktop. My buddy WB6YOK recommended I cut a mousepad to fit inside the rubber feet, and while I haven't done it yet, the idea has merit. But keying is precise and the device works great. 

According to American Morse, the KK-2 weighs in at 1.5 pounds (24 oz). I haven't weighed it yet, but that seems accurate. As I will be operating in the backcountry as well as from home, having a "mid-weight" unit was important (although I am seriously considering their DCP or Port-a-Paddle kits for lightweight backcountry use).

You can find this paddle online at http://www.americanmorse.com/kk2.htm

Saturday, January 18, 2014

Elecraft T1 Tuner Repair

I've been kind of "radio inactive" whilst sorting out a few things over the last 3 years or so. First time operating in quite a while was back in October up in the Fish lake National forest with my sons. Just prior to leaving, I visited my buddy Chuck to run my gear through its paces. We hooked up my T1 QRP tuner (actually a max of 20 watts) to his FT-897 and my PRC74 military radio whip antenna. I keyed an AM carrier, pressed the tune switch and man--that old military whip tuned up in about 1.5 seconds. Well, that's what I thought... In actuality, I either hit it with too much RF (might have turned down the wrong power settings on the 897) or the tuner just hadn't been used in a long while... Regardless, I fried two diodes. They are barely visible on either side of the right-most torroid on the bottom of this photo. Small blue components aligned horizontally in this snap.


I looked all over and found replacement diodes at Mouser. Ironically, they are fifty cents each, and shipping is $6 (and it's no wonder--my two diodes were shipped in a mid-sized cardboard box!).

I've been stabbing away at desoldering these diodes, but no joy. I'm taking them to my buddy's. He's got a beautiful desoldering station (no joke--I seem to use it a lot). This repair should go quickly! Along wth testing my PFR, we're doing the repair in the next couple days. Hopefully my next post will be of a successful tuning sequence with my 817 and his Gap Titan antenna.

By the way: the trip to Fish Lake wasn't a total bust. That old whip is resonant on 10m (when switched to the antenna's 40m configuration), and 10m was wide open. At 5 watts with right around 1:1.5 antenna matching, I was using PSK to contact France and several US stations. It could have been worse!

73's de K7JTO

Hendricks PFR3 build, groups 1 & 2

If you've read my other blog posts here, you know I'm really interested in light-weight portable operations. That's what led me to buy the Yaesu FT-817, but eventually I realized that was good for park bench or quick day-trip summit work, but it just wouldn't work for a long (3+ days) backcountry hike. 

I reviewed a ton of radios annd came to the conclusion that I needed to learn CW and move to a dedicated QRP rig. After a lot of research, I was about ready to buy an Elecraft KX-1 (http://www.elecraft.com/KX1/KX1.htm). It's highly rated, well-crafted, and quite popular. Then someone turned me onto the Hendricks PFR3 (http://www.qrpkits.com/pfr3.html). The owner of the company was at a QRP meeting listening to someone discuss backcountry QRP operation. An audience member asked what the best rig for backcountry is, and the presenter said it didn't exist yet. He proceeded to list out the features of the dream rig, and Hendricks wrote it all down. He and Steve Weber design, prototyped, and started selling the rig. Not only is it better designed for the backcountry, but it's also much cheaper (the PFR3 currently sells for $240).

About 3 years ago, in 2011, I ordered my kit. I think I sorted the kit the first day I received it, but that's about it. Life got very busy for me, I went through some ups and downs, and now three years later I'm finally building it. In researching the kit, I found there's very little available on the Internet on how to build this rig. If you can't figure it out in the manual, there aren't many resources other than the group. I decided to document the build process so others might benefit.

I am about 4 hours into the build, done with the first two stages.

Basically stage 1 is the LED and power switch. The receiver, stage 2, is most of the right half of the circuit board. The build is very straightforward, except for one item: there's a torrid with a 5-turn primary winding and a 40-turn secondary winding:

I discovered in the course of winding that there is only room for a 40-turn winding, but the manual calls for 40 turns followed by 5 turns. It was all very confusing, until I emailed the PFR3 Yahoo group. A group member clarified: the 5 turns go over the 40 turns. This is probably the least clear portion of the manual.


Another point of conversation: some people have had issues with torroid wires breaking due to the jostling of backcountry travel (shaking in the pack). After discussion with list members, I decided to drop some wax under each torroid. That's what you can see in the shot above. The torroid a are installed on what will be the bottom of the board.


It's difficult to tell, but the radio is powered up and showing 30.0 on the right three digits.


My kit arrived with every component, but unfortunately I lost one of the RF chokes. A list member sent me a replacement. In the lower left of the photo you can see the stock choke--it looks like a fat resistor, just below C42. In the middle of the photo, between the blue and green caps, is the replacement choke. I love the way amateurs help each other out all the time!


Just another random shot of the main board. The kit is very well laid out and goes together quickly--most people estimate 6-8 hours to build. I'm probably 4 hours in, but a lot more considering the head scratching I went through over that torroid!

The manual lists a modification to stage two which address noise in the receiver. It requires two caps to be added--one in a through-hole, and on jumping a couple pins on another component. I was in Seattle on business so I grabbed the components at Frys and installed them with Group 2.

Next step is to dial in the receiver, then build out stage 3 (transceiver). Finally, prep the case and finalize the install.

Monday, March 11, 2013

TrunkTrackerino v .9 finished

OK I can officially put this down for a while! TrunkTrackerino .9 is finally working - I'm recording GPS coordinates and writing them when I have a valid fix. I had issues with the log file, but I've worked those out. All that's left now:
  • Have to fix an issue with the log file time stamp
  • Have to add in logic to sleep when speed ! >= 1
  • Have to slow down the read (it's every .5 seconds right now)
  • Bonus: add logic to put the device to sleep for 5 min when speed !>=.5, to save on battery power
Once those changes are done (and I'm kind of burned out on the Arduino now), then I'm ready to throw this in the trunk of my car and do a little 'applied testing' before I let my boys show me how they manage their driving.

After that, my next addition will be an APRS shield so I can start communicating geo-loc over radio. That is the base bundle for the balloon instrument pack.

Code:
// TrunkTracker sketch combines code from GPSTest_RMC and SD_GPSLogger
// Throw your Arduino in the trunk to see where your teens really go
// and how fast they really drive.

#include "Arduino.h"
//#include "GPSconfig.h"
#include <avr/sleep.h>
#include <SD.h>

// If running Arduino < 1.0, add references to WProgram.h and NewSoftSerial.h
#include "SoftwareSerial.h"

// Set this to 0 when in production; all serial output will be diasabled
#define DEBUG 0

// My shield is wired with RX/TX swapped
//SoftwareSerial mySerial = SoftwareSerial(2, 3);
SoftwareSerial mySerial = SoftwareSerial(3, 2);

// power saving modes
#define SLEEPDELAY 0    /* power-down time in seconds. Max 65535. Ignored if TURNOFFGPS == 0 */
#define TURNOFFGPS 0    /* set to 1 to enable powerdown of arduino and GPS. Ignored if SLEEPDELAY == 0 */
#define LOG_RMC_FIXONLY 0  /* set to 1 to only log to SD when GPS has a fix */

// Set up pins used
#define powerpin 4      // Use pin 4 to control power to GPS
#define led1Pin 5
#define led2Pin 6

// Set GPSRATE to 4800 for my GPS
#define GPSRATE 4800

// Create a buffer of 90 to store GPS data. Usually about 80 chars so 90 is plenty
#define BUFFSIZE 90

// Create an int for iterating
uint8_t i;

// Create instance of logfile
File logFile;

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 10;

// Global variables
char buffer[BUFFSIZE];     // string buffer for the sentence
char *parseptr;            // a character pointer for parsing the GPS sentence
char buffidx;              // an indexer into the buffer
bool fix = false;          // current fix on data
bool gotGPRMC = false;             // true if current data is a GPRMC string

// The time date, location, data, etc.
uint8_t hour, minute, second, year, month, date;
uint32_t latitude, longitude;
uint8_t groundspeed, trackangle;
char latdir, longdir;
char validity;

// Setup the sketch
void setup()
{
  // First set up GPS comms
  if (powerpin)
  {
    pinMode(powerpin, OUTPUT);
  }
  // Use the pin 13 LED as an indicator
  pinMode(13, OUTPUT);
  // connect to the serial terminal at 9600 baud
  Serial.begin(9600);
  // connect to the GPS at the appropriate rate
  // IF THIS IS WRONG for your GPS, change it above
  mySerial.begin(GPSRATE);
  // print title with ending line break
  if (DEBUG)
     Serial.println("GPS Parser started");
  digitalWrite(powerpin, LOW);  //pull low to turn on
 
 
  // Now set up SD for logging
  // This code lifted from "Datalogger" sample sketch
  if (DEBUG)
    Serial.println("Initializing SD card...");
 // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
 // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card init. failed!");
    error(1);
  }
  // Now create a unique file
  strcpy(buffer, "GPSLOG00.TXT");
  for (i = 0; i < 100; i++) {         
    // Keep iterating till you find unique file name
    // Create if does not exist, do not open existing, write, sync after write
    buffer[6] = '0' + i/10;
    buffer[7] = '0' + i%10;
    if (! SD.exists(buffer)) {
      break;
    }
  }
  // Now open the file just created
  logFile = SD.open(buffer, FILE_WRITE);
  if( ! logFile ) {
    if (DEBUG)
    {
       Serial.print("Couldnt create "); Serial.println(buffer);
    }
    error(3);
  }
  if (DEBUG)
  {
     Serial.print("Writing to "); Serial.println(buffer);
  }
  // Done opening log file
}

uint32_t parsedecimal(char *str)
{
  uint32_t d = 0;
 
  while (str[0] != 0)
  {
    if ((str[0] > '9') || (str[0] < '0'))
       return d;
    d *= 10;
    d += str[0] - '0';
    str++;
  }
  return d;
}

// Read line from GPS unit
void readline(void)
{
  if (DEBUG)
    Serial.print("Input from GPS: ");
  char c;
  buffidx = 0; // start at beginning of line
  while (1)
  {
    c = mySerial.read();
    if (c == -1)
       continue;
    // Output status to screen
    if (DEBUG)
       Serial.print(c);
    if (c == '\n')
       continue;
      
    // if we're nearing the end of buffer, terminate
    if ((buffidx == BUFFSIZE-1) || (c == '\r'))
    {
      buffer[buffidx] = 0;
      return;
    }
    // Write each char into buffer
    buffer[buffidx++] = c;
  }
}

// Main program - keep doing this over and over
void loop()
{
  uint32_t tmp;
 
  if (DEBUG)
     Serial.print("\n\rRead: ");
  readline();
 
  // Check if $GPRMC (global positioning fixed data)
  if (strncmp(buffer, "$GPRMC",6) == 0)
  {
    // Set gotGPRMC
    gotGPRMC = true;
    //hhmmss time data
    parseptr = buffer+7;
    tmp = parsedecimal(parseptr);
    hour = tmp / 10000;
    minute = (tmp / 100) % 100;
    second = tmp %100;
   
    parseptr = strchr(parseptr, ',') + 1;
    validity = parseptr[0];
    parseptr +=2;
   
    /*
    // Break out if "validity" = "V"
    if(validity = 'V')
    {
      if(DEBUG)
         Serial.print("\nGPS navigation error. Trying again...");
      return;
    }
    */
   
    // grab latitude & longitude data
    // latitude
    latitude = parsedecimal(parseptr);
    if (latitude != 0)
    {
      latitude *= 10000;
      parseptr = strchr(parseptr, '.') + 1;
      latitude += parsedecimal(parseptr);
    }
    parseptr = strchr(parseptr, ',') + 1;
   
    // read latitude N/S data
    if (parseptr[0] != ',')
    {
      latdir = parseptr[0];
    }
   
    // longituide
    parseptr = strchr(parseptr, ',')+1;
    longitude = parsedecimal(parseptr);
    if (longitude != 0)
    {
      longitude *= 10000;
      parseptr = strchr(parseptr, '.') + 1;
      longitude += parsedecimal(parseptr);
    }
    parseptr = strchr(parseptr, ',') + 1;
    // read longitude E/W data
    if (parseptr[0] != ',')
    {
      longdir = parseptr[0];
    }
   
    // groundspeed
    parseptr = strchr(parseptr, ',') + 1;
    groundspeed = parsedecimal(parseptr);
   
    // trackangle, just 'cause
    parseptr = strchr(parseptr, ',') + 1;
    trackangle = parsedecimal (parseptr);
   
    // date
    parseptr = strchr(parseptr, ',') + 1;
    tmp = parsedecimal(parseptr);
    date = tmp / 10000;
    month = (tmp / 100) % 100;
    year = tmp % 100;
   
    // OK - we've parsed the full string. Now let's print to serial if in debug mode
    if (DEBUG)
    {
        Serial.print("\n\tTime: ");
        Serial.print(hour, DEC); Serial.print(':');
        Serial.print(minute, DEC); Serial.print(':');
        Serial.println(second, DEC);
        Serial.print("\tDate: ");
        Serial.print(month, DEC); Serial.print('/');
        Serial.print(date, DEC); Serial.print('/');
        Serial.println(year, DEC);
        Serial.print("\n\tStatus: "); Serial.print(validity);
       
        Serial.print("\n\tLat: ");
        if (latdir == 'N')
           Serial.print('+');
        else if (latdir == 'S')
           Serial.print('-');
   
        Serial.print(latitude/1000000, DEC); Serial.print("* ");
        Serial.print((latitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
        Serial.print((latitude%10000)*6/1000, DEC); Serial.print('.');
        Serial.print(((latitude%10000)*6/10)%100, DEC); Serial.println('"');
      
        Serial.print("\tLong: ");
        if (longdir == 'E')
           Serial.print('+');
        else if (longdir == 'W')
           Serial.print('-');
        Serial.print(longitude/1000000, DEC); Serial.print("* ");
        Serial.print((longitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
        Serial.print((longitude%10000)*6/1000, DEC); Serial.print('.');
        Serial.print(((longitude%10000)*6/10)%100, DEC); Serial.println('"');
       
        Serial.print("\tGroundspeed: ");
        Serial.println(groundspeed);
       
        Serial.println("Now writing to SD card...\n\t");
        Serial.println(buffer);
    }
   
    // Now log tab separated string
    digitalWrite(led2Pin, HIGH);    // First turn on LED2 to indicate writing to SD
    logFile.write((uint8_t *) buffer, buffidx);  // write the string to the SD card
    logFile.println("");
    logFile.flush();
   
    digitalWrite(led2Pin, LOW);    // turn off LED2 (write to SD is finished)
   
    buffidx = 0;                 // reset buffer pointer
   
    if(fix)
    {
      if ((TURNOFFGPS) && (SLEEPDELAY))
      {
        digitalWrite(powerpin, HIGH); // turn off GPS
        delay(100);                   // wait for serial monitor write to finish
        sleep_sec(SLEEPDELAY);         // turn off CPU
       
        digitalWrite(powerpin, LOW);  // turn on GPS
      }  // if (TURNOFFGPS)
    } // if (fix)
   
    return;
  } // if(gotGPRMC)
   
}

// Handling Errrs HERE
// blink out an error code
void error(uint8_t errno) {
  if (DEBUG)
  {
    /* Need to investigate
      if (SD.errorCode()) {
        putstring("SD error: ");
        Serial.print(card.errorCode(), HEX);
        Serial.print(',');
        Serial.println(card.errorData(), HEX);
      }
      */
     Serial.print("Error writing to SD card. ");

  }

  while(1) {
    for (i=0; i<errno; i++) {
      digitalWrite(led1Pin, HIGH);
      digitalWrite(led2Pin, HIGH);
      delay(1000);
      digitalWrite(led1Pin, LOW);
      digitalWrite(led2Pin, LOW);
      delay(100);
    }
    for (; i<10; i++) {
      delay(200);
    }
  }
}

void sleep_sec(uint16_t x) {
  while (x--) {
     // set the WDT to wake us up!
    WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
    WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1);
    WDTCSR |= (1<< WDIE);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 //   sleep_enable();
    sleep_mode();
//    sleep_disable();
  }
}


 

Sunday, March 10, 2013

TrunkTrackerino

It's simple, really:
I have teens...
They drive my car...
They are boys...
I am an engineer...
I like life hacks...
I have an Arduino...
And a GPS logging shield....

Therefore, TrunkTrackerino.

More than two years ago I started a push to get my Arduino working with the GPS logger shield. It failed, mostly because I had some other life pressures. I recently pulled out my Arduino and started messing with it again, not really sure why... And I got the GPS working. And then I thought... I can build a simple device to throw in the trunk that will record driving speed! And thus TrunkTrackerino was born.

There are sketches for using a GPS. There are also sketches for logging GPS data to a card reader. But I really didn't like any of them individually, so I have merged them together. And as of today, I believe I have it working (not entirely sure, since I'm in my hotel and can't pick up signal--I will know more tomorrow).

The goal is to build an Arduino-based device which
* tracks speed and location
* sleeps when there is no motion
* logs nothing when there's no valid data
* stores data on an SD card
* can be imported into XL to view historical speed data
* can be imported into Google Earth for bread crumb data

Eventually this project will end up as the base for the APRS balloon tracking system. For now, it's enough to know my boys are as honest as they say they are.

Update: I took a brief stroll around the hotel entrance today. For some reason, the logging code is logging an empty file. The GPS is working great--when I watch in Arduino's serial monitor, I can see good valid strings which are being parsed great. I'd say I'm 10 lines of code from a working beta.



Thursday, December 8, 2011

Near Space Balloon

Every once in a while I get a hair-brained scheme that I can actually sell to some unsuspecting person. Like the weather balloon! My son was looking for a science experiment, and I was looking for a challenge. And now we are building a weather balloon.


We will be launching a 1200 gram balloon into near space, sometime between mid-Jan and mid-Feb 2012. Near space is an awesome place... you can see the earth's curvature, elements of the atmosphere, etc. It's really cold out there, too, with temperatures around- 50 C.


We will be sending up one or more Arduino boards in our balloon instrument package, to measure altitude, GPS coordinates, temperature, etc. Our second instrument package will include an APRS solution as well as a 2m radio beacon. Finally, thanks to the generosity of the folks at GoPro, we'll have a GoPro Hero HD on board to record the whole trip.


In this blog, I will be recording our progress. So keep up with it to watch as we design, build, test and launch.


73 de K7JTO


Published with Blogger-droid v2.0.1

Monday, October 31, 2011

Test from Android

It's been a while since I last posted. Life has been coming at me fast! Just a quick test that I can post from my aallAndroid device right now, but more to come.


Published with Blogger-droid v2.0