Thursday, May 24, 2018

More Arduino: A Simple Iambic CW Keyer

I've been using the homebrew "TO" style keyer that I described in earlier posts for several months now, and I have to admit that I don't very much like it.  It also reminds me of why I ditched my Hallicrafters TO keyer over 30 years ago:  They don't support iambic mode and are a bit "fiddly" when compared to Curtis-based keyers.  So, I'm working on a replacement that uses the cheap (<$5.00) Arduino Pro-Mini board.

While scouring the web in search of ideas, I came across Ernest, PA3HCM's Simple Arduino Keyer project and was quite impressed, not only by how well it works but by how short and simple his code is.  Bravo, Ernest!

Of course, not being able to leave well enough alone, I had to add a few creature comforts: Adjustable weighting and sidetone frequency.  Ernest's code made that easy enough to do - the timing is based on the value read from the speed pot and the frequency of the sidetone, so with a little bit of manipulation, I was able to modify the code to add a "correction factor" that allows the weight or tone frequency to be changed without affecting the code speed.  It works well, and unlike the old-school "TO" based design, is very forgiving of operator induced timing errors.

Here's the code:

// Simple Iambic Keyer Mod0b3 by N8NM
// Based on the excellent work of Ernest PA3HCM
// May 23, 2018

/*
   Revision History:
   Mod0b0 - Initial build by Ernest PA3HCM with Arduino Pull-up resistors enabled
   Mod0b1 - Added PTT output functionality
   Mod0b2 - Added WEIGHT control, range: 2.25:1-3.75:1
   Mod0b3 - Added TONE control to adjust sidetone freq. Strap to 3.3V line if not using this feature.

   Controls:
   Speed: Sets element length (determines words per minute)
   Weight:Varies dash/dah ratio +/- 25%
   Tone: Adjusts sidetone frequency

*/

#define P_DOT     2                   // Connects to the dot lever of the paddle
#define P_DASH    3                   // Connects to the dash lever of the paddle
#define P_PTT    11                   // PTT output to radio
#define P_AUDIO  12                   // Audio output
#define P_CW     13                   // Output of the keyer, connect to your radio
#define P_SPEED  A0                   // Center pin of SPEED pot
#define P_WEIGHT A1                   // Center pin of WEIGHT pot
#define P_TONE   A2                   // Center pin of TONE pot (strap to 3.3V for fixed freq.)

int speed;                           // Declare variable used in reading speed pot
float weight;                        // Declare variable used in reading weight pot
int tone_val;                        // Declare variable used in reading tone pot
float loop_delay;                    // Declare variable used to calculate audio tone loop delay
unsigned long startMillis;           // Declare variable used to determine PTT delay
unsigned long currentMillis;         // Declare variable used to determine PTT delay
byte PTTSTATE = 0;                   // Declare variable used as PTT status flag

// Initializing the Arduino
void setup()
{
  Serial.begin(115200);               // open UART serial port at 115200 bps
  pinMode(P_DOT, INPUT_PULLUP);       // Enable DIT input with internal pull-up
  pinMode(P_DASH, INPUT_PULLUP);      // Enable DAH input with internal pull-up
  pinMode(P_AUDIO, OUTPUT);           // Enable output for sidetone audio
  pinMode(P_CW, OUTPUT);              // Enable output used to key radio's CW line
  digitalWrite(P_CW, LOW);            // Start with key up
  pinMode(P_PTT, OUTPUT);             // Enable output used to key radio's PTT line
  digitalWrite(P_PTT, LOW);           // Start with PTT off
}

// Main routine
void loop()
{
  speed = analogRead(P_SPEED) / 2;                     // Read the keying speed from potmeter
  weight = (analogRead(P_WEIGHT) * .001465) + 2.25;    // Read the character weight from potentiometer
  tone_val = analogRead(P_TONE) + 330;                 // Read the tone value from potentiometer
  if (!digitalRead(P_DOT))                             // If the dot lever is presssed..
  {
    keyAndBeep(speed);                                 // ... send a dot at the given speed
    delay(speed);                                      //     and add a space following the dit
  }
  if (!digitalRead(P_DASH))                            // If the dash lever is pressed...
  {
    keyAndBeep(speed * weight);                        // ... send a dash at the given speed
    delay(speed);                                      //     and add a space following the dah
  }
  if (PTTSTATE == 1)                                   // If PTT is active...
  {
    currentMillis = millis();                          // ... get the current time
    if (currentMillis - startMillis >= 1000)           // ... and if more than 1000ms has elapsed since last element was sent
    {
      PTTSTATE = 0;                                    // ... clear the PTT flag
      digitalWrite(P_PTT, LOW);                        // ... and release PTT
    }
  }
}

// Key the transmitter and sound a beep
void keyAndBeep(int speed)
{
  PTTSTATE = 1;                         // Set PTT flag
  digitalWrite(P_PTT, HIGH);            // Activate PTT
  digitalWrite(P_CW, HIGH);             // Key down
  for (float i = 0; i < (speed / (tone_val * .002)); i++) // Beep loop
  {
    digitalWrite(P_AUDIO, HIGH);        // Set audio pin HIGH for 1ms
    delayMicroseconds(tone_val);
    digitalWrite(P_AUDIO, LOW);         // Set audio pin LOW for 1ms
    delayMicroseconds(tone_val);
  }
  digitalWrite(P_CW, LOW);             // Key up
  startMillis = millis();              // Start PTT "hang timer"
}


And here's the circuit diagram:
The pot values aren't critical, though linear taper pots should be used for the speed and weight controls and audio (log) taper for the tone and volume.  I'm using 1K, since that's the first thing I grabbed.

Presently, I've got the keyer built on a solderless breadboard, and other than the occasional intermittent connection, it's been a joy to operate.  My Irish/Polish/Catholic ancestry has left me with no natural sense of rhythm, and it's able to mask most of my sending errors!

73 - Steve N8NM

Sunday, April 8, 2018

Arduino - writing and reading a string to/from EEPROM



In my rigs that use an Arduino for control, I like to take advantage of the on-board EEPROM to save the last-used frequency (and other info) so that it's retained over a power cycle.  I didn't do this on my first couple of rigs, and having them power-up to "default" settings bothered me; we're well into the second decade of the 21st century, so why build something that acts like it's from 1980? 

With rigs using the Si5351, this was fairly simple because the frequency data is in long integer format.  With the NiceRF 818 modules I'm using in the Shack in the Box, however, the data is stored as string variables that get passed from the Arduino to the modules as part of a longer AT command string thats sent over a serial connection.

So, what I did was write functions to break each string up, byte by byte, and store the integer value of each byte (they're in ASCII otherwise) to EEPROM. Likewise, reading is done one byte at a time, and each byte is concatenated (fancy way to say appended) to a string holding the "reassembled" data word.

Since others may find this helpful, below is a sketch that writes the string "0123" to the first four slots in EEPROM, then reads and reassembles it back into another string, displaying each step in the Arduino IDE's Serial Monitor as it progresses.

One thing worth mentioning is that the EEPROM has a finite number of write cycles before it gives-up the ghost.  In a rig where you only write to it at power down (or, in the case of the SITB, when storing a VFO to memory), this should never be an issue, but you have to be careful when writing your sketch not to put EEPROM.writes in a loop, else you could burn it up fairly rapidly.  That's the purpose of the "flag" variable in my example sketch:  After one write/read cycle, the flag is set and the loop won't call to the write function until the next reboot.

Anyway, here's the sketch:

/*
   Sketch writing and reading a 4 byte STRING of numerals to/from EEPROM, then printing them in the serial monitor.
*/

#include<EEPROM.h>                                                      // Include EEPROM library

String TestString = "0123";                                             // Declare string variable to be input to sketch.
int addr;                                                               // Declare variable to store EEPROM address.
int flag = 0;                                                           // Declare variable used as a flag to signal loop after write/read cycle completes
String OutputString = "";                                               // Declare string variable to store output from sketch.

void writeeeprom()                                                      // Function to write 4 bytes to EEPROM:
{
  Serial.print(F("TestString = "));                                     // Print input string (TestString) to serial monitor
  Serial.println(TestString);
  for (addr = 0; addr <= 3; addr++)                                     // While addr = 0 to 3, incrementing by 1 each iteration...
  {
    Serial.print(F("In Loop, writing "));                               // ...Print byte being written to serial monitor...
    Serial.print(TestString.charAt(addr));                              //
    Serial.print(F(" To EEPROM Address "));                             // ...Print the address being written to to the serial monitor...
    Serial.println(addr);
    EEPROM.write(addr, (TestString.charAt(addr) - 48));                 // ...The byte will be the ASCII value of the number, convert it to its integer
  }//                                                                   // ...value and write it to the EEPROM.
  Serial.println(F("String written to EEPROM"));                        // Write message to serial monitor when loop completes.
}

void readeeprom()                                                       // Function to read 4 bytes from EEPROM:
{
  for (addr = 0; addr <= 3; addr++)                                     // While addr = 0 to 3, incrementing by 1 each iteration...
  {
    OutputString += EEPROM.read(addr);                                  // Read byte at 'addr' and append it to OutputString...
    Serial.print(F("In Loop, reading "));                               // ...print the byte being read to the serial monitor...
    Serial.print(EEPROM.read(addr));                                    //
    Serial.print(F(" From EEPROM Address "));                           // ...print the address being read to the serial monitor.
    Serial.println(addr);
  }
  flag = 1;                                                             // Set the flag to indicate that we've written and read all four bytes.
  Serial.print(F("OutputString = "));                                   // Print the reassembled string to the serial monitor.
  Serial.println(OutputString);
}

void setup()
{
  Serial.begin(9600);                                                   // open UART serial port at 9600 bps
}

void loop()
{
  if (flag == 0)                                                        // While the flag = 0
  {
    writeeeprom();                                                      //... write to EEPROM...
    readeeprom();                                                       //... then read from EEPROM
  }
}


And here's what is output to the Serial Monitor:

TestString = 0123
In Loop, writing 0 To EEPROM Address 0
In Loop, writing 1 To EEPROM Address 1
In Loop, writing 2 To EEPROM Address 2
In Loop, writing 3 To EEPROM Address 3
String written to EEPROM
In Loop, reading 0 From EEPROM Address 0
In Loop, reading 1 From EEPROM Address 1
In Loop, reading 2 From EEPROM Address 2
In Loop, reading 3 From EEPROM Address 3
OutputString = 0123
 

 

Saturday, March 31, 2018

Shack in the Box: A 2m/70cm FM transceiver

This is a project that I started last year and, after a few weeks, lost interest in it until recently.

During my usual web snooping for interesting parts, I came across these VHF and UHF modules being sold by Nice RF in China.  About the size of three side-by-side postage stamps, each is a complete (except for the low-pass filter and audio power amp) transceiver for the VHF (136-174 MHz) and UHF (400-470 MHz) bands.  The modules are good for about a Watt output, and are programmed serially via a series of AT commands - perfect for interfacing to an Arduino!

The modules are the ultimate black-boxes and contain all of the RF, switching, demodulating, and CTCSS/DCS circuitry, so building this rig has been much more of an effort in programming than it has in building hardware, which is partly the reason that I lost interest in it last May; I had gotten stuck in how to program a few functions and temporarily burned-out.  But, after taking a break from it, I've been making good progress over the past few days.

One of my peeves about many 2m/70cm rigs is that they're not at all intuitive to operate.  My ancient Kenwood TR-7950, on the other hand, is a breeze; even someone unfamiliar with the radio could easily figure out how everything works on it, so I used that as my "model" for the user interface.

Basically, one can either enter the desired frequency via the keypad (VFO mode) or recall it from one of 16 memory channels, selected using the pot to the right of the display.  The display shows the frequency, repeater offset, tone frequency and mode, and also indicates whether the selected memory is in, or locked-out of, the scan list.

The keypad itself is a 16 switch matrix that I purchased from Ebay.  To conserve I/O, I've interfaced it to the Arduino via a resistor divider network, allowing it to be read using only one analog I/O pin.  Likewise, the memory selection is done using a pot and another analog I/O pin.

Serial communication between the Arduino and VHF/UHF modules is done using the "Soft Serial" libraries, which allows using other I/O pins for serial comms and keeps the UART free for programming/debugging.  

Not shown on the VERY INCOMPLETE schematic below is the LCD module, which talks to the Arduino over the I2C buss. 

Cosmetically, I've long been intrigued by the Paraset tranceivers that were provided to the resistance during WWII, so the vague resemblance isn't coincidental.

Obviously, this is still very much a work in progress, so I'll be posting a few follow-ups as things progress.  I just got this to the point to where I've made a few QSOs with it, so I wanted to share it in its raw, al fresco state.

Preliminary (very!) and incomplete schematic - for inspirational purposes only, do not duplicate!!!
 One may wonder why anyone would go through the trouble of building something like this when you can order something like a Baofeng for $30.  That's a valid question, and my answer is simple: Because I can!


Monday, March 19, 2018

Giving A Voice to the $20 Bill - In CW.

It's been said many times that there's nothing like the sound of a direct conversion receiver, and a couple of weeks using the $20 Bill has certainly affirmed that for me, the direct-to-audio experience with a competent DC rig is indeed something special.

But, I didn't get into this hobby just to listen, so it didn't take long (maybe two days) before I started noodling and doodling a transmitter board to install inside the rig.


Being true to the theme of the original rig, I used all common and inexpensive transistors: 2N3904, 2N3906 and a pair of BD-139s in push-pull to deliver roughly 5 Watts when using a 13.8V supply.  Nothing fancy and nothing being pushed very hard makes for a predictable and stable QRP transmitter.

"Splicing" it in to the rig was simple: The VFO from the receiver is "hard wired" to the input of the transmitter, meaning that it is always connected to both circuits rather than switched between RX and TX.  At the other end, I connected a relay at the junction of the mixer and bandpass filter to switch the filter/antenna circuit between the two modes.  Similarly, a relay is inserted between the audio driver and power amps, allowing switching between receiver audio and transmitter sidetone.

A few hundred Hz of VFO shift is needed when transmitting, else people will reply at your zero-beat frequency.  To accomplish this, one set of relay contacts switches a gimmick capacitor in parallel with the main tuning capacitor.  The gimmick is simply a pair of insulated wires twisted together, the number of twists was determined experimentally.

To use the rig as a transceiver, you simply tune stations to the lower side of zero beat, flip the T/R switch and pump the key.  It doesn't get much easier.

Since building the transmitter board, I've made several QSOs and, other than my signal being weak, the reports are that the tone is pure and free of annoying clicks and/or chirp - everything I look for in a CW transmitter.

Simple rigs like this are a blast to operate.  The appliance guys don't know what they're missing!


 

Thursday, March 1, 2018

Cheap and Easy Audio Filter For DC Receivers

I've been having a lot of fun with the $20 Bill rig, it works great, but, as with anything, there's always room for improvement.

When I designed the thing, I was going for simplicity, so the audio bandpass filtering was very rudimentary, basically consisting of the coupling capacitors to limit the lows and a couple of shunt capacitors to roll-off the highs.  I like a wide receiver, but after a few days, even I thought it was a bit too wide. 

My first few efforts used discreet components, but these either proved marginally effective or used more parts than the rest of the rig, so, alas, I broke down and resorted to the magic black boxes.  But, rather than use a modern DSP subsystem, I went somewhat old-school and used an IC that's been around pretty much forever: The LM324.  The '324 is a quad op-amp that's very common and dirt cheap; yeah, there are better parts, but the ol' '724 is good enough for this application.

 There are excellent active filter tutorials elsewhere on the web, so I'll just describe the circuit at a very high level:

Each stage is comprised of a high-pass filter (3.3K in series with .01uF) on it's input, and a high-cut filter (68K paralleled by .01uF) in it's feedback loop.  By cascading eight stages, I was able to get very decent stop-band attenuation; four stages probably would have been perfectly adequate, but more is always better, right? 

Here's what LTSpice says the passband should look like:


Built in the physical realm, it's a bit tighter than that, likely due to the loose tolerances of the parts I used, which is to be expected when the resistors and capacitors cost less than a penny each when bought in bulk.  But, it's good enough!

With any filter, the real test is in listening to it: What's it sound like?  Actually, very nice - it reminds me a lot of the 3KC filter in my SX-101A, very pleasant when listening to SSB signals and more than adequate for casual CW.  My only gripe is that it's a bit noisy, but that may be due to where I have it tacked into the $20 Bill - I inserted it after the volume control, and a better place for it may be at the input to the power amplifier stage.  Maybe I'll try that tomorrow, or maybe I'll do something else.

I'll close with this teaser:  There's another hardware defined transceiver on my drawing board (screen?) and it'll have a very unique architecture - something I haven't seen anyone do before, and there may be a very good reason for that (like, it doesn't work!)
 

Saturday, February 17, 2018

Spontaneous Construction: The $20 Bill, or Oh No, Not Another 40m DC Receiver.

UPDATE: 22 February 2018 - Corrected Schematic
Thank you to Walter, KA4KXX, for kindly pointing out some errors in the "toroid table" at the top of the "Preliminary 2" schematic previously published here.  This has been corrected in the "Preliminary 3" schematic below.

 

This project started last weekend, on a whim after my Grandson, Austin, came over and asked if we could "Make some circuits".  So, I started putting together a low powered audio amplifier and it blossomed into a pretty competent little direct conversion receiver.

If you follow Bill, N2CQR's SolderSmoke blog, you know that he's working on a simple DC receiver of his own, which, along with his aversion to using the magic chips, served as inspiration for this rig, which is how it got it's name: $20 is my guess at what it'd cost to duplicate, and Bill, of course, is Bill.  The alternate name is based on my belief that the last thing the world needs is another 40m DC receiver.


As with most of my other projects, the chassis is bent from a combination of 20ga and 22ga galvanized steel.  I had just enough in my scrap pile to build the chassis and cabinet, which is currently out in the garage while the paint dries.  The decals were left over from the set I purchased from Radio Daze for the Echophone EC-1B.  Waste not, want not.

This is one of my few projects where I didn't steal any circuits from anyone else; I designed it in my head, refined it using LT Spice, and built it Manhattan style, and the thing worked perfectly right out of the gate - the only tweaking that I had to do was some futzing with the inductor in the VFO to get it to cover the entire band.

The circuitry is pretty simple: Signals first pass through a band-pass filter and then hit an FET preamp before arriving at the input of the diode product detector, where they're converted to baseband audio and applied to the audio amplifier string. At first glance, it might appear that I've got way too much gain, but if you look again, you'll see that the middle two stages are feedback amps and don't provide that much gain, but they're very stable and dead quiet.

Also, the audio passband is tailored to start rolling off frequencies above about 2KHz.  I thought about making it tighter, but wanted to be able to use it to listen to SSB; For some reason, I get a kick out of listening to the guys running their state-of-the-art megabuck rigs on a junkbox rig.  

The output stage is a push-pull 2N3904/2N3906 pair that provides a couple dozen milliwatts of power, plenty for headphones and adequate for a speaker if you're using it in a quiet room.

The VFO is a basic series-tuned Colpitts, lightly coupled to a buffer amp and then to a gain amp.  The capacitors are all NPO, and the inductor is wound on a T50-2 core and "hot glued" to the board.  There's a slight drift at start-up, but after 15-20 minutes, it settles down and is more stable than it has a right to be - watching signals in the waterfall of WSJT-X, I see no drift at all over several minutes.  The only magic chip used in the rig is an LM78L05 to regulate the VFO voltage, only because I don't have any suitable Zeners in my junk box.

What really impresses me, though, is how incredibly quiet the receiver is: Put on phones and crank the audio without an antenna and you'd swear that you forgot to turn it on; there's NO background hiss at all - something that's bothered me about my prior DC receiver efforts.  Connect the antenna and you'll quickly reach for the gain pot - signals seemingly jump out of nowhere!

The rig can be powered either from its internal 9V battery or a 12V bench supply.  It is a bit current hungry, drawing about 70mA, which is why I added the provision for external DC power.

As I mentioned, I started this last weekend and worked on it a couple of hours each evening and another 3-4 today, so yes, one can build a practical rig without giving up all semblance of a life outside of the shack.

There's a major CW contest this weekend, and the wall to wall signals make using a DC receiver challenging, it didn't take long to get the hang of using it and was able to make several DX contacts.

I don't often wear a hat, but if I did, I'd tip the brim toward Bill in Falls Church for giving me the idea to build a (mostly) discreet component, hardware defined radio.  I have a feeling that more will follow, but I really need to get back to the SDR-2018 that's sitting here taunting me.

Friday, February 9, 2018

Echophone EC-1B: Finally finished!

Finished - for the second time.
Let's start this post with a tale of woe:

I actually had this thing ready to go early this week, but, since it'll be a gift for my grandson and subject to abuse, I wanted to shoot a couple of coats of clear over it to give it some protection.  My idea an intention were both good, but my execution sucked wind!  Which leads to the last statement in my last post:

Don't use lacquer over enamel.

I've known this for some time, but have been successful in cheating fate through multiple test-sprays over well cured enamel base, and abandoning the thought if there was any sign of an adverse reaction.  I did that with this radio and, by all indications, it looked like it'd be OK.  It wasn't...

Within a few minutes, my previously perfect hammer-tone finish had severely wrinkled in spots.  Dammit!  Oh well, nothing else to do but strip it down and do it over - this time clearing with a compatible product.

Paint-wise, the second effort turned out better than the first, but my decal application wasn't as good.  But, it's adequate, so I'm not going to mess with it.

I can't help but be impressed by the performance that they were able to wring out of such a simple circuit.  Assuming it's intended purpose was casual shortwave broadcast listening, it's remarkably adequate.  For amateur use, though, it's challenging. 

In developing the specifications for the original Zenith Trans-Oceanic, Commander MacDonald insisted that one shouldn't need "micrometer fingers" to tune the thing.  With this set (and the S-38s), such digits definitely come in handy, especially when tuning SSB signals.

But, once you calibrate your fingers, it's completely possible to tune SSB stations.  It's not easy, but it can be done.  I did incorporate one simple modification while re-working this set to aid in CW/SSB reception:  When in "CW" mode, the original design defeats the AGC by putting the cathode of the IF tube right to ground.  This sets the gain to maximum, which causes strong signals to "override" the BFO.  Replacing the short-to-ground with a 470 ohm resistor reduces the gain just enough to where 90% of the signals can be resolved without "overriding" the BFO.  Cool!

Weak points?  Well, these were designed to be cranked-out as cheaply as possible, so they suffer from mechanical instability.  The dial resolution is vague, and, the IF filtering is quite broad.  Again, perfectly fine for casual AM SWBC listening, not so much for CW/SSB.

Other than my epic paint failure, this has been a fun project and I'm actually having a lot of fun dialing around the bands with the little fellow.  So much that, since I'll be giving this one away, I'm going to look for another one for myself!