Store › Forums › Video Experimenter › General Discussion › Stuck on Interrupts
- This topic has 33 replies, 3 voices, and was last updated 13 years, 5 months ago by joey.
-
AuthorPosts
-
June 26, 2011 at 2:58 am #529joeyMember
Hi,
So I finished up my project and ran into two problems, one I can work around, another I’m stuck on.
My project involves an arduino, the VE, a GPS shield, and a temperature probe. I’m displaying an overlay with this and another piece of data.
Problem 1: I wanted to put the GPS on top of the stack but the pins are not in the standard place on the VE board. Thankfully the GPS works in the middle of the sandwich of boards.
Problem 2: I’ve run across a problem with RX/TX. The GPS uses pins 0 & 1 and it appears that the VE also uses these. If I enable these
// EIMSK = _BV(INT0);
// EICRA = _BV(ISC11);then the GPS stops working. If I leave them disabled, I get the correct output from my sketch over serial but when I put the VE on, the stack stops working. As soon as I remove it, serial works again.
Any ideas on how to get around this problem?
// This is an example of how to always present your callsign and other goodies on a VE
// Note that there is no known way to display the degree symbol as the char chart is different
// joey@stan4d.net
// Make sure to install newsoftserial from Mikal Hart
// http://arduiniana.org/libraries/NewSoftSerial/
#include
#include
#include
// Use pins 2 and 3 to talk to the GPS. 2 is the TX pin, 3 is the RX pin
NewSoftSerial mySerial = NewSoftSerial(2, 3);
// Use pin 4 to control power to the GPS
const int powerpin = 4;
// Set the GPSRATE to the baud rate of the GPS module. Most are 4800
// but some are 38400 or other. Check the datasheet!
const int GPSRATE=4800;
// The buffer size that will hold a GPS sentence. They tend to be 80 characters long
// so 90 is plenty.
const int BUFFSIZ=90; // plenty big
TVout tv;
char messageTop[96] = "";
char messageBottom[96] = "";
char messageBottom2[96] = "";
const char callsign[] = "NV0N";
//TMP36 Pin Variables
const int temperaturePin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
//the resolution is 10 mV / degree centigrade
//(500 mV offset) to make negative temperatures an option
char charTemp[3] = ""; //the char representation of the float for temp
// GPS global variables
char buffer[BUFFSIZ]; // string buffer for the sentence
char *parseptr; // a character pointer for parsing
char buffidx; // an indexer into the buffer
// 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 status;
char charTmp[4] = " ";
char charTime[6] = "00:00";
char charDate[9] = "00/00/00";
char gpsCoords[13] = "";
void setup() {
tv.begin(0);
initOverlay();
tv.select_font(font6x8);
tv.fill(0);
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 desired rate
mySerial.begin(GPSRATE);
// prints title with ending line break
Serial.println("void setup running");
digitalWrite(powerpin, LOW); // pull low to turn on!
}
// Initialize ATMega registers for video overlay capability.
// Must be called after tv.begin().
void initOverlay() {
TCCR1A = 0;
// Enable timer1. ICES0 is set to 0 for falling edge detection on input capture pin.
TCCR1B = _BV(CS10);
// Enable input capture interrupt
TIMSK1 |= _BV(ICIE1);
// XXX this causes the GPS to stop working when enabled
// Enable external interrupt INT0 on pin 2 with falling edge.
// EIMSK = _BV(INT0);
// EICRA = _BV(ISC11);
}
// Required to reset the scan line when the vertical sync occurs
ISR(INT0_vect) {
display.scanLine = 0;
}
void loop() {
uint32_t tmp;
// Serial.print("nrRead: ");
readline();
// check if $GPRMC (global positioning fixed data)
if (strncmp(buffer, "$GPRMC",6) == 0) {
// hhmmss time data
parseptr = buffer+7;
tmp = parsedecimal(parseptr);
hour = tmp / 10000;
minute = (tmp / 100) % 100;
second = tmp % 100;
parseptr = strchr(parseptr, ',') + 1;
status = parseptr[0];
parseptr += 2;
// grab latitude & long 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];
}
//Serial.println(latdir);
// longitude
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);
// track angle
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;
// Serial.print("ntTime: ");
// Serial.print(hour, DEC);
// Serial.print(':');
// Serial.print(minute, DEC);
// Serial.print(':');
// Serial.println(second, DEC);
itoa(int(hour),charTime,10); // sprintf fails so we use this
strcat(charTime,":");
itoa(int(minute),charTmp,10); // sprintf fails so we use this
strcat(charTime, charTmp);
// Serial.print("tDate: ");
// Serial.print(month, DEC);
// Serial.print('/');
// Serial.print(date, DEC);
// Serial.print('/');
// Serial.println(year, DEC);
itoa(int(month),charDate,10); // sprintf fails so we use this
strcat(charDate,"/");
itoa(int(date),charTmp,10); // sprintf fails so we use this
strcat(charDate, charTmp);
strcat(charDate,"/");
itoa(int(year),charTmp,10); // sprintf fails so we use this
strcat(charDate, charTmp);
// Serial.print("tLat: ");
if (latdir == 'N') {
// Serial.print('+');
strcpy(gpsCoords,"+");
}
else if (latdir == 'S') {
// Serial.print('-');
strcpy(gpsCoords,"-");
}
// Serial.print(latitude/1000000, DEC);
// Serial.print("* ");
itoa(int(latitude/1000000),charTmp,10); // sprintf fails so we use this
strcat(gpsCoords, charTmp);
strcat(gpsCoords, "*");
strcat(gpsCoords, " ");
// Serial.print((latitude/10000)%100, DEC);
// Serial.print(''');
itoa(int((latitude/10000)%100),charTmp,10); // sprintf fails so we use this
strcat(gpsCoords, charTmp);
strcat(gpsCoords, "'");
strcat(gpsCoords, " ");
// 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('+');
strcat(gpsCoords,"+");
}
else if (longdir == 'W') {
// Serial.print('-');
strcat(gpsCoords,"-");
}
// Serial.print(longitude/1000000, DEC);
// Serial.print("* ");
itoa(int(longitude/1000000),charTmp,10); // sprintf fails so we use this
strcat(gpsCoords, charTmp);
strcat(gpsCoords, "*");
strcat(gpsCoords, " ");
// Serial.print((longitude/10000)%100, DEC);
// Serial.print(''');
itoa(int((longitude/10000)%100),charTmp,10); // sprintf fails so we use this
strcat(gpsCoords, charTmp);
strcat(gpsCoords, "'");
strcat(gpsCoords, " ");
// Serial.print(' ');
// Serial.print((longitude%10000)*6/1000, DEC);
// Serial.print('.');
// Serial.print(((longitude%10000)*6/10)%100, DEC);
// Serial.println('"');
}
// temperature
float temperature = getVoltage(temperaturePin); //getting the voltage reading from the temperature sensor
temperature = (((temperature - .5) * 100)*1.8) + 32; //converting from 10 mv per degree wit 500 mV offset
// setup the messages for output on the tv
// clear at start of loop
sprintf(messageTop, "");
sprintf(messageBottom, "");
sprintf(messageBottom2, "");
//assemble top message
strcat(messageTop,callsign);
// assemble bottom message
strcat(messageBottom,charTime);
strcat(messageBottom," ");
strcat(messageBottom,charDate);
strcat(messageBottom,"Z ");
itoa(int(temperature),charTemp,10); // sprintf fails so we use this
strcat(messageBottom,charTemp);
strcat(messageBottom,"F");
// assemble 2nd bottom meessage
strcat(messageBottom2,gpsCoords);
// write out to TV
tv.select_font(font6x8);
tv.print(0,0, messageTop);
// Serial.print("messageTop=");
// Serial.println(messageTop);
// the 4x6 font is awefully small. I thought of scrolling but that's too distracting.
// right now it's a bit small to read.
tv.select_font(font4x6);
tv.print(0,75, messageBottom);
Serial.print("messageBottom=");
Serial.println(messageBottom);
tv.print(0,85, messageBottom2);
Serial.print("messageBottom2=");
Serial.println(messageBottom2);
}
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;
}
void readline(void) {
char c;
buffidx = 0; // start at begninning
while (1) {
c=mySerial.read();
// Serial.print("readline while 1. c=");
// Serial.println(c);
if (c == -1)
continue;
// Serial.print(c);
if (c == 'n')
continue;
if ((buffidx == BUFFSIZ-1) || (c == 'r')) {
buffer[buffidx] = 0;
return;
}
buffer[buffidx++]= c;
}
}
/*
* getVoltage() - returns the voltage on the analog input defined by
* pin
*/
float getVoltage(int pin){
return (analogRead(pin) * .004882814); //converting from a 0 to 1024 digital range
// to 0 to 5 volts (each 1 reading equals ~ 5 millivolts
}
June 26, 2011 at 4:49 pm #1337joeyMemberI found two possible solutions that I’ll try later today.
1) I’m using soft serials so I could potentially just change the soft serial ports!
2) If that fails I found the docs to hook my GPS directly to the board. I could try this and hook it to the VE.
J
June 26, 2011 at 5:42 pm #1338joeyMemberlooks like the VE and the GPS Shield both share D2. I can fix that on the GPS shield so off to the workbench I go.
June 26, 2011 at 6:36 pm #1339joeyMemberSo with some soldering I got the stack to work but am having an issue with interrupts.
The newsoftserial uses int 0 – 4 which conflicts with
void initOverlay() {
TCCR1A = 0;
// Enable timer1. ICES0 is set to 0 for falling edge detection on input capture pin.
TCCR1B = _BV(CS10);
// Enable input capture interrupt
TIMSK1 |= _BV(ICIE1);
// Enable external interrupt INT0 on pin 2 with falling edge.
EIMSK = _BV(INT0);
EICRA = _BV(ISC11);
}Is there anyway to change these interrupts?
June 26, 2011 at 9:00 pm #1340joeyMemberfwiw, I found tinygps and rewrote the program using it. It uses newsoftserial too so the interrupts are still an issue.
// This is an example of how to always present your callsign and other goodies on a VE
// Note that there is no known way to display the degree symbol as the char chart is different
// joey@stan4d.net
// Make sure to install newsoftserial and tinyGPS from Mikal Hart
// http://arduiniana.org/libraries/NewSoftSerial/
#include
#include
#include
#include
// Use pins 4 and 5 to talk to the GPS. 5 is the TX pin, 4 is the RX pin
// I had to unsolder the jumpers and rewire the GPS Sheild to avoid pin 2
// pin 2 is in use by the VE
// Create an instance of the TinyGPS object
const int RXPIN=5;
const int TXPIN=4;
TinyGPS gps;
NewSoftSerial uart_gps(RXPIN, TXPIN);
// Set the GPSRATE to the baud rate of the GPS module. Most are 4800
// but some are 38400 or other. Check the datasheet!
const int GPSBAUD=4800;
// declare the GPS variables
char charTmp[10] = "";
char charTime[6] = "00:00";
char charDate[11] = "00/00/0000";
char gpsCoords[15] = "";
char gpsAlt[6] = "0000M";
// This is where you declare prototypes for the functions that will be
// using the TinyGPS library.
void getgps(TinyGPS &gps);
TVout tv;
char messageTop[96] = "";
char messageBottom[96] = "";
char messageLastline[96] = "";
const char callsign[] = "NV0N";
//TMP36 Pin Variables
const int temperaturePin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
//the resolution is 10 mV / degree centigrade
//(500 mV offset) to make negative temperatures an option
char charTemp[3] = ""; //the char representation of the float for temp
void setup() {
tv.begin(0);
// the overlay code is somehow conflicting on interrupts
// initOverlay();
tv.select_font(font6x8);
tv.fill(0);
// connect to the serial terminal at 9600 baud
Serial.begin(9600);
// connect to the GPS at the desired rate
uart_gps.begin(GPSBAUD);
// prints title with ending line break
Serial.println(" ...waiting for lock... ");
}
// Initialize ATMega registers for video overlay capability.
// Must be called after tv.begin().
void initOverlay() {
TCCR1A = 0;
// Enable timer1. ICES0 is set to 0 for falling edge detection on input capture pin.
TCCR1B = _BV(CS10);
// Enable input capture interrupt
TIMSK1 |= _BV(ICIE1);
// Enable external interrupt INT0 on pin 2 with falling edge.
EIMSK = _BV(INT0);
EICRA = _BV(ISC11);
}
// Required to reset the scan line when the vertical sync occurs
ISR(INT0_vect) {
display.scanLine = 0;
}
void loop() {
while(uart_gps.available()) // if there is data on the RX pin...
{
int c = uart_gps.read(); // load the data into a variable...
if(gps.encode(c)) // if there is a new valid sentence...
{
getgps(gps); // then grab the data.
}
}
// temperature
float temperature = getVoltage(temperaturePin); //getting the voltage reading from the temperature sensor
temperature = (((temperature - .5) * 100)*1.8) + 32; //converting from 10 mv per degree wit 500 mV offset
// setup the messages for output on the tv
// clear at start of loop
sprintf(messageTop, "");
sprintf(messageBottom, "");
sprintf(messageLastline, "");
//assemble top message
strcat(messageTop,callsign);
// assemble bottom message
strcat(messageBottom,charTime);
strcat(messageBottom," ");
strcat(messageBottom,charDate);
strcat(messageBottom,"Z ");
itoa(int(temperature),charTemp,10); // sprintf fails so we use this
strcat(messageBottom,charTemp);
strcat(messageBottom,"F");
// assemble 2nd bottom meessage
strcat(messageLastline,gpsCoords);
// write out to TV
tv.select_font(font6x8);
tv.print(0,0, messageTop);
// Serial.print("messageTop=");
// Serial.println(messageTop);
// the 4x6 font is awefully small. I thought of scrolling but that's too distracting.
// right now it's a bit small to read.
tv.select_font(font4x6);
tv.print(0,75, messageBottom);
Serial.print("messageBottom=");
Serial.println(messageBottom);
tv.print(0,85, messageLastline);
Serial.print("messageLastline=");
Serial.println(messageLastline);
}
/*
* getVoltage() - returns the voltage on the analog input defined by
* pin
*/
float getVoltage(int pin){
return (analogRead(pin) * .004882814); //converting from a 0 to 1024 digital range
// to 0 to 5 volts (each 1 reading equals ~ 5 millivolts
}
// The getgps function will get and print the values we want.
void getgps(TinyGPS &gps)
{
// To get all of the data into varialbes that you can use in your code,
// all you need to do is define variables and query the object for the
// data. To see the complete list of functions see keywords.txt file in
// the TinyGPS and NewSoftSerial libs.
// Define the variables that will be used
float latitude, longitude;
// Then call this function
gps.f_get_position(&latitude, &longitude);
// You can now print variables latitude and longitude
Serial.print("Lat/Long: ");
Serial.print(latitude,5);
itoa(int(latitude),gpsCoords,10); // sprintf fails so we use this
strcat(gpsCoords,".");
int floatTmp = abs((latitude - (int)latitude) * 100);
if (floatTmp < 10 ) {
strcat(gpsCoords,"0");
itoa(floatTmp, &gpsCoords[strlen(gpsCoords)], 10);
}
else {
itoa(floatTmp, &gpsCoords[strlen(gpsCoords)], 10);
}
strcat(gpsCoords,", ");
Serial.print(", ");
Serial.println(longitude,5);
itoa(int(longitude),charTmp,10); // sprintf fails so we use this
strcat(gpsCoords, charTmp);
strcat(gpsCoords,".");
floatTmp = abs((longitude - (int)longitude) * 100);
if (floatTmp < 10 ) {
strcat(gpsCoords,"0");
itoa(floatTmp, &gpsCoords[strlen(gpsCoords)], 10);
}
else {
itoa(floatTmp, &gpsCoords[strlen(gpsCoords)], 10);
}
strcat(gpsCoords," ");
// Same goes for date and time
int year;
byte month, day, hour, minute, second, hundredths;
gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
// Print data and time
Serial.print("Date: ");
Serial.print(month, DEC);
Serial.print("/");
Serial.print(day, DEC);
Serial.print("/");
Serial.print(year);
Serial.print(" Time: ");
Serial.print(hour, DEC);
Serial.print(":");
Serial.print(minute, DEC);
Serial.print(":");
Serial.print(second, DEC);
Serial.print(".");
Serial.println(hundredths, DEC);
itoa(int(hour),charTime,10); // sprintf fails so we use this
strcat(charTime,":");
itoa(int(minute),charTmp,10); // sprintf fails so we use this
strcat(charTime, charTmp);
itoa(int(month),charDate,10); // sprintf fails so we use this
strcat(charDate,"/");
itoa(int(day),charTmp,10); // sprintf fails so we use this
strcat(charDate, charTmp);
strcat(charDate,"/");
itoa(int(year),charTmp,10); // sprintf fails so we use this
strcat(charDate, charTmp);
// Serial.print("gpsCoords=");
// Serial.println(gpsCoords);
// Here you can print the altitude and course values directly since
// there is only one value for the function
Serial.print("Altitude (meters): ");
Serial.println(gps.f_altitude());
int altitude = int(gps.f_altitude());
itoa(altitude,gpsAlt,10); // sprintf fails so we use this
strcat(gpsAlt,"M");
// XXX there is some sort of compiler bug here. This adds it to gpsCoords not gpsAlt
// Serial.print("gpsCoords2=");
// Serial.println(gpsCoords);
// Same goes for course
Serial.print("Course (degrees): ");
Serial.println(gps.f_course());
// And same goes for speed
Serial.print("Speed(kmph): ");
Serial.println(gps.f_speed_kmph());
Serial.println();
// Here you can print statistics on the sentences.
unsigned long chars;
unsigned short sentences, failed_checksum;
gps.stats(&chars, &sentences, &failed_checksum);
//Serial.print("Failed Checksums: ");Serial.print(failed_checksum);
//Serial.println(); Serial.println();
}
June 29, 2011 at 6:30 am #1346actonMemberI think you’ll find tinyGPS just takes a character from the gps and interprets it. You need to get the character from the GPS via serial interface. The problem with the traditional serial communications is the interrupts, and because they’ve been taken over to handle the video timing to need to do it without interupts. You’re going to have to ditch newsoftserial and use the hardware uart on pins 0 & 1.
The way to do it is to use polling. There’s already a project using this method on the Nootropic website that should get you on your way at: http://nootropicdesign.com/projectlab/category/gps/
I need to take it a step further and get some other stuff done during the horizontal blanking period. I guess this means I will have to strip the bare minimum code out of Pollserial.begin. I can live a single baud rate and single chip/speed variant. Some hints as to the minimum I need to read the hardware serial and put it in a buffer would be appreciated from anyone who understands this sort of thing!
June 29, 2011 at 8:15 pm #1349joeyMemberThe provided sketch doesn’t run even if it’s just the VE and the Arduino. I did retrofit my code to match it and had the same results. It’s also harder to debug since I can’t see the output on the serial console.
June 30, 2011 at 7:27 am #1351MichaelKeymasterHi guys, sorry for the slow response. I’m on vacation out of the country and only have limited net access.
Bottom line is that you must use polling serial comm provided by tvout. The project in my blog shows that I successfully read gps info and overlaid it. But you can’t read too much data using the polling approach. I configured my em406 gps to emit only the rmc and gga sentences. And my gps is only 1Hz. Joey, what doesnt work?
June 30, 2011 at 3:39 pm #1354joeyMember@Michael wrote:
Hi guys, sorry for the slow response. I’m on vacation out of the country and only have limited net access.
Bottom line is that you must use polling serial comm provided by tvout. The project in my blog shows that I successfully read gps info and overlaid it. But you can’t read too much data using the polling approach. I configured my em406 gps to emit only the rmc and gga sentences. And my gps is only 1Hz. Joey, what doesnt work?
I have the same GPS. If I load the sketch on VE, even without the GPS, it doesn’t display (lights are, nobody is home, nothing outputted). I suspect the sketch is just stopped somewhere but since I can’t see the serial output for debugging. If I load some of my other sketches they do run and display. Suggestions?
June 30, 2011 at 9:05 pm #1353MichaelKeymasterI don’t think it will display anything until some data is received.
Did you properly configure the em406 to only output RMC and GGA sentences?
June 30, 2011 at 10:14 pm #1357joeyMember@Michael wrote:
I don’t think it will display anything until some data is received.
Did you properly configure the em406 to only output RMC and GGA sentences?
No I didn’t. I figured that for diagnostics, too much would be better than none at all. I guess I can try that.
July 1, 2011 at 12:27 am #1359joeyMemberOk in attempting to figure out how to program the GPS I realized the GPS wasn’t locking on. Turns out resetting the datum was the key.
Handy setup strings for the EM-406A:
* NMEA 8N1 various baud rates:
$PSRF100,1,1200,8,1,0,*2D
$PSRF100,1,2400,8,1,0,*28
$PSRF100,1,4800,8,1,0,*22
$PSRF100,1,9600,8,1,0,*21
$PSRF100,1,19200,8,1,0,*14
$PSRF100,1,38400,8,1,0,*11
Debug On:
$PSRF105,1,*3E
Debug Off:
$PSRF105,0,*3F
Select WGS84 Datum:
$PSRF106,21,*0FNow your sketch works but mine doesn’t. Any idea on how to display debug statements? e.g. Serial.println
July 1, 2011 at 12:32 am #1360joeyMemberah, pserial.println works!
July 1, 2011 at 12:39 am #1361joeyMemberOk, back to troubleshooting. First off, thanks guys for helping me out.
So right now, pserial.available is never true. I just get “loop”. This is the same routine that is in the overlay demo but it’s not working here. The GPS is setup exactly the same and the “gps lock” light is flashing. And yes, it’s on UART.
pserial.println("loop");
while(pserial.available()) // if there is data on the RX pin...
{
pserial.println("available");
if(gps.encode(pserial.read())) // if there is a new valid sentence...
{
pserial.println("getgps");
getgps(gps); // then grab the data.
}
}
Here’s the current code for inspection:
// This is an example of how to always present your callsign and other goodies on a VE
// Note that there is no known way to display the degree symbol as the char chart is different
// joey@stan4d.net
#include
#include
#include
#include
TVout tv;
// Use pins 4 and 5 to talk to the GPS. 5 is the TX pin, 4 is the RX pin
// I had to unsolder the jumpers and rewire the GPS Sheild to avoid pin 2
// pin 2 is in use by the VE
// Create an instance of the TinyGPS object
pollserial pserial;
TinyGPS gps;
// Set the GPSRATE to the baud rate of the GPS module. Most are 4800
// but some are 38400 or other. Check the datasheet!
const int GPSBAUD=4800;
// declare the GPS variables
char charTmp[10] = "";
char charTime[6] = "00:00";
char charDate[11] = "00/00/0000";
char gpsCoords[15] = "";
char gpsAlt[6] = "0000M";
// This is where you declare prototypes for the functions that will be
// using the TinyGPS library.
void getgps(TinyGPS &gps);
// declare overlay text vars
char messageTop[96] = "";
char messageBottom[96] = "";
char messageLastline[96] = "";
const char callsign[] = "NV0N";
//TMP36 Pin Variables
//the analog pin the TMP36's Vout (sense) pin is connected to
//the resolution is 10 mV / degree centigrade
//(500 mV offset) to make negative temperatures an option
const int temperaturePin = 0;
char charTemp[3] = ""; //the char representation of the float for temp
void setup() {
tv.begin(0);
tv.set_hbi_hook(pserial.begin(GPSBAUD));
initOverlay();
tv.select_font(font6x8);
tv.fill(0);
}
// Initialize ATMega registers for video overlay capability.
// Must be called after tv.begin().
void initOverlay() {
TCCR1A = 0;
// Enable timer1. ICES0 is set to 0 for falling edge detection on input capture pin.
TCCR1B = _BV(CS10);
// Enable input capture interrupt
TIMSK1 |= _BV(ICIE1);
// Enable external interrupt INT0 on pin 2 with falling edge.
EIMSK = _BV(INT0);
EICRA = _BV(ISC11);
}
// Required to reset the scan line when the vertical sync occurs
ISR(INT0_vect) {
display.scanLine = 0;
}
void loop() {
pserial.println("loop");
while(pserial.available()) { // if there is data on the RX pin...
pserial.println("available");
if(gps.encode(pserial.read())) { // if there is a new valid sentence...
pserial.println("getgps");
getgps(gps); // then grab the data.
}
}
// temperature
float temperature = getVoltage(temperaturePin); //getting the voltage reading from the temperature sensor
temperature = (((temperature - .5) * 100)*1.8) + 32; //converting from 10 mv per degree wit 500 mV offset
// setup the messages for output on the tv
// clear at start of loop
sprintf(messageTop, "");
sprintf(messageBottom, "");
sprintf(messageLastline, "");
//assemble top message
strcat(messageTop,callsign);
// assemble bottom message
strcat(messageBottom,charTime);
strcat(messageBottom," ");
strcat(messageBottom,charDate);
strcat(messageBottom,"Z ");
itoa(int(temperature),charTemp,10); // sprintf fails so we use this
strcat(messageBottom,charTemp);
strcat(messageBottom,"F");
// assemble 2nd bottom meessage
strcat(messageLastline,gpsCoords);
// write out to TV
tv.select_font(font6x8);
tv.print(0,0, messageTop);
// the 4x6 font is awefully small. I thought of scrolling but that's too distracting.
// right now it's a bit small to read.
tv.select_font(font4x6);
tv.print(0,75, messageBottom);
tv.print(0,85, messageLastline);
}
/*
* getVoltage() - returns the voltage on the analog input defined by
* pin
*/
float getVoltage(int pin){
return (analogRead(pin) * .004882814); //converting from a 0 to 1024 digital range
// to 0 to 5 volts (each 1 reading equals ~ 5 millivolts
}
// The getgps function will get and print the values we want.
void getgps(TinyGPS &gps)
{
// Define the variables that will be used
float latitude, longitude;
// Then call this function
gps.f_get_position(&latitude, &longitude);
itoa(int(latitude),gpsCoords,10); // sprintf fails so we use this
strcat(gpsCoords,".");
int floatTmp = abs((latitude - (int)latitude) * 100);
if (floatTmp < 10 ) {
strcat(gpsCoords,"0");
itoa(floatTmp, &gpsCoords[strlen(gpsCoords)], 10);
}
else {
itoa(floatTmp, &gpsCoords[strlen(gpsCoords)], 10);
}
strcat(gpsCoords,", ");
itoa(int(longitude),charTmp,10); // sprintf fails so we use this
strcat(gpsCoords, charTmp);
strcat(gpsCoords,".");
floatTmp = abs((longitude - (int)longitude) * 100);
if (floatTmp < 10 ) {
strcat(gpsCoords,"0");
itoa(floatTmp, &gpsCoords[strlen(gpsCoords)], 10);
}
else {
itoa(floatTmp, &gpsCoords[strlen(gpsCoords)], 10);
}
strcat(gpsCoords," ");
// Same goes for date and time
int year;
byte month, day, hour, minute, second, hundredths;
gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
itoa(int(hour),charTime,10); // sprintf fails so we use this
strcat(charTime,":");
itoa(int(minute),charTmp,10); // sprintf fails so we use this
strcat(charTime, charTmp);
itoa(int(month),charDate,10); // sprintf fails so we use this
strcat(charDate,"/");
itoa(int(day),charTmp,10); // sprintf fails so we use this
strcat(charDate, charTmp);
strcat(charDate,"/");
itoa(int(year),charTmp,10); // sprintf fails so we use this
strcat(charDate, charTmp);
int altitude = int(gps.f_altitude());
itoa(altitude,gpsAlt,10); // sprintf fails so we use this
strcat(gpsAlt,"M");
// XXX there is some sort of compiler bug here. This adds it to gpsCoords not gpsAlt
}
July 1, 2011 at 6:55 am #1362MichaelKeymasterI’m glad you’ve made progress. You can’t use the serial monitor for debugging if the gps is connected to the uart. The uart can only communicate with one device. To debug, why not just print to the tv screen?
Tv.println()Ok, here’s the deal with the gps overlay sketch: there’s barely enough SRAM for it to work, and any mods you make are likely to push it over the limit, which causes the arduino to freeze up or put funny lines of pixels on the screen. I’m not sure you’ll be able to do much more than the sketch I provided. You’re doing super cool stuff and I hope your memory usage can be trimmed down. String literals are expensive so consider storing them in flash memory with PROGMEM (see arduino site).
I found it critical to limit gps output to rmc and GGA. Or it didn’t work.
I’ll look at your code more next week but I’m on vacation in London now and only have an iPod and typing is tedious…
-
AuthorPosts
- You must be logged in to reply to this topic.