Monday, April 27, 2015

APRS & GPS Software

I continue to explore different software packages to aid in balloon payload tracking using APRS.

I came across two applications that may be useful:







The extModem application is a command line tool that implements a software packet modem. What's interesting is that it supports the KISS protocol via a TCP port. I have used SoundModem which is very good but only supports the AGW Packet engine API. With extModem and the Virtual Serial Port Emulator I can connect the modem to APRS applications that use KISS modems over COM ports.





The NMEA GPS application is an iPhone application that allows me to send GPS data to other applications over the local network. In this case I can again use the Virtual Serial Port Emulator to connect my iPhone GPS to legacy APRS applications that need to use a COM port.


Below are some notes of how I connected the extModem and NMEA GPS to UI-View32 using the Virtual Serial Ports:













Here is my Virtual Serial Port Emulator configuration











Sunday, April 19, 2015

VOIP Audio Tools for Ham Radio

I like to operate my FT-817 remotely over my local LAN and have been using IPSound to carry the audio for many years. This has worked great using Ham Radio Deluxe 5.x to control the radio tuning, etc. however I was thinking there must be something out there that will work with my iPad by now since IPSound is a Windows only application.

I figured I would look for a Open Source Voice Over IP (VOIP) application and found one called Linphone. Linphone is one of many SIP telephone applications available. What interesting is I have seen Hams using Wifi Mesh applications like Broadband-Hamnet and connecting ATA phone adapters like a Grandstream HT701 so they can talk over the mesh. They of course are using a analog phone and to dial each other you just use the IP address of each station, but why do that when you can just use a softphone like Linphone. You can setup the contacts and you will not need to remember IP addresses, etc. I guess depending on the analog phones they use with the ATA adapters they could have memories in the phones. The analog phone do make it simpler to use if it were needed in some emergency communication situations.

Anyway, I did successfully get Linphone running on my Windows XP PC that I use to control my FT-817 and another copy on my iPad. The only thing I discovered is that I could not achieve the same audio quality as IPSound. I tried all the Linphone CODECs and the best one was the G722. For standard HF radio use this is fine. There may be better CODECs available as plugins but I have not yet pursued that direction.

Since Linphone is multi-platform it makes it very handy (e.g. Andriod, IOS, Linux, Windows, etc.) There is also a command line mode that I have not tested yet. All in all this seems like a usable solution and I will use it to monitor some of the HF nets for the next few weeks.

Sunday, April 12, 2015

Balloon Tracking Simulation Experiment

I was thinking about how to prepared for a balloon launch carrying an APRS payload without actually launching a balloon and thought that if the APRS data could be simulated and transmitted from the ground anyone receiving the APRS packet would interpret it as if it where real and coming from a balloon. This would allow us to create a simulated balloon flight profile and then transmit it from the same area it would be flying from but it would not be in the air, but instead from a mobile vehicle. We could have two groups (e.g. one tracking team and one simulated balloon team) go out and exercise the equipment and verify they could recover the payload by succesfully finding the simulated payload. This method should also be picked up via the APRS IGATEs and on the Internet APRS-IS network so the folks supporting us from their home QTH could monitor APRS.fi and track it as well.

I searched the Internet for various solutions and settled on the following:

  • UI-View32 --> LINK
  • NMEA Generator --> LINK
  • Virtual Serial Port Emulator --> LINK
UI-View32 is a very popular APRS applications and I have spent many hours exploring it and I still find new things it can do (like this!). It has the ability to connect a GPS to it via a COM port. When a GPS is connected to UI-View it basically becomes a tracker like you would use in a balloon, but it is running on a PC. The next component is the NMEA Generator. I found the link to this on WA8LMF site which is a great resource for all things APRS. The NMEA Generator is the key and it basically can generate the serial strings that come from a GPS and send them to a COM port. This makes UI-View think it is receiving GPS location data. So now I need to connect the NMEA Generator to UI-View32. To do this I use a Virtual Serial Port emulator. This allows both applications to run on the same PC and talk to each other. The nice feature of the NMEA Generator is its ability to take a .INI file that you have created and drag and drop onto the application (read the docs) and it will load a set of points that you have created for the flight or trip into the generator. See below for a file I created ti simulate a flight. I created the flight profile using real wind data and balloon weights, etc. using Balloon Track for Windows another outstanding application. Balloon Track can export in many formats but I used CSV .because I need Lat, Lon, Altitude, and speed (mind your units!). Then I used Excel to format it to work in the INI file (Note: you need a sequence number D1, D2, D3, etc.)The key thing I discovered was unless you want the NMEA Generator to loop and repeat your data points, the last record should have a blank speed value. In addition, if you don't want the simulated balloon to continue to drift forever on the ground, the second to last speed value should be set to zero '0'.

I did all the experiments connected the APRS-IS and have not transmitted any of the packets on the air which is the next step and the final goal. I will need to see how this setup will run on a 800 Mhz Windows XP laptop. 


 [Option]  
 SpeedUnit=0  
 Version=Ver1.18  
 EngCharset=0  
 EngFontName=Arial  
 EngFontSize=8  
 JpCharset=1  
 JpFontName=Tahoma  
 JpFontSize=8  
 TrackMax=50  
 TimeDiff=  
 MagVari=  
 MainTop=36  
 MainLeft=28  
 [Track]  
 D1=33.75176235,-118.0567753,85,2  
 D2=33.75188794,-118.0565514,106,20.37468822  
 D3=33.75331956,-118.0536856,323,24.08305198  
 D4=33.75508722,-118.0504115,542,27.7701033  
 D5=33.75649766,-118.0470814,768,25.93723385  
 D6=33.75714538,-118.0441726,999,20.37468822  
 D7=33.757194,-118.0424913,1235,11.10377883  
 D8=33.75679214,-118.0421775,1478,3.708363756  
 D9=33.75572611,-118.0429181,1729,9.249596954  
 D10=33.75412309,-118.0443713,1983,14.81214259  
 D11=33.75231754,-118.0461303,2246,16.66632447  
 D12=33.75014851,-118.0479573,2514,18.52050634  
 D13=33.74745902,-118.0495352,2791,20.37468822  
 D14=33.74472201,-118.0502351,3075,18.52050634  
 D15=33.73888334,-118.0503581,3667,18.52050634  
 D16=33.73346457,-118.048734,4297,16.66632447  
 D17=33.7281628,-118.0484004,4971,14.81214259  
 D18=33.72100578,-118.0522323,5694,20.37468822  
 D19=33.71070127,-118.0585446,6477,27.7701033  
 D20=33.69364442,-118.0672461,7332,40.74937644  
 D21=33.66465533,-118.079235,8275,61.12406466  
 D22=33.62329029,-118.0992921,9329,79.64457101  
 D23=33.59469352,-118.1175273,9999,90.74834984  
 D24=33.5864404,-118.1227875,9329,90.74834984  
 D25=33.57353805,-118.1290326,8275,79.64457101  
 D26=33.56386113,-118.1330223,7332,61.12406466  
 D27=33.55781541,-118.1360955,6477,40.74937644  
 D28=33.55396045,-118.1384479,5694,27.7701033  
 D29=33.55114968,-118.1399464,4971,20.37468822  
 D30=33.54897387,-118.1398074,4297,14.81214259  
 D31=33.54665698,-118.139112,3667,16.66632447  
 D32=33.54406341,-118.1391638,3075,18.52050634  
 D33=33.54282553,-118.1394783,2791,18.52050634  
 D34=33.54158725,-118.1402014,2514,20.37468822  
 D35=33.54057153,-118.1410532,2246,18.52050634  
 D36=33.53971191,-118.141887,1983,16.66632447  
 D37=33.53893682,-118.1425865,1729,14.81214259  
 D38=33.53841359,-118.1429483,1478,9.249596954  
 D39=33.53821353,-118.1427921,1235,3.708363756  
 D40=33.53823878,-118.1419447,999,11.10377883  
 D41=33.53857184,-118.1404583,768,20.37468822  
 D42=33.53930566,-118.1387338,542,25.93723385  
 D43=33.54023695,-118.1370163,323,27.7701033  
 D44=33.54100122,-118.1354928,106,24.08305198  
 D45=33.54132354,-118.1349205,7,20.37468822  
 D46=33.54134483,-118.134878,0,0  
 D47=33.54134483,-118.134878,0,  
 [DGPS]  
 Invalid=,  
 SPS=,  

Thursday, April 9, 2015

Club Balloon Launch (no payload)

Last Saturday was our planned Club Balloon launch. Everything was going very well until we discovered our APRS payload was not working. After we spent more than 2 hours trying to resolve the issue we had to abort, however we had already filled the balloon partially so we ended up just releasing the balloon with no payload attached. Lesson learned was don't start filling the balloon until the complete payload chain is operational!

That lesson cost us a $40 balloon and $60 of helium.





Sunday, March 29, 2015

Teensy 3.1 Impressions and the Audio Library

I have been hearing a lot of good things about the Teensy 3.1 development board regarding its use as a SDR platform HERE. It seems like it has a great deal of capability over the the Teensy 2.0 that I have been using. This power is due to it's 32 bit ARM processor. The coolest thing is that it uses the Arduino IDE and nearly all of your sketches will run on it. The Teensy SDR linked above exploits the Teensy 3.1 audio DSP functions and PJRC has created a simple GUI tool to help you create your audio projects easily.

As a simple test after I powered up my Teensy 3.1, I used the audio design tool to define two sine wave sources, mix them together and output them to the on-board DAC. Below is an image of my session with the tool (it is web based or you can download and run locally).



After the design is completed in the tool you just press the RED "Export" button and it will output the code for your sketch. I ended up tailoring mine to generate a Dial Tone and I was blown away how good it sounded! I just took the output of the DAC and feed it directly into a standard PC powered speaker.

You do need to do a little coding since the tool just sets up the streams. The tool generated the code that is between the "// GUItool ..." comments below in the example. I needed to call the audio objects in the "loop()" section which you can figure out from the docs and the examples provided. The comment section at the bottom is when I was playing with other Tel-co sounds (e.g. Busy Signal).

I am very impressed with the Teensy 3.1 platform and intend on replacing my Teensy 2.0 in my Proto Type Radio with it soon and try out some of the audio SDR functions.

Example Code:

 // Simple Mixer to generate a Dialtone  
 #include <Audio.h>  
 #include <Wire.h>  
 #include <SPI.h>  
 #include <SD.h>  
 // GUItool: begin automatically generated code  
 AudioSynthWaveformSine  sine1;     //xy=183,181  
 AudioSynthWaveformSine  sine2;     //xy=192,251  
 AudioMixer4       mixer1;     //xy=392,207  
 AudioOutputAnalog    dac;      //xy=591,178  
 AudioConnection     patchCord1(sine1, 0, mixer1, 0);  
 AudioConnection     patchCord2(sine2, 0, mixer1, 1);  
 AudioConnection     patchCord3(mixer1, dac);  
 // GUItool: end automatically generated code  
 void setup() {  
  // Audio connections require memory to work. For more  
  // detailed information, see the MemoryAndCpuUsage example  
  AudioMemory(3);  
  }  
  void loop() {  
  sine1.frequency(350); //350  
  sine1.amplitude(0.1);  
  sine2.frequency(440);//440  
  sine2.amplitude(0.1);  
  //delay(100);  
  //sine1.amplitude(0);  
  //sine2.amplitude(0);  
  //delay(100);  
  }  

Saturday, March 14, 2015

Prototype Radio V - CAT Control with Omni-Rig

I continue to experiment with the CAT control of the Si5351 with the simple DC receiver. I wanted to document the use of Omni-rig that I mentioned in the last post. After Omni-Rig is installed, HDSDR will be able to access the Omni-Rig setup screen below. You just select the rig type, the COM port the Arduino is on, and the baud rate (e.g. we are using 4800, but it can be changed in the code).
The best way to run it is to Sync the LO frequency and then check the sync to/from Omni-Rig as seen below. The you just click on the frequency and type in the frequency you want and press enter. Then you will see the span of frequencies based on your bandwidth setting. To tune around at this point, change the LO not the TUNE frequency. Your offsite will remain fixed based on the setting below. This works well for me at this point. I am able to use 192K sample rate which gives me more than 80 Khz (this is half of the 192 since this is not a true SDR which would center you and give you 80 below and 80 above)
There is a setting that positions the SDR cursor when you tune it. The default is 10000 hz or 10Khz, but you may want to adjust it to the best part of the pass-band. I find that 40khz is the lowest noise part of my pass-band for my setup. I have also been investigating noise issues that are caused by the PC's USB port. I will need to devise some filtering next. In the mean time I have found that placing an "un-powered" USB power block across the DC buss cuts most of the noise. I just use a USB cable that has the power pins broken out to pins plugged into the breadboard and plugged into the power block.
Here is the offsite screen with the default 10khz setting.

Sunday, March 8, 2015

Prototype Radio IV - CAT Control

I mentioned to my friend Gary N6SER how cool it would be to write some code for the Arduino to control the Si5351 via the standard Computer Aided Transceiver (CAT) control. He used Ham Radio Deluxe HRD as his standard platform for testing and picked the Elecraft K2 to model. Here is the programming guide --> HERE. He got a basic sketch running that controlled frequency and Mode (e.g. CW, LSB, USB, etc). I then took his sketch and incorporated the Si5351 library to control the clock module. The idea is to build the simplest radio system and use the Arduino serial port to control it with already existing software that uses the CAT interface. No display is needed, no knobs, switches, etc. the software provides the front panel. The sketch has now been tested on my Prototype Radio with HRD version 5.xFLRigCommander, and most exciting - OmniRig with HDSDR. The choice of using the K2 was brilliant because it has one of the simplest command structures. There is more work to be done but it does work. One issue is that the Arduino connected to the computer couples a lot of noise sources into the prototype radio's simple direct conversion receiver. I had no problem tuning around with HDSDR and it controlling the local oscillator (LO) of the Si5351. The OmniRig integration with HDSDR worked great. Below is what the code looks like so far. I do have a simple LCD display on it for debugging purposes only.




1:  #include <Wire.h>   
2:  //#include <Encoder.h>  
3:  #include "si5351.h"  
4:  #include <LiquidCrystal_I2C.h> // F Malpartida's NewLiquidCrystal library  
5:  #define I2C_ADDR  0x20 // Define I2C Address where the PCF8574A is  
6:  #define BACKLIGHT_PIN   7  
7:  #define En_pin 4  
8:  #define Rw_pin 5  
9:  #define Rs_pin 6  
10:  #define D4_pin 0  
11:  #define D5_pin 1  
12:  #define D6_pin 2  
13:  #define D7_pin 3  
14:  LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);  
15:  Si5351 clockgen;  
16:  long int freq = 7040000; // In Hz  
17:  long int frequency = freq;  
18:  int mode = 1; //(1=LSB, 2=USB, 3=CW, 6=RTTY, 7=CW-REV, 9=RTTY-REV)  
19:  String received;  
20:  String command;  
21:  String parameter;  
22:  String sent;  
23:  const int ledPin = 11;  
24:  void setup()  
25:  {  
26:   // Setup for Ham Radio Deluxe 5.24.0.38  
27:   // Elecraft K2  
28:   Serial.begin(4800);  
29:   lcd.begin (8,2); // initialize the lcd   
30:   lcd.home();  
31:   lcd.print("CAT-RMT");  
32:   lcd.setCursor(0, 1);  
33:   lcd.print("v1.35");  
34:   delay(4000);  
35:   lcd.clear();  
36:   pinMode(ledPin, OUTPUT);  
37:   clockgen.init(SI5351_CRYSTAL_LOAD_8PF);  
38:   // Set CLK0 to output current value with a fixed PLL frequency  
39:   clockgen.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);  
40:   clockgen.set_freq(frequency, SI5351_PLL_FIXED, SI5351_CLK0);  
41:  }  
42:  void loop()  
43:  {  
44:   if(Serial.available() > 0)  
45:   {  
46:    received = Serial.readStringUntil(';');  
47:    received.toUpperCase();  
48:    received.replace("\n","");  
49:    command = received.substring(0,2);  
50:    parameter = received.substring(2,received.length());  
51:    if (command == "FA")  
52:    {  
53:     if (parameter != "")  
54:     {  
55:      freq = parameter.toInt();  
56:      frequency = freq;  
57:      clockgen.set_freq(frequency, SI5351_PLL_FIXED, SI5351_CLK0);  
58:      lcd.setCursor(0, 0);  
59:      lcd.print(frequency);  
60:      lcd.setCursor(0, 0);  
61:     }  
62:     sent = "FA" // Return 11 digit frequency in Hz.  
63:     + String("00000000000").substring(0,11-(String(freq).length()))   
64:      + String(freq) + ";";  
65:    }  
66:    else if (command == "IF")  
67:    {  
68:     sent = "IF" // Return 11 digit frequency in Hz.  
69:     + String("00000000000").substring(0,11-(String(freq).length()))   
70:      + String(freq) + String("   ") + "+" + "0000" + "0" + "0" + String(" ") + "00" + "0" + String(mode) + "0" + "0" + "0" + "0" + "01" + String(" ") + ";";  
71:    }  
72:    else if (command == "MD")  
73:    {  
74:     if (parameter != "")  
75:     {  
76:      mode = parameter.toInt();  
77:      //PrintToTft(String(mode),9);  
78:      lcd.setCursor(0, 1);  
79:      lcd.print(String(mode));  
80:      lcd.setCursor(0, 1);  
81:     }  
82:     sent = "MD"   
83:      + String(mode) + ";";  
84:    }  
85:    else if (command == "ID")  
86:    {  
87:     sent = "ID"   
88:      + String("017") + ";";  
89:    }  
90:    else if (command == "TX")  
91:    {  
92:     digitalWrite(ledPin, HIGH);   
93:     sent = command  
94:      + String(parameter) + ";";   
95:    }  
96:    else if (command == "RX")  
97:    {  
98:     digitalWrite(ledPin, LOW);   
99:     sent = command  
100:      + String(parameter) + ";";   
101:    }  
102:    else if (command == "SM")  
103:    {  
104:     sent = command  
105:      + String(parameter) + "0010" + ";";   
106:    }  
107:   else  
108:   {  
109:       sent = command  
110:       + String(parameter) + ";";  
111:   }  
112:    Serial.println(sent);  
113:    //PrintToTft(sent,5);  
114:    sent = String("");      
115:   }  
116:  }