Tuesday, May 19, 2015

ADS-GM2 GPS

I received my new GPS module from ArgentData ADS-GM2 that I will be using for a balloon tracker and decided to give it a bench test.


The connections are broken out in two ways. The connections on the left of the board are setup to mate to a DB-9 female or to the right with a 6 pin mini wafer connector. Since I will be using the RS-232 pins I decided to just use the DB-9 side. All the connection I need are on the top of the board so I used a .100 inch header soldered to the top of the board to break out the pins:

2 - RS-232 out
3 - RS-232 in
4 - Power
5 - Ground

Pin 1 is marked on the board as X1. I powered the board with 5 volts and connected my USB to RS-232 adapter to it and was able to see the serial NMEA sentences at 4800 baud on pin 2.

Just for fun I wanted to see the accuracy of this GPS module and had I found an interesting piece of freeware called VisualGPS. The software is designed to take the NMEA data from the GPS for a period of time while it is stationary and produce an analysis of the variations. The following is the analysis after about 12 hours.


It is interesting to see the variance over time. The GPS system is very complex and many calculations are made, both in the GPS module and in the system as a whole via the ground stations and uplinked via the satellite messaging.

The NMEA strings contain position information of the satellites which VisualGPS can also plot:


As well as a coverage plot:

The longer you collect data the more complete the plot will become. This can be useful for evaluating the antenna and the orientation of the antenna.

Tuesday, May 12, 2015

How to use your Cellphone for voice, video, and chat when cell service is DOWN

After using  Linphone from the post HERE , I realized how simple it would be to create a ad hoc phone, video, and messaging network with just a wireless access point and smart phones loaded with the Linphone application. The basic recipe is one wireless access point like an old Linksys and two smartphones with Linphone loaded. The two smartphone will need to join the Linksys wireless network. The Linksys does not need to be connected to the Internet. The two smartphone will basically just be on the local wireless network offered by the Linksys. The only catch is you do need to know each others IP addresses to communicate. Once you know that you can call each other by just using the SIP address in the form - name@IPAddress:5060 the name can actually be anything (e.g. Bill@192.168.1.50:5060).

What this means is that if you take a old Linksys Access Point and run it off a battery and maybe put it up on a mast in the air say 20 to 30 feet up you could provide voice, video, and chat capabilities to a parking lot full of people. This may be useful for an emergency situation, etc.

If the WiFi setup included a registration process, perhaps a directory could be populated so people joining the network would "see" the other members.

I am looking at a Raspberry Pi image that can run as an Access Point, this would then allow a web server to be part of the network. Also the Rasp Pi is small and light and should use less power than a old Linksys wireless router, will need to verify.

Tuesday, May 5, 2015

Teensy 3.1 APRS

I came across an interesting post in the Teensy PJRC Forum about using a Teensy 3.1 as a APRS tracker. This is based on the trackuino code, but since the Teensy 3.1 has a 12 bit DAC no external hardware is needed thanks to this modified code.

I wanted to try out the code posted HERE but it took a few steps to get it running in the Arduino IDE so I thought I would share what I did:


  1. I took the posted code and placed it in a folder called "Aprs" in the Arduino IDE "libraries" folder.
  2. I removed the file called "APRSExample.cpp" from that "libraries" folder.
  3. I also grabbed the Adafruit GPS Library files from HERE and placed them in a folder called "Gps" in the Arduino IDE "libraries" folder.
  4. Next I started the Arduino IDE and opened a new sketch and pasted the content of the "APRSExample.cpp" into the editor.
  5. Next I tried to compile it and got a few errors and ended up removing the bottom 10 lines that contain the "int main(void)" section (not valid in Arduino sketches). After that it compiled (cool!).
Since I don't currently have a GPS connected to my Teensy 3.1 and wanted to try it without a GPS so I needed to make a few more changes to the code. Basically I just commented the original "aprs_send" method and substituted my own with fixed values for time, lat/lon, speed, heading, etc. and in the main "loop" commented all the "if" statements out so it would just loop and send every 10 seconds. If this was used the define sections in the code would need to reflect the call sign, ID, etc.

Below is the working code running in my Arduino IDE v1.0.6 and the teensyduino add-on. I hope to further modifiy the code to support other APRS packet types like weather and telemetry.




 /*  
 aprs-teensy31  
 =============  
 Example code for generating APRS   
 packet "sounds" on the teensy 3.1's DAC pin.  
 Summary  
 =======  
 This code is intended to be used with the Arduino Library   
 for Teensy 3.1. For simplicity you can use Teensyduino.  
 aprs.h contains the two function calls you need.  
 Call aprs_setup with the parameters you want.  
 Call aprs_send to send a packet.   
 Note:  
 =====  
 It will not return until the entire packet has been sent.  
 The code is structured as generic C-code with no clases   
 or object oriented features. It is purely functional in nature anyway.  
 Acknowledgement  
 ===============  
 The APRS library is based on code retrieved from the Trackuino project.   
 This is a hardware/software project designed to use the   
 Arduino and a Radiometrix HX1 transmitter as a position tracking system.   
 The code was written by Javier Martin under the same GNU General   
 Public License.  
 */  
 #include <WProgram.h>  
 // Note: this example uses my GPS library for the Adafruit Ultimate GPS  
 // Code located here: https://github.com/rvnash/ultimate_gps_teensy3  
 #include <GPS.h>  
 #include <aprs.h>  
 // APRS Information  
 #define PTT_PIN 13 // Push to talk pin  
 // Set your callsign and SSID here. Common values for the SSID are  
 #define S_CALLSIGN   "KC3ARY"  
 #define S_CALLSIGN_ID  1  // 11 is usually for balloons  
 // Destination callsign: APRS (with SSID=0) is usually okay.  
 #define D_CALLSIGN   "APRS"  
 #define D_CALLSIGN_ID  0  
 // Symbol Table: '/' is primary table '\' is secondary table  
 #define SYMBOL_TABLE '/'   
 // Primary Table Symbols: /O=balloon, /-=House, /v=Blue Van, />=Red Car  
 #define SYMBOL_CHAR 'v'  
 struct PathAddress addresses[] = {  
  {(char *)D_CALLSIGN, D_CALLSIGN_ID}, // Destination callsign  
  {(char *)S_CALLSIGN, S_CALLSIGN_ID}, // Source callsign  
  {(char *)NULL, 0}, // Digi1 (first digi in the chain)  
  {(char *)NULL, 0} // Digi2 (second digi in the chain)  
 };  
 HardwareSerial &gpsSerial = Serial1;  
 GPS gps(&gpsSerial,true);  
 // setup() method runs once, when the sketch starts  
 void setup()  
 {  
  Serial.begin(9600); // For debugging output over the USB port  
  gps.startSerial(9600);  
  delay(1000);  
  gps.setSentencesToReceive(OUTPUT_RMC_GGA);  
  // Set up the APRS module  
  aprs_setup(50, // number of preamble flags to send  
         PTT_PIN, // Use PTT pin  
         100, // ms to wait after PTT to transmit  
         0, 0 // No VOX ton  
         );  
 }  
 // Function to broadcast your location  
 void broadcastLocation(GPS &gps, const char *comment)  
 {  
  // If above 5000 feet switch to a single hop path  
  int nAddresses;  
  if (gps.altitude > 1500) {  
   // APRS recomendations for > 5000 feet is:  
   // Path: WIDE2-1 is acceptable, but no path is preferred.  
   nAddresses = 3;  
   addresses[2].callsign = "WIDE2";  
   addresses[2].ssid = 1;  
  } else {  
   // Below 1500 meters use a much more generous path (assuming a mobile station)  
   // Path is "WIDE1-1,WIDE2-2"  
   nAddresses = 4;  
   addresses[2].callsign = "WIDE1";  
   addresses[2].ssid = 1;  
   addresses[3].callsign = "WIDE2";  
   addresses[3].ssid = 2;  
  }  
  // For debugging print out the path  
  Serial.print("APRS(");  
  Serial.print(nAddresses);  
  Serial.print("): ");  
  for (int i=0; i < nAddresses; i++) {  
   Serial.print(addresses[i].callsign);  
   Serial.print('-');  
   Serial.print(addresses[i].ssid);  
   if (i < nAddresses-1)  
    Serial.print(',');  
  }  
  Serial.print(' ');  
  Serial.print(SYMBOL_TABLE);  
  Serial.print(SYMBOL_CHAR);  
  Serial.println();  
  // Send the packet  
  /*  
  aprs_send(addresses, nAddresses  
        ,gps.day, gps.hour, gps.minute  
        ,gps.latitude, gps.longitude // degrees  
        ,gps.altitude // meters  
        ,gps.heading  
        ,gps.speed  
        ,SYMBOL_TABLE  
        ,SYMBOL_CHAR  
        ,comment);  
 */  
 aprs_send(addresses, nAddresses  
        ,1, 15, 59  
        ,33.47,-118 // degrees  
        ,10 // meters  
        ,0  
        ,0  
        ,SYMBOL_TABLE  
        ,SYMBOL_CHAR  
        ,comment);  
 }  
 uint32_t timeOfAPRS = 0;  
 bool gotGPS = false;  
 // the loop() methor runs over and over again,  
 // as long as the board has power  
 void loop()  
 {  
  //if (gps.sentenceAvailable()) gps.parseSentence();  
  //if (gps.newValuesSinceDataRead()) {  
   //gotGPS = true; // @TODO: Should really check to see if the location data is still valid  
   //gps.dataRead();  
   //Serial.printf("Location: %f, %f altitude %f\n\r",  
            //gps.latitude, gps.longitude, gps.altitude);  
  //}  
  //if (gotGPS && timeOfAPRS + 60000 < millis()) {  
   broadcastLocation(gps, "Hi Gary N6SER" );  
   //timeOfAPRS = millis();  
   delay(10000);  
  //}  
 }