My adventures in amateur radio, cycling, running, adventure motorcycling, traveling, and diving. In other words, I have too many hobbies!
Thursday, January 23, 2014
American Morse KK2 Paddle
Saturday, January 18, 2014
Elecraft T1 Tuner Repair
Hendricks PFR3 build, groups 1 & 2
Monday, March 11, 2013
TrunkTrackerino v .9 finished
- Have to fix an issue with the log file time stamp
- Have to add in logic to sleep when speed ! >= 1
- Have to slow down the read (it's every .5 seconds right now)
- Bonus: add logic to put the device to sleep for 5 min when speed !>=.5, to save on battery power
After that, my next addition will be an APRS shield so I can start communicating geo-loc over radio. That is the base bundle for the balloon instrument pack.
Code:
// TrunkTracker sketch combines code from GPSTest_RMC and SD_GPSLogger
// Throw your Arduino in the trunk to see where your teens really go
// and how fast they really drive.
#include "Arduino.h"
//#include "GPSconfig.h"
#include <avr/sleep.h>
#include <SD.h>
// If running Arduino < 1.0, add references to WProgram.h and NewSoftSerial.h
#include "SoftwareSerial.h"
// Set this to 0 when in production; all serial output will be diasabled
#define DEBUG 0
// My shield is wired with RX/TX swapped
//SoftwareSerial mySerial = SoftwareSerial(2, 3);
SoftwareSerial mySerial = SoftwareSerial(3, 2);
// power saving modes
#define SLEEPDELAY 0 /* power-down time in seconds. Max 65535. Ignored if TURNOFFGPS == 0 */
#define TURNOFFGPS 0 /* set to 1 to enable powerdown of arduino and GPS. Ignored if SLEEPDELAY == 0 */
#define LOG_RMC_FIXONLY 0 /* set to 1 to only log to SD when GPS has a fix */
// Set up pins used
#define powerpin 4 // Use pin 4 to control power to GPS
#define led1Pin 5
#define led2Pin 6
// Set GPSRATE to 4800 for my GPS
#define GPSRATE 4800
// Create a buffer of 90 to store GPS data. Usually about 80 chars so 90 is plenty
#define BUFFSIZE 90
// Create an int for iterating
uint8_t i;
// Create instance of logfile
File logFile;
// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 10;
// Global variables
char buffer[BUFFSIZE]; // string buffer for the sentence
char *parseptr; // a character pointer for parsing the GPS sentence
char buffidx; // an indexer into the buffer
bool fix = false; // current fix on data
bool gotGPRMC = false; // true if current data is a GPRMC string
// The time date, location, data, etc.
uint8_t hour, minute, second, year, month, date;
uint32_t latitude, longitude;
uint8_t groundspeed, trackangle;
char latdir, longdir;
char validity;
// Setup the sketch
void setup()
{
// First set up GPS comms
if (powerpin)
{
pinMode(powerpin, OUTPUT);
}
// Use the pin 13 LED as an indicator
pinMode(13, OUTPUT);
// connect to the serial terminal at 9600 baud
Serial.begin(9600);
// connect to the GPS at the appropriate rate
// IF THIS IS WRONG for your GPS, change it above
mySerial.begin(GPSRATE);
// print title with ending line break
if (DEBUG)
Serial.println("GPS Parser started");
digitalWrite(powerpin, LOW); //pull low to turn on
// Now set up SD for logging
// This code lifted from "Datalogger" sample sketch
if (DEBUG)
Serial.println("Initializing SD card...");
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(10, OUTPUT);
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card init. failed!");
error(1);
}
// Now create a unique file
strcpy(buffer, "GPSLOG00.TXT");
for (i = 0; i < 100; i++) {
// Keep iterating till you find unique file name
// Create if does not exist, do not open existing, write, sync after write
buffer[6] = '0' + i/10;
buffer[7] = '0' + i%10;
if (! SD.exists(buffer)) {
break;
}
}
// Now open the file just created
logFile = SD.open(buffer, FILE_WRITE);
if( ! logFile ) {
if (DEBUG)
{
Serial.print("Couldnt create "); Serial.println(buffer);
}
error(3);
}
if (DEBUG)
{
Serial.print("Writing to "); Serial.println(buffer);
}
// Done opening log file
}
uint32_t parsedecimal(char *str)
{
uint32_t d = 0;
while (str[0] != 0)
{
if ((str[0] > '9') || (str[0] < '0'))
return d;
d *= 10;
d += str[0] - '0';
str++;
}
return d;
}
// Read line from GPS unit
void readline(void)
{
if (DEBUG)
Serial.print("Input from GPS: ");
char c;
buffidx = 0; // start at beginning of line
while (1)
{
c = mySerial.read();
if (c == -1)
continue;
// Output status to screen
if (DEBUG)
Serial.print(c);
if (c == '\n')
continue;
// if we're nearing the end of buffer, terminate
if ((buffidx == BUFFSIZE-1) || (c == '\r'))
{
buffer[buffidx] = 0;
return;
}
// Write each char into buffer
buffer[buffidx++] = c;
}
}
// Main program - keep doing this over and over
void loop()
{
uint32_t tmp;
if (DEBUG)
Serial.print("\n\rRead: ");
readline();
// Check if $GPRMC (global positioning fixed data)
if (strncmp(buffer, "$GPRMC",6) == 0)
{
// Set gotGPRMC
gotGPRMC = true;
//hhmmss time data
parseptr = buffer+7;
tmp = parsedecimal(parseptr);
hour = tmp / 10000;
minute = (tmp / 100) % 100;
second = tmp %100;
parseptr = strchr(parseptr, ',') + 1;
validity = parseptr[0];
parseptr +=2;
/*
// Break out if "validity" = "V"
if(validity = 'V')
{
if(DEBUG)
Serial.print("\nGPS navigation error. Trying again...");
return;
}
*/
// grab latitude & longitude data
// latitude
latitude = parsedecimal(parseptr);
if (latitude != 0)
{
latitude *= 10000;
parseptr = strchr(parseptr, '.') + 1;
latitude += parsedecimal(parseptr);
}
parseptr = strchr(parseptr, ',') + 1;
// read latitude N/S data
if (parseptr[0] != ',')
{
latdir = parseptr[0];
}
// longituide
parseptr = strchr(parseptr, ',')+1;
longitude = parsedecimal(parseptr);
if (longitude != 0)
{
longitude *= 10000;
parseptr = strchr(parseptr, '.') + 1;
longitude += parsedecimal(parseptr);
}
parseptr = strchr(parseptr, ',') + 1;
// read longitude E/W data
if (parseptr[0] != ',')
{
longdir = parseptr[0];
}
// groundspeed
parseptr = strchr(parseptr, ',') + 1;
groundspeed = parsedecimal(parseptr);
// trackangle, just 'cause
parseptr = strchr(parseptr, ',') + 1;
trackangle = parsedecimal (parseptr);
// date
parseptr = strchr(parseptr, ',') + 1;
tmp = parsedecimal(parseptr);
date = tmp / 10000;
month = (tmp / 100) % 100;
year = tmp % 100;
// OK - we've parsed the full string. Now let's print to serial if in debug mode
if (DEBUG)
{
Serial.print("\n\tTime: ");
Serial.print(hour, DEC); Serial.print(':');
Serial.print(minute, DEC); Serial.print(':');
Serial.println(second, DEC);
Serial.print("\tDate: ");
Serial.print(month, DEC); Serial.print('/');
Serial.print(date, DEC); Serial.print('/');
Serial.println(year, DEC);
Serial.print("\n\tStatus: "); Serial.print(validity);
Serial.print("\n\tLat: ");
if (latdir == 'N')
Serial.print('+');
else if (latdir == 'S')
Serial.print('-');
Serial.print(latitude/1000000, DEC); Serial.print("* ");
Serial.print((latitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
Serial.print((latitude%10000)*6/1000, DEC); Serial.print('.');
Serial.print(((latitude%10000)*6/10)%100, DEC); Serial.println('"');
Serial.print("\tLong: ");
if (longdir == 'E')
Serial.print('+');
else if (longdir == 'W')
Serial.print('-');
Serial.print(longitude/1000000, DEC); Serial.print("* ");
Serial.print((longitude/10000)%100, DEC); Serial.print('\''); Serial.print(' ');
Serial.print((longitude%10000)*6/1000, DEC); Serial.print('.');
Serial.print(((longitude%10000)*6/10)%100, DEC); Serial.println('"');
Serial.print("\tGroundspeed: ");
Serial.println(groundspeed);
Serial.println("Now writing to SD card...\n\t");
Serial.println(buffer);
}
// Now log tab separated string
digitalWrite(led2Pin, HIGH); // First turn on LED2 to indicate writing to SD
logFile.write((uint8_t *) buffer, buffidx); // write the string to the SD card
logFile.println("");
logFile.flush();
digitalWrite(led2Pin, LOW); // turn off LED2 (write to SD is finished)
buffidx = 0; // reset buffer pointer
if(fix)
{
if ((TURNOFFGPS) && (SLEEPDELAY))
{
digitalWrite(powerpin, HIGH); // turn off GPS
delay(100); // wait for serial monitor write to finish
sleep_sec(SLEEPDELAY); // turn off CPU
digitalWrite(powerpin, LOW); // turn on GPS
} // if (TURNOFFGPS)
} // if (fix)
return;
} // if(gotGPRMC)
}
// Handling Errrs HERE
// blink out an error code
void error(uint8_t errno) {
if (DEBUG)
{
/* Need to investigate
if (SD.errorCode()) {
putstring("SD error: ");
Serial.print(card.errorCode(), HEX);
Serial.print(',');
Serial.println(card.errorData(), HEX);
}
*/
Serial.print("Error writing to SD card. ");
}
while(1) {
for (i=0; i<errno; i++) {
digitalWrite(led1Pin, HIGH);
digitalWrite(led2Pin, HIGH);
delay(1000);
digitalWrite(led1Pin, LOW);
digitalWrite(led2Pin, LOW);
delay(100);
}
for (; i<10; i++) {
delay(200);
}
}
}
void sleep_sec(uint16_t x) {
while (x--) {
// set the WDT to wake us up!
WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1);
WDTCSR |= (1<< WDIE);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// sleep_enable();
sleep_mode();
// sleep_disable();
}
}
Sunday, March 10, 2013
TrunkTrackerino
I have teens...
They drive my car...
They are boys...
I am an engineer...
I like life hacks...
I have an Arduino...
And a GPS logging shield....
Therefore, TrunkTrackerino.
More than two years ago I started a push to get my Arduino working with the GPS logger shield. It failed, mostly because I had some other life pressures. I recently pulled out my Arduino and started messing with it again, not really sure why... And I got the GPS working. And then I thought... I can build a simple device to throw in the trunk that will record driving speed! And thus TrunkTrackerino was born.
There are sketches for using a GPS. There are also sketches for logging GPS data to a card reader. But I really didn't like any of them individually, so I have merged them together. And as of today, I believe I have it working (not entirely sure, since I'm in my hotel and can't pick up signal--I will know more tomorrow).
The goal is to build an Arduino-based device which
* tracks speed and location
* sleeps when there is no motion
* logs nothing when there's no valid data
* stores data on an SD card
* can be imported into XL to view historical speed data
* can be imported into Google Earth for bread crumb data
Eventually this project will end up as the base for the APRS balloon tracking system. For now, it's enough to know my boys are as honest as they say they are.
Update: I took a brief stroll around the hotel entrance today. For some reason, the logging code is logging an empty file. The GPS is working great--when I watch in Arduino's serial monitor, I can see good valid strings which are being parsed great. I'd say I'm 10 lines of code from a working beta.
Thursday, December 8, 2011
Near Space Balloon
Every once in a while I get a hair-brained scheme that I can actually sell to some unsuspecting person. Like the weather balloon! My son was looking for a science experiment, and I was looking for a challenge. And now we are building a weather balloon.
We will be launching a 1200 gram balloon into near space, sometime between mid-Jan and mid-Feb 2012. Near space is an awesome place... you can see the earth's curvature, elements of the atmosphere, etc. It's really cold out there, too, with temperatures around- 50 C.
We will be sending up one or more Arduino boards in our balloon instrument package, to measure altitude, GPS coordinates, temperature, etc. Our second instrument package will include an APRS solution as well as a 2m radio beacon. Finally, thanks to the generosity of the folks at GoPro, we'll have a GoPro Hero HD on board to record the whole trip.
In this blog, I will be recording our progress. So keep up with it to watch as we design, build, test and launch.
73 de K7JTO
Monday, October 31, 2011
Test from Android
It's been a while since I last posted. Life has been coming at me fast! Just a quick test that I can post from my aallAndroid device right now, but more to come.











