Monday, July 28, 2008

Getting Ready for Contesting

Slowly talking myself into giving amateur radio contesting a shot.  There is a few VHF/UHF contests over the next few months.  First one is UHF only (which limits me to 70cm) this weekend, which is when I'm up in Portola, but I might stick my mag mount on top of a locomotive and see if I can get anything.  I don't expect to; last time I was in Portola, I called for any station's signal report on all the local repeaters, and got complete silence.  I don't think there is any Hams in Portola, CA...

I also finally got my question answered.  I was wondering that if I made a QSO with a station that wasn't planning on submitting their logs, wouldn't that become a NIL?  Turns out, those are call Uniques, and just look super sketchy.  Thanks K9JY.

Sorry about the lack of posts lately.  Internet has been dialup speed (~3kBps) half the time and I've been busy with school and work.

Thursday, July 17, 2008

Tinkering in Antennas

So all this simplex work lately just pleads for a better antenna.  My workhorse of an antenna is a copper J Pole made out of 1/2" copper tubing, which I'll write about later.  Right now I just want to express my frustration / surprise on the disconnect between SWR and performance.

SWR is the Standing Wave Ratio of an antenna.  As you go from one conductor to another (ie coax to antenna), some fraction of the radio energy is reflected back to the radio, which if bad enough can damage the radio.  It is every antenna designers dream to build an antenna with the longed after 1:1 SWR.

When I built my J Pole, I measured an SWR of 1.8:1, which is passable, yet not great.  Yesterday I slapped together a vanilla dipole using welding rod (whoever mentioned that in his article in the 60s was GENIUS), and first shot I got a 1.6:1.  Great!  An antenna that not only scores better than my J Pole, but is directional too!

Yes, and no.  It is directional.  I can hit a repeater, rotate it 90 degrees, and not hit the repeater.  Good deal.  At the same time, I can plug my radio into the J Pole, and hit the repeater until the cows come home with at least a +1 S reading.  So a better SWR is better for your radio, but a better antenna is a better antenna is a better antenna.

I'm collecting the stock I need to build a Yagi, so we'll see if I can ever top my first attempt.

Tuesday, July 15, 2008

Ground Level QSLs

So surprise surprise, I managed to get KK6BS Joe in Dublin on the horn again tonight (~30 miles), yet at ground level instead of at the top of a hill, so my antenna is working better than I expected it to. One thing I had going for me was he was about 20 degrees clear of our house, so I didn't have our lousy roof to go through.

8:55pm - I also made my first contact with WA6CTP Mike, who thought he was somewhere in SW San Jose, which isn't as impressive, but was still an enjoyable conversation.

9:50pm - KI6KND Dave in Hayward. 22.4 miles north and running a ground plane. I picked him up first on 446MHz, but he couldn't quite copy me on it. After 5-10 minutes, I got a break in the band and we traded a 2 meter simplex channel to move to and we were able to talk fine. Goes to show the difference in bands, and the minute to minute variability in each band's range.

Monday, July 14, 2008

I Love My Dad

Actual phone conversation between me and my father:

Me: "Hey dad, so I got three tickets this weekend."
Dad: "Yeah?"
Me: "Yeah, I got a $35 parking ticket at De Anza, then Sunday night we went up to Rancho San Antonio, and I got another parking ticket, and we all got infractions for being there after hours."
Dad: "You know how much the infraction is going to be?"
Me: "No."
Dad: "Well there's a leason to be learned from this.  You just need to pay more attention to these things.  It's fine though, it's not like the world is ending."
Me: "Yeah...  but there goes my paycheck."

Now there is a few different things going on here that I want you to notice.
  1. I'm paying for it, which really kind of sucks.  I very well might spend as much on citations as my radio costed.
  2. He didn't get mad at me.
  3. Because of #2, it would make sense for me to ever tell him something like this again
I really want you to roll #3 over in your mouth for a while.  How many parents do you know that would just explode, ground the kid, etc etc.  All that is doing is training the kid to not let the parents know what is going on.  I already feel like crap; I just got three tickets in ONE WEEKEND.  Having my dad call it "No big deal" was exactly what I needed to hear. 

Now I'm going to go pay a couple hundred dollars in tickets, and move on with my life.  Ham radio is an expensive hobby, but usually it's the equipment that makes it so, not the citations for doing ham activities.

Expensive QSLs

So last night we were bored, and decided to hike up to Rancho San Antonio to test out my new J-Pole antenna I built a few weeks ago. The antenna worked great, but I got a $35 parking ticket and we all got written infractions because we were in the park after hours.

UPDATE: The infractions came out to be $161 each, which is pretty brutal, but not as bad as I feared.

We setup our antenna in high meadow and got the following contacts on 146.520 MHz/5 watts:
N6KZW (20:58) - 13.3 miles East
KG6GKW (21:02) - 6 miles North
KF6QCH (21:11) - 32 miles North-West (280&101, North of San Bruno Mountains)
KK6BS (21:14) - 29 miles North-North-East (North of the Kilkare Woods mountain range), he was using a 1/4 wave ground plane in a third floor apartment.

So overall we had a pretty successful evening, although not worth the legal fees. Even the farther stations were still coming in S6-S7 (out of 9), so there is still plenty of umph left. There was just a lack of stations listening, since it was rather late to be working VHF. Even the contacts we did get took a good 10 minutes of calling CQ for them to respond.

73 de KI6RLA

Thursday, July 3, 2008

Tying It All Together into a Clock

So after my last few posts, the next step in the project almost seems enevitable.  Combine the Arduino, LCD, and DS1306+ chip together to make a clock.  Of course Jeff was thouroghly involved with this project, as usual.


This project took us about 1.5-2 hours to figure out, with lots of totally random errors that we couldn't explain.

So first off, Jeff wrote up the code to catch the interupt every second and increment the seconds, minutes, hours, and am/pm correctly.  This was pretty easy since I already figured out all the snafus with the DS1306+ chip.  It wasn't quite how I would have written it, but it worked on the first run anyways.

Meanwhile, I was working on trying to figure out the hardware.  The LCD took up almost all the pins on the Arduino, not leaving me much to work with.  We tried moving the Enable pin from 2 to 13 to free up one of the interupt pins, but no dice.  The library was good enough to not usse magic values for each pin, but made many many grave assumptions about which order all of the pins are in, which we never managed to work around.

After hacking on that for quite some time, we dumped the LiquidCrystal library and went with the LCD4Bit library instead, since it only used a 4 bit bus to talk to the HD44780 and happened to not use pin 3, which is the second interupt pin.  Glancing over the documentation yet again screwed me, and I missed the needed grounding of the R/W pin until the very end.  Other than that, it was an almosst complete dropin replacement, with nice features like turning on the second line for us.  We removed the DB0-DB3 lines, and moved forward.

Meanwhile, Jeff was trying to debug the rest of the program, using the serial port instead of the LCD to read the output.  For some reason, calling the half-hacked LiquidCrystal init function in setup() killed the interupt after the first trigger, even though lcd.init() was returning well before the first trigger.  This was never explained and fixed when we switched over to LCD4Bit.

So now for the final moment.  Bring together the last hour of hacking and frustration, and it won't compile.  Hex file .../clock.hex does not exist.  And sure enough, it didn't exist.  we comment out lcd.init(), and it compiles fine again.  Doesn't make any sense.  Eventually, I happened to delete some old commented out code at the bottom that Jeff was using as a reference, and it started compiling again.  No explanation as to why.  That code had been there the entire time.

So now for the features I am most proud of:
The clock is set over the serial line, so you have to plug this clock into your computer to set it (but what fun would a nerds clock be otherwise?).  You just need to send it a string based on how much you want to move it forward.  "hhmmmm" would move it forward 2 hours and 4 minutes.  Sending an "s" just sets the seconds back to zero, as per Jeff's idea.
The display is a preallocated string initialized with "hh:mm:ssnm".  Each time there is an update to the time, each byte is set based on the value/10 or value%10, with '0' added to it to create the correct ASCII code.  I thought this was most clever.

I am planning on adding features to it, namely the ability to set it from the Arduino without a computer and USB cable.  I have 4 I/O pins left, so it will be possible.  Two of them also happen to be PWM pins, which would make running something like a buzzer off them really easy, so there may be alarms in its future.

And for your pained enjoyment, the code in its entirity.  The 1Hz wave is connected to pin 3, Enable to 2, DB4-DB7 to pins 7-10, R/W to 11, and RS to 12.  In the picture above, it is shown running off of a random 12V wall wart I had rolling around on my floor.  Makes more sense than having a clock run off a computer all day.

Code for Arduino Clock:
#include <LCD4Bit.h>

LCD4Bit lcd = LCD4Bit(2);
volatile boolean updated = false; // Used to indicate a new second
char time[] = "hh:mm:ssnm"; // Each byte will be set to display 

    //the time correctly
int seconds = 0;
int minutes = 0;
int hours = 0;
int ampm = 0; // am = 0, pm = 1


void setup()
{
  Serial.begin(9600); // Needed for setting the time over USB
  lcd.init();
  attachInterrupt(1, blink, RISING);
}

void loop()
{
  if (Serial.available()) {  //set the time using the serial monitor
    int inputchar = Serial.read();
    switch (inputchar) {
      case 'm':  // Increment minutes
        minutes++;
        break;
      case 'M':  // Added too many minutes, subtract one
        minutes--;
        break;
      case 'h':
        hours++;
        break;
      case 'H':
        hours--;
        break;
      case 's':
        seconds = 0;
        break;
    }
  }
  if (updated) { // On a new second, add 1 to seconds, and do all 

                //the carrying. Update display.
    seconds = (seconds + 1) % 60;  //update the time when the 

                                  //crystal fires
    if (seconds == 0) minutes = (minutes + 1) % 60;
    if (seconds == 0 && minutes == 0) hours = (hours + 1) % 12;
    if (seconds == 0 && minutes == 0 && hours == 0) ampm = 1 - ampm;


    // Update the string "time"

    time[0] = (hours / 10)+'0';
    time[1] = (hours % 10)+'0';
    if (hours == 0){  // handle the special case of 12, represented as 0
      time[0] = '1';
      time[1] = '2';
    }
    time[3] = (minutes / 10)+'0';
    time[4] = (minutes % 10)+'0';
    time[6] = (seconds / 10)+'0';
    time[7] = (seconds % 10)+'0';
    if (ampm) time[8] = 'p' ;
    else time[8] = 'a';
    time[9] = 'm';
 
    lcd.clear();  // update the LCD
    lcd.printIn("   ");
    lcd.printIn(time);
    updated = false; // Reset the new second flag
  }
}

void blink()  // interupt handler. Name left 

           //over from the AttachInterupt example.
{
  updated = true;
}


Now a Card Carrying Member of the ARRL

So I just mailed off my membership form for the ARRL. The ARRL is the American Radio Relay League, which is pretty much the Ham radio equivalent of the NRA for gun users. The ARRL communicates with the government to protect our rights as Ham operators.

They also have a lot of other perks like an overseas QSL card mailing service, email forwarding from KI6RLA@ARRL.net to my own email address, and a monthly magazine subscription.

Down the rabbit hole I go. Want to come along?

Wednesday, July 2, 2008

Stupid C Book

This is a direct quote from the textbook for my C programming class:
Most programming languages have three strateges for inter-function communication: pass by value, pass by reference, and return.  The C language, unfortunately, uses only the first and last strategies; there is no pass by reference in C. (Computer Science: A Structured Programming Approach Using C 3rd ed. pg. 176)
I just do not know where these people get off.  If passing a pointer isn't pass by reference, I don't quite know what is.  This is all completely insane!  Thank god I'm heading off for Portola in 30 hours.

All I'm going to say is that this programming class is a very good lesson in how to keep my mouth shut.

Initial Work With the DS1306

In my second round of free samples from chip makers, I requested a pair of DS1306+ and DS28CZ04G-4+.

The DS28CZ04G-4+ is a 4kB EEPROM, among other things. I had already requested larger EEPROMs from Atmel, but they haven't been responding to my requests at all, so forget them. Unfortunately, this was a complete bust, based solely on package size (The IC, not mine).

On the other hand, the DS1306+ managed to get out the starting gates without falling flat on its face, due to it being in the beloved DIP package, which fits perfectly in breadboards. It is a real time clock chip, which means it just keeps time. All you need to give it is the standard 32768 Hz crystal, usually found in watches, and it'll sit there and keep time for you. It has a ton of neat features you can access through the serial interface, like it being smart enough to know how many days in each month, and which years are leap years, etc. I just haven't gotten there yet, and have only played with its most basic feature, the 1 Hz square wave.

It's simple: Every second, one of the pins is high, then low, then high on the next second. I then hooked this pin up to one of the interupt pins on the Arduino, so every time the square wave raised from low to high, it triggered an interupt in the Arduino, and called a function. In the example on the Arduino interupt page, it just turns an LED on and off, which was all I really needed for my first trial.


So I wire everything up, load the sketch, and... it kind of works. Every second, the LED flickers and ends up either on or off, almost completely at random, but every second. So we have a bouncing problem. Instead of the Arduino seeing a clean rise (like this: .......''''''''), it sees multiple rises, which triggers the interrupt multiple times (like this: .......'.'..''.'.''''''''). I tried playing around with the standard debouncing software tricks, but had little success.

Luckily, I then happened on another writeup about the DS1306, and all I needed was that first picture at the top. See that brown resistor on the right side? That's what I was missing. The DS1306 doesn't actually generate a 1Hz square wave. It just drains the pin every second. With a pull-up resistor holding the pin normally at HIGH, then the DS1306 pulls it down to LOW when it should be. What I was doing before was letting it float half the time, then the chip pulled it low half the time, which is a big no-no in digital logic. I'm surprised the Arduino didn't see it more like this: ...........''.''.'.'.'.''.............'.'.'.'''.'.''...'.''.............


So long story short, I added a 10k ohm resistor between Vcc1 and 1Hz, and the bouncing problem disappeared completely. I then added a counter to the interrupt function and monitored it through the USB serial port, and the chip kept time to within a second after 30 minutes, which shows there is at least nothing seriously wrong with it.

And the moral of the story is: Data sheets may be 20, 30, or even 300 pages long, but the amount of information they hold warrant that. If you're having problems, before falling into chaotic engineer-solving-problem mode, reread the data sheet one more time.

Tuesday, July 1, 2008

HD44780 Command Codes

Never mind the fact that I've been spending the vast majority of evenings geeking out with Jeff Glass, we've made quite a bit of progress on the Arduino.

After figuring out the pinout on my LCD display on my last post, we then hooked it up to the Arduino, and it worked!  Unfortunatly, it only displayed text on one line, which is no good.  Reading through the data sheet for the HD44780, we realized that there is a ton of different codes you can send the LCD to do useful things (including turning on the second line).  The command code table is on page 24.

The table really isn't very clear, so we spent a lot of time stumbling around, only getting complete garbage on the screen.  Translating from the table's binary representation to decimal values was a pain in the ass, so we first off broke out the good old binconst.h trick to allow us to place binary constants straight in the code.  After futzing around for a while, we think we've figured out most of the command codes and what they do:
  • 12 - Turn off the cursor
  • 24 - scroll the text left, this is good because it's done by the controller and has much less flicker than doing it by lcd.clear(), lcd.printIn(string+1);
  • 28 - scroll the text right
  • 56 - turn on second line.  It divides the 80 byte buffer between the two lines, so to write on the second line, you need to make sure the printIn(string) string is 40 byes long for the first line, then it will print at the beginning of the second line.  How I'm handling this is I have a 40 char buffer for the first line, which I then copy text into, printIn it, then can print whatever I want, and will go onto the second line.
So those were the command codes we found useful.  We didn't bother to figure out how to undo them, since it was just easier to call lcd.init() again.  This is unlikely, but anyone have any of the other command codes out of that ridiculously cryptic table on the data sheet they found useful?