Posts Tagged ‘ DDS ’

Arduino – Si5351 Powered Signal Generator

Arduino-Si5351 Signal Generator

Arduino-Si5351 Signal Generator

Device Description

For a long time I wanted a general purpose signal generator. Now Direct Digital Synthesizer hardware is available on a single programmable chip. The Analog Devices AD9851 is used in many ham radio projects, also widely used is the Silicon Labs Si5351. Either of these can be obtained from many sources such as Adafruit, Sparkfun, or on EBay and there’s lots of information on the internet. Even Amazon has them. A few dollars gets a DDS chip that will tune continuously from audio to VHF mounted on a small breakout board. I purchased an Si5351 board from Etherkit because they offer a version with a TCXO.

Silicon Labs makes the Si5351 in several variations. It’s intended use is as a multiple output clock generator with up to eight individually programmed frequencies. Most commonly available breakout boards though, use the A version with three outputs. Digikey has the bare chips for less than $1. Connectors are optional, most boards are set up for SMA female jacks. The signal generator I built brings out all three outputs but I used good old RCA phono jacks. SMA connectors are wonderful but the cables to use them are pricey. My box will be used to check and align receivers so precision impedance control is less important.

AD9851 chips have a real Digital/Analog converter on board, it uses an amplitude lookup table to produce a fair sine wave. The data sheet says:

“The AD9851 uses an innovative and proprietary angle rotation algorithm that mathematically converts the 14-bit truncated value of the 32-bit phase accumulator to the 10-bit quantized amplitude that is passed to the DAC. This unique algorithm uses a much-reduced ROM look-up table and DSP to perform this function.”

which sounds suspiciously like the quarter wave sine synthesis I experimented with a few years ago. I’ll have to revise my WordPress pages about quarter wave DDS techniques to include the phrase “angle rotation algorithm”. The price for pure sine wave complexity is, the device has only a single output. In contrast, the Si5351 outputs a square wave on all it’s ports – it is intended to serve as a programmable frequency clock source but for my purposes I don’t care and the available multiple outputs are attractive.
I breadboarded the Etherkit breakout along with one of Paul Stoffregen’s Teensy-LCs I had on hand for the controller. A Teensy-LC has an ARM Cortex M0 heart clocked at 48 Mhz. An ordinary 16 Mhz Arduino would probably work in this circuit but would have trouble with sweep. I used basic software from N6QW to get started and my oscilloscope soon showed it was working. Then a series of enhancements to the N6QW sketch followed:
  • expand to controlling all three outputs
  • setting up frequencies using rotary encoder and LCD menus
  • save and restore setup in EEPROM
  • add output power change to the menus
  • add  output OFF to the power menu
  • add sweep capability with menu control

The Box

A thin metal gift card box was cut up to form an enclosure for the generator. It is about a quarter inch larger than the usual Altoids tin in all three dimensions. I needed the extra volume to fit in a battery and charger removed from a cheap phone power pack. These booster packs usually contain a single 18650 cell and it just fits.

Arduino-Si5351 Signal Generator Interior

Arduino-Si5351 Signal Generator Interior

The components are, top to bottom, blue 16×2 LCD board supporting the Teensy-LC. The entire unit can be 5 volt powered either from the Teensy USB jack or from the battery charger, I added a fat diode to isolate the two sources.  Both the Teensy and the Si5351 board are using their on board voltage regulators. The LCD is five volt, but the Teensy-LC does not have 5 volt tolerant inputs. There are 2.2k resistors between the LCD data pins and the Teensy to smooth over that discrepancy, these would not be necessary if the LCD was a 3.3 volt unit. The pot below the Teensy adjusts the LCD contrast.
At left below the LCD is the Adafruit (Bourns) rotary encoder. It just clears the battery. Right of the encoder is a strip of perf board with the three output select pushbuttons mounted. The LCD, encoder and buttons are Adafruit parts.
At the top of the open box bottom is the salvaged 18650 cell. The measured drain of the whole circuit is less than 100 milliamps so the battery should last half a day at least. The gooey glob at the center is a 2.5 amp fuse. To the right of the battery is the on/off switch and isolation diode. The salvaged Lithium charge/boost circuit is the green board at bottom right. It has it’s own separate USB jack because the USB data leads are not accessible. To program the unit you have to plug into the Teensy USB jack.
Finally the blue board in the bottom is the Etherkit breakout. The actual Si5351 chip is at the left end, next to the TCXO. There are three RCA output jacks mounted in the left side of the box, the fourth jack next to the handle is for syncing the scope when sweeping.

Operation

On power up the unit reads saved frequency settings from EEPROM. The display then shows frequency, current port selected, and the output power setting.

Click one of the three buttons to change the port selected to display on the LCD.

Rotating the encoder knob will change the frequency digit under the flashing cursor. Press click the encoder knob to change the digit under the cursor, you can set the cursor to change digits from 1 Hz to 10 MHz.

Hold one of the port select buttons down and turn the encoder knob to change output power for that port. The chip has choices of 8 milliamps, 6 mA, 4 mA, 2 mA, and OFF. Silicon Labs’ spec for driver impedance is 50-85 ohms.

If any of the above settings are changed, the software waits ten seconds, then copies the current settings into EEPROM. In the event the unit gets confused, it can be restored to last saved settings by cycling the power switch. Also it can be returned to default settings by holding down all three port select buttons, while powering up.

Arduino-Si5351 Signal Generator Frequency/Power

Arduino-Si5351 Signal Generator Frequency/Power Setting

 

Sweep Function

Sweep is accessed from a separate menu. Press down the encoder knob for more than two seconds (a long press) and release to enter sweep parameters for the currently selected port.  A short click of the encoder knob will advance the menu through the sweep choices, currently +/-  0, 1000, 5000, 15000, 50000, or 150000 Hz. The unit sweeps from frequency minus that amount to frequency plus that amount so the total width of sweep is twice the setting. Sweeping is done by reprogramming frequencies in 20 steps between the limits.

A second long press of the encoder knob will return to the frequency menu. The letters “sw” appear on the LCD to indicate that that port is set up to sweep. All three ports can be set up but only the port currently selected in the display will be sweeping at any given time.

A pulse is available at a phono jack on top of the box to trigger an oscilloscope at start of each sweep iteration.

Sweep parameters are not currently saved in EEPROM.

Arduino-Si5351 Signal Generator Sweep

Arduino-Si5351 Signal Generator Sweep Setup Screen

 

The Software

I am using the Si5351 library from Etherkit. I added a function to completely disable the output drivers to save battery when a port is set to “OFF” so I will include the library in the zip file.
Most of the sketch, implementing multiple port and the menus, was straight forward. The one thing that gave me fits was the quadrature nature of the rotary encoder. This is a mechanical switch and it glitches. Not a problem if you are say, setting an analog output from 0 to 1023, you probably wouldn’t notice but if you need to change a digit by exactly one, glitches are intolerable.  Conventional debouncing a switch usually just waits a certain amount of milliseconds after a transition is detected, read again and proceed. There are debounce libraries for doing this. I had no luck. I finally found an post by Oleg Mazurov about treating the quadrature pulses as a Gray code. It helped a lot and I posted about my findings in the Adafruit Feather forum.
The Adafruit rotary encoder outputs four state transitions on each of it’s 24 rotary detent positions. To get one increment per detent, I tried skipping four state reads with a software counter but it was still glitching if the knob was inadvertently touched. What finally worked was changing the Gray code decode table to disallow all but one positive change and one negative change. The allowed changes remaining are in the middle of the detent so glitches near the resting position are unlikely.
Sweep is accomplished by reprogramming a port frequency on the fly. Tests indicate this is slow and the 20 step sweep takes about 65 milliseconds which limits the sweep rate to about 15 per second. I found a very good way to time something is to write a 1 to some output pin at the beginning, then write a 0 at the end. It’s easy to see exactly how much time the intervening code took by measuring the pulse on an oscilloscope. The send_frequency function takes 3.5 milliseconds. Looking at the Si5351 library, the set_freq code is long and complex. It might be possible to speed this up by using the set_freq_manual call but I’m not smart enough to do that. Porting this code to a 16 Mhz Arduino might make the sweep unusably slow.

Addendum April 4, 2018: Amplitude Modulation Experiment

I thought I might try generating an AM modulated signal by summing three generator outputs.  A 1.1 MHz signal modulated  at 1 KHz would have a 1.100 MHz carrier, a 1.101 MHz upper sideband at half the carrier amplitude, and a 1.099 MHz sideband at half the carrier amplitude. I breadboarded a resistive combiner as follows:
Resistive Combiner

Resistive Combiner

The Si5351 was set to equal drive power on all three outputs.  I examined the output on the oscilloscope, channel 1 connected to AM Out, channel 2 to Audio Out with sync taken from Channel 2. The result is not encouraging. It does output an amplitude modulated signal but the waveforms are bizarre. I see a blocky square wave changing at a 1000 Hz rate but there is some phase problem I can’t control.  This is the best I could capture:

AM Modulated Signal

AM Modulated Signal

Connecting an audio amp and speaker does show a 1 KHz tone if the phases happen to line up just right. I found that setting any one of the generators to be one Hz off frequency results in a rolling pattern with about a one per second beat note in the speaker.

This method of faking Amplitude Modulation is certainly not precise or controllable. Setting one of the outputs off frequency by a few Hz does give a useful warbling tone in an AM receiver.

Files

A zip archive is available including sketch source, the Si5351 library, and a schematic
Jan 4, 2018 V1.1 including the sweep function
 Jan 5, 2018 V1.11 Sweep bug would not change freq while in sweep mode. Cleaned up schematic.
https://www.dropbox.com/s/hk7nc063ipjisr7/SignalGenV1.11.zip?dl=0
Advertisements

Still More Fun With Direct Digital Synthesis: TeensyLC with DAC

I posted a link to my previous page on setting up PWM Direct Digital Synthesized sine waves on PJRC’s Teensy 2.0, a 32u4 Arduino. Paul Stoffregen (the PJ in PJRC) commented that I should try porting my DDS demo sketch to a TeensyLC. “You won’t need PWM” he said. “Use the Digital Analog Converter” he said. I was a bit hesitant because TeensyLC has an ARM processor running at 48 Mhz. Quite a bit more power than the Atmel 16 Mhz chips and more I/O capability, so worth a look.  PJRC supplies an Arduino IDE add on called Teensyduino which configures support for PJRC boards so simply doing an analogWrite to pin A12 (took me a while to actually find A12) starts the DAC instead of starting PWM. Teensyduino has an included library IntervalTimer which sets a repetitive timer running and attaches that to an Interrupt Service Routine which you supply.  So an LC port should be simple as the dirty work of configuring the timer is taken care of.

Arduino PWM based DDS uses a fixed sample rate of 31 or 62 Khz and the interrupt generated sine wave has to fit into that constraint. That means low frequency audio tones are relatively smooth as there are lots of sample periods to go around even with the 256 step tables. High audio frequencies on the other hand, suffer distortion as the shorter period audio wave can’t fit in enough sample periods.

In the TeensyLC, the DAC always gets a fixed number of bits so you change the interrupt frequency to change the frequency of the generated audio tone. For instance, using the 256 step table, to generate a 1000 Hz tone requires 1000 * 256 interrupts per second. That’s about one every four microseconds, which even with the 48 Mhz processor clock, is going to use a LOT of CPU time. The shortest period I could set with IntervalTimer was 5 microseconds, my experiments with the demo program showed a maximum audio frequency of 650 Hz with the 256 step table, the 128 table limited at 1300 Hz, and the 64 step table maxed out at 2600 Hz.

Another down side to the DAC method stems from the fact that the audio frequency granularity is determined by the 1 microsecond granularity of the IntervalTimer function multiplied by the number of steps in the sine table.  The demo program shows this while sweeping. Low audio frequencies sweep smoothly but the higher frequencies have very noticeable jumps. Higher sine table sizes show this effect much more.

But the output wave form is much better than PWM. The following photos were shot using the Quarter Wave symmetry version of the demo sketch. Full table version traces were identical. All these were taken at a set audio frequency of 440 Hz. The filter was a single 10K resistor in series with the output pin, and a 0.01 ufd capacitor to ground. You can see the wave period changing a bit with the different table sizes. That is due to the granularity issue.

TeensyLC DAC Bottom - Raw, Top - Filtered 256 Step Table, Quarter Wave

TeensyLC DAC Bottom – Raw, Top – Filtered
256 Step Table, Quarter Wave

 

TeensyLC DAC Bottom - Raw, Top - Filtered 128 Step Table, Quarter Wave

TeensyLC DAC Bottom – Raw, Top – Filtered
128 Step Table, Quarter Wave

 

TeensyLC DAC Bottom - Raw, Top - Filtered 64 Step Table, Quarter Wave

TeensyLC DAC Bottom – Raw, Top – Filtered
64 Step Table, Quarter Wave

 

TeensyLC DAC Bottom - Raw, Top - Filtered 32 Step Table, Quarter Wave

TeensyLC DAC Bottom – Raw, Top – Filtered
32 Step Table, Quarter Wave Symmetry

 

TeensyLC DAC Bottom - Raw, Top - Filtered 16 Step Table, Quarter Wave Symmetry

TeensyLC DAC Bottom – Raw, Top – Filtered
16 Step Table, Quarter Wave Symmetry

I will probably use the TeensyLC in my next version of morse keyer.  I have to find a 16×2 LCD that will work at 3.3 volts, figure out how to interface a 5 volt PS2 keyboard, and how to charge and connect a 5 volt battery pack. The LC (and the 32u4) have USB serial built in which will make interfacing a terminal window on a logging computer a lot easier.

I found a useful web page showing how you implement quarter wave sine symmetry DDS on an FPGA and I took this opportunity to streamline the quarter wave ISR. You have to be familiar with bit banging to understand it now.

The demo sketches, full table and quarter table versions, and the Libre spreadsheet I used to develop the quarter wave half step offset tables are included in the archive at:
https://dl.dropboxusercontent.com/u/40929640/ArduinoSineSynth/TeensyLC_DDS_Demos.zip

Arduino Based Iambic Keyer(s)

Version 1.0 – ATTiny85 Port

Richard Chapman KC4IFB published an article in the Sep/Oct 2009 QEX magazine (subscription required) for constructing an Iambic Keyer on the Arduino platform. I downloaded his code from the QEX web site (ARRL membership required) and found it worked well.  I have not been active in Ham Radio for years and my morse code is seriously rusty, so I decided to build a keyer for practice purposes and maybe to use on a real radio some day when I figure out how to get an antenna up on this small lot.  I have a WB4VVF Accu-Keyer I used with my homemade paddles long ago.  I bought the PC board from WB4VVF himself at the Dayton Hamvention.  Chapman’s keyer implementation on the Arduino Uno felt exactly the same and I had no problem getting used to it.

I wanted to see if this code would run on an ATtiny85 chip. These are beautiful little microcontrollers in an 8 pin DIP package. They have 8K of internal flash memory and with a minor bit of library downloading, are programmable via the Arduino IDE.  There is a catch though, tiny85 does not normally have bootloader code like a formal Arduino does so you need additional circuitry to burn your sketch onto the little chip. In July 2013 Jim Williams from Workshop 88 in Glen Ellyn conducted a class in tiny85 programming which I attended. At the end of the class we all had our own Arduino ISP adapter board and could burn a tiny85 by using an Arduino UNO as an intermediary.

I amped up my ISP adapter by adding a ZIF socket. It also can program the ATMega328 chips by moving five jumpers.

ISP programmer for ATtiny85 and ATMEGA328 microcontrollers

ISP programmer for ATtiny85 and ATMEGA328 microcontrollers

With the ISP programmer working, I was ready to work on the tiny85 port.  I found Chapman’s code worked but there was no side tone generated.  After a few hours debugging I noticed Chapman’s code was turning the tone on in every iteration of loop(). The tiny85 did not like that. I just added a flag so tone was turned on once, then left on, and the tiny85 port was working 100%. In the end, a very minor change.

I wanted SMALL so I added code to eliminate the speed potentiometer. In my version, you hold both paddles closed for 5 seconds and it goes into speed set mode. Dots increase the speed and dashes decrease.  Another five second Iambic squeeze and it goes back to normal mode.  Also I added a Straight Key mode. If a two conductor instead of a three conductor plug is inserted in the paddle jack it will just beep out what it sees on the dot paddle.  Good for code practice with my J38 if I can remember where I put it.

Source code for the ATtiny85 port is here. This is the finished Keyer in the mandatory Altoids enclosure (but note SMALL Altoids):

Atmel ATtiny85 based Iambic Keyer

It was a challenge to get everything in there and still have the lid close.  The speaker is from a defunct greeting card but rest of the parts were purchased from Jameco. In the end, the most expensive single component was the Altoids mints from the drug store.  The ATtiny85 chips are less than a dollar if you buy ten.

There are these few parts required:

  • speaker and 22 ohm resistor
  • 2032 battery and holder
  • two 3.5 mm jacks, one output, one paddles
  • three bypass capacitors
  • Dropping resistor and LED
  • Power switch
  • ATtiny85 chip and 8 pin socket
Interior of ATtiny85 Iambic Keyer.

Interior of ATtiny85 Iambic Keyer.

There is a short video of the keyer in action here.  So now if I spend a few minutes every day practicing I might get back to the 13 WPM I had to do to get my current license.

Version 2.0 – ATMega328 with Memories

Richard’s QEX article suggested several possible enhancements. I thought adding memories would make the device much more useful so began another journey into Arduino programming. Yes, I know there are already Arduino keyers out there. The K3NG implementation has a ridiculous number of options, but I wanted to do my own based on Chapman’s sketch in the most efficient manner possible. A schematic drawing of my completed keyer is available, and I have written a description of the functions. Source code for the sketch is here.

The PS2 keyboard requires +5 volts so I designed around a five volt Sparkfun Pro Mini board. Only ten bucks! Available here or here. The Pro Mini has an on board 150 milliamp capacity 5 volt regulator if you use a 7-12 volt power supply.

Features in the keyer sketch now include:

  1. Memory or keyboard characters are buffered in an asynchronous circular queue so memory buttons or keyboard characters can be “typed ahead”.
  2. PS2 and serial terminal keyboards supported.
  3. Paddle generated morse is interpreted and printed as ASCII letters on the serial terminal.
  4. Four programmable memories with 50 character capacity each.
  5. Memories programmable from the keyboards or from the paddles.
  6. Random code practice modes, letters, letters and numbers, letters, numbers, and punctuation.
  7. Sending speed settable 10 to 45 WPM. Limits can be changed by recompiling.
  8. Sidetone frequency settable 100 to 1500 hz. Limits easily changed by recompiling.
  9. Commonly changed default settings are in a separate header file (Canned.h).
  10. Message strings, sending speed, and sidetone frequency are stored in EEPROM and easily reset to defaults.

The sketch requires five I/O connectors:

  1. A 3 conductor jack for the paddle or straight key. Connect dot paddle to tip, dash paddle to ring. Use a 2 conductor plug for a straight key in the same jack.
  2. A 3 conductor jack for transmitter keying. A 2N2222 open collector output is on the tip. Line level sidetone is connected through a 5k resistor to the ring so you can connect an external amplifier if you need louder audio.
  3. A power jack for either a 5 volt or 7 -12 volt wall wart supply. Consult the Sparkfun documentation for which Pro Mini pin to use for power.
  4. A six conductor mini DIN connector for the PS2 keyboard. See Canned.h for information on the four leads needed.
  5. A connection for programming, and TTL serial terminal through an FTDI adapter. This can also power the unit instead of the wall wart.

There are six push button switches and a volume control needed:

  1. A reset button for the Arduino.
  2. A Function button.
  3. Four push buttons to activate individual memories.
  4. The volume control feeds a one transistor buffer for the internal speaker. It does not affect the level on the line output connection.

Operation:

Pressing reset momentarily has different effects depending on what other switches are closed. A processor reset normally takes a few seconds, when finished three mid tone beeps will be heard.

  • Press the reset button alone to restart the Arduino. This is also the only way to exit code practice mode.
  • Press the reset button while holding the function button down until three low tone beeps sound will restore the four message memories and code speed to defaults. Default messages, speed, and sidetone frequency are set at compile time from the file canned.h. You must do this action when loading the sketch for the first time into a new Arduino to initialize the EEPROM.
  • Press the reset button with a 2 conductor straight key plug inserted and the keyer enters straight key mode where the sketch generates tone and output simply follows the key closures.
  • Press the reset button while holding down one of the memory buttons starts random code practice. Characters will be generated in five character groups and echoed on the serial port.
  1. Memory 1: letters only
  2. Memory 2: letters and numbers
  3. Memory 3: letters and numbers
  • Pressing reset while holding Memory 4 enters sidetone frequency set mode. The dot paddle increases frequency, dash paddle decreases. Press M4 again to exit set mode.

The function button has three duties:

  • Reset to default messages as mentioned above. You must hold the function button down until you hear 3 low tone beeps.
  • Holding function alone down triggers speed change mode. While function is held, the dot paddle increases speed, dash paddle decreases speed.
  • Holding function down and then momentarily pressing a memory button allows programming that memory. After programming, press function again to return to normal.

New memory messages may be entered from the PS2 keyboard, the serial port keyboard, or from the paddles.

Pressing a memory button by itself transmits the programmed message.

Serial or PS2 keyboards have a command mode, entered by typing a back slash followed by a single character. Commands implemented are:

  1. \+ increase sending speed one Word Per Minute
  2. \- decrease sending speed one Word Per Minute
  3. \u increase sidetone frequency by 5%
  4. \d decrease sidetone frequency by 5%
  5. \w save current sidetone frequency and WPM to EEPROM memory
  6. \1, \2, \3, \4 send a message as though a memory button was pressed.

The keyboard translation table (AtoM.h) includes all the characters shown in the Wikipedia article on Morse Code except the underscore and the dollar sign. Typing an unsupported character echos “x” on the serial port and will be ignored by the morse interpreter.

Version 2.0 Hardware Implementation

Here is a photo of my 2.0 construction. There are three jacks on the left for power, paddles and transmitter keying. PS2 keyboard jack on the right, small volume control and send monitor LED on the front. Not visible is the six pin serial connector on the rear.

On the lid of the S.A.E. you can see a small speaker through the holes around the center. Round holes were made with a heavy duty paper punch. For buttons, I used 6 mm square through hole PCB mount switches with four pins, the kind everybody uses on their solderless breadboard. I bent the pins on one side back so they could be soldered directly to the Altoids lid. Quarter inch square holes for the buttons were punched with a hollow chisel mortiser bit which worked quite well.  I made labels by placing the lid in a scanner, adding text to the scan in GIMP, then printing a 1:1 image of the labeled lid on photo paper. I cut the letters out and glued them to the Altoids lid. This technique produces text labels with the original Altoids artwork underneath. I coated each label with clear nail polish for protection.

Arduino Memory Keyer Exterior

Arduino Memory Keyer Exterior

With the box opened you can see the small Sparkfun Pro Mini board. It is mounted by a pair of L shaped wires cut from a paper clip. These are soldered in the Mini’s two ground pins and then soldered to the Altoids tin. A rectangular hole in the back of the tin provides access to the six pin serial connector. All the in use Arduino inputs have 9.8 k pull up resistors added, and are bypassed at the switch with a small capacitor. The outer end of the pullup resistors are soldered to a narrow bit of PC material wired to Vcc.

Three jacks on the left are epoxyed in place. The PS2 jack on the right, which was salvaged from a defunct USB-PS2 adaptor, is held by a narrow copper strap soldered to the jack and to the Altoids tin. A small perf board at the front holds most of the ancillary components for keying and the audio control. I mounted the perf board using more stiff wire cut from the paper clip.

There is a strip of thin PC material laid across the button switches to add more physical support. The two switch pins not soldered to the Altoids lid are bent over the strip and soldered. Notches filed in strategic places across the copper isolate each switch, and I added the necessary 0.1 uFd capacitors at this point.  The speaker is tucked under one of the PC strips and epoxyed in a couple of places. A short piece of flexible solder wick bonds the box lid to the bottom.

Arduino Memory Keyer Interior

Arduino Memory Keyer Interior

Future Enhancements

Add a FTDI USB to Serial adapter inside the box. It would allow a more graceful connection to a host computer running a serial communication program. Or build another unit with a USB integrated chip.

Add a 16×2 LCD display. Code would be trivial, but will probably have to find a bigger box.

Expand to six or eight memories. My sketch is compiling in about 13 k of flash, and has over 1500 bytes of ram free plus the Pro Mini has eight analog inputs so easily done. But how many memory messages can the average ham keep track of? I think four is a good number and I love the Altoids tin paradigm.

Credits

Many thanks to Richard Chapman KC4IFB whose February 2009 QEX article provided the inspiration and base for this sketch. His iambic keyer sketch feels exactly like my original WB4VVF Accukeyer. A version of his sketch with instrumentation added so you can see the state changes is here. Also see Rarons Blog  for a discussion of the tree method for decoding and encoding morse characters. Would you believe 300 WPM full duplex?  I did not use his library but his work was very helpful in building efficient translation tables. The circular queue was implemented with help from examples from the Embedded Systems Journal.

Revision History

V2.0.0 Initial coding to implement fully asynchronous event loop.
All delay() and spin waits removed from the main loop path.
Remove numbers only practice. Change eeprom order. Add change sidetone.
https://dl.dropboxusercontent.com/u/40929640/ArduinoMorseCode/MemoryKeyerV2.0.zip

V2.0.1 Minor tuning space generation in doIambic.
https://dl.dropboxusercontent.com/u/40929640/ArduinoMorseCode/MemoryKeyerV2.0.1.zip

V2.0.2 Converted sidetone generation to DDS/PWM sine wave with help from
http://ko7m.blogspot.com/2014/08/direct-digital-synthesis-dds.html

https://dl.dropboxusercontent.com/u/40929640/ArduinoMorseCode/MemoryKeyerV2.0.2.zip

Quarter Wave Symmetry

Quarter Wave Symmetry
1000 Hz 256 Step Table

V2.0.3 Changed sine table to half step offset. Saves one byte.
https://dl.dropboxusercontent.com/u/40929640/ArduinoMorseCode/MemoryKeyerV2.0.3.zip

V2.0.4 Added sidetone envelope shaping. Required several other changes.
https://dl.dropboxusercontent.com/u/40929640/ArduinoMorseCode/MemoryKeyerV2.0.4.zip

Shaped Dits at 45 WPM

Shaped Dits at 45 WPM

V2.0.4.1 Bug fix was dropping dits on a long string of upper case “H”s. Disable interrupt while changing sine tables.
https://dl.dropboxusercontent.com/u/40929640/ArduinoMorseCode/MemoryKeyerV2.0.4.1.zip

V2.0.5  Changed AtoM table from prog_uint16_t to char to save memory, which created bug where setup does gratuitous write to A6 and A7. Fixed problems when compiling under Arduino IDE 1.6.1, did not accept typedefs in pgmspace.h. Fixed bug in initByte, 1.6.1 did not like  aaByte = aByte -= 0x20;  Compiled size is 2k smaller in 1.6.1 and no more bogus compiler warnings!
https://dl.dropboxusercontent.com/u/40929640/ArduinoMorseCode/MemoryKeyerV2.0.5.zip

April 30 – Have not changed the V2.0.5 sketch but did redo the audio section of the Altoids keyer. I found the single transistor audio buffer was not satisfactory, distorting badly when driven by a sine wave. Also it was drawing 50 milliamps at idle. I removed the transistor and connected an LM386 amplifier – much better sound and very little current draw when idle. A revised schematic is at:
https://dl.dropboxusercontent.com/u/40929640/ArduinoMorseCode/MemoryKeyerV2.0.5Schematics.zip

Notes

20 March 2015  —  The keyer sketch was developed with Arduino 1.0.6. Recently I downloaded the latest Arduino IDE 1.6.1 and discovered the keyer sketch will not compile. It appears the newer version of GCC will not accept the typedefs used in the pgmspace.h library. I will upload a 1.6.1 release as soon as I figure out what’s going on. FIXED see V2.0.5 above.

24 March 2015  — Was shopping in Frys and bought an inexpensive (< $3) adaptor, is USB A female to PS2 male, is about the same size as the two connectors placed end to end.  It was made by Shaxon Industries in guess where. To my complete surprise it works. Using the adaptor I can connect any USB keyboard to the keyer which is good news, as PS2 keyboards especially compact ones, are getting hard to find. I measured power supply current with the adaptor, it does not add significant drain over the 25 Ma the keyer itself draws. The small USB keyboard I tried added only about 3 milliamps when not typing. I did find the transistor I used to buffer the speaker draws 25 milliamps itself, will have to find a more efficient amplifier.

Advertisements