Store › Forums › Video Experimenter › General Discussion › Stuck on Interrupts
- This topic has 33 replies, 3 voices, and was last updated 13 years, 4 months ago by joey.
-
AuthorPosts
-
July 1, 2011 at 5:16 pm #1365joeyMember
@Michael wrote:
I’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?
I would but nothing outputs. 🙂 That’s part of my problem. My smaller sketches without the GPS work so the board is ok. During the loop section of the code you can see tv.out calls. I know it executes because I see the “loop” message each time the loop is executed. Alas, nothing is output on the display though.
@Michael wrote:
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.
Ah ok. I saw the mem debug code in your sketch. I’ll enable that and see what happens. When I upload the numbers at the bottom tell me I use roughly 3000 out of 6000 (as I recall… it’s not in front of me at the moment).
@Michael wrote:
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’ve replaced #define with const int per the docs in order to save space but maybe it’s not enough. If it wasn’t for me needing strings to assemble the output message it would rock. I can’t use STRING because of type conversions and sprintf is just a PoS. strcat/strcpy used with itoa seems to work. I thought about trying PString ( http://arduiniana.org/libraries/pstring/ ) but am not sure how expensive that is.
I’m getting a bad feeling that I may not be able to add the Geiger counter to this stack due to lack memory. 🙂
@Michael wrote:
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…
Nifty. I’ll be there the first of August. I work there but live in the US.
July 2, 2011 at 5:27 pm #1367joeyMemberSo my sketch with debugging code is
Binary sketch size: 14128 bytes (of a 32256 byte maximum)
and the results of the debug code is “511”.
Interesting thing is with the debug code, the sketch fails to run when the VE is plugged in but if I lift it off the risers, presto, the sketch starts working. I do have a felt pad atop the gps receiver. Early on I discovered that the metal top of the receiver would cause the ve to stop working by effectively shorting pins. That’s not the case currently.
July 2, 2011 at 5:45 pm #1368joeyMemberso that debug loop didn’t really tell me what’s going on, so I used this instead
//variables created when compiling, used for debugging
extern int __bss_end;
extern void *__brkval;
int getMemory() {
int freeValue;
if((int)__brkval == 0)
freeValue = ((int)&freeValue) - ((int)&__bss_end);
else
freeValue = ((int)&freeValue) - ((int)&__brkval);
return freeValue;
}
and that tells me 1458
July 2, 2011 at 6:21 pm #1369joeyMemberSo just to ensure my GPS is working on UART, I wrote up this sketch and it works.
#include
TinyGPS gps;
// This is where you declare prototypes for the functions that will be
// using the TinyGPS library.
void getgps(TinyGPS &gps);
void setup() {
Serial.begin(4800);
}
void loop()
{
while(Serial.available()) // While there is data on the RX pin...
{
int c = Serial.read(); // load the data into a variable...
if(gps.encode(c)) // if there is a new valid sentence...
{
getgps(gps); // then grab the data.
}
}
}
// 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);
Serial.print(", ");
Serial.println(longitude,5);
// 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);
//Since month, day, hour, minute, second, and hundr
// 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());
// 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();
}
So I’m still stumped by why my original sketch is not get anything from the GPS.
July 2, 2011 at 6:31 pm #1370joeyMemberOk this is really crazy. I just rewrote the above with pserial and it doesn’t work.
July 2, 2011 at 7:03 pm #1371MichaelKeymasterOk, here are some thoughts:
The memory numbers reported at upload time are for the flash memory and not SRAM.
The routine you used for determining free mem is better than the malloc version I had used. I saw the new approach on dangerousprototypes.com recently.
A value of 511 by my routine means you’ve blown the stack (in my experience)
The large value (1400+) from the new routine is wrong, too. A correct Val is <200.
If your code works well enough with Serial, then that’s great. The serial interrupts may not disrupt the video much.
pserial is primitive and has a small buffer (64?) so if you don’t read data quickly and frequently, maybe it has problems.
July 3, 2011 at 6:34 am #1373MichaelKeymasterAnd I’m still generally confused about how you are using the Arduino’s single UART to communicate with two devices at the same time. I would not expect that to work. I suggest you use the tv as debug output instead of the serial monitor. Just use tv.println to watch your debug output on the screen.
Isn’t your gps module getting confused by all debug info you are writing into it?
July 3, 2011 at 3:50 pm #1374joeyMember@Michael wrote:
If your code works well enough with Serial, then that’s great. The serial interrupts may not disrupt the video much.
When I try to do this, the sketch won’t run with VE on the stack. Take it off, and I get perfect output. Perhaps that’s because I don’t know how to change “tv.set_hbi_hook(pserial.begin(4800));” to “tv.set_hbi_hook(Serial.begin(4800));”. set_hbi_hook is looking for a function, not a serial commands. I don’t understand what’s happening at that low level.
July 3, 2011 at 3:56 pm #1375joeyMember@Michael wrote:
And I’m still generally confused about how you are using the Arduino’s single UART to communicate with two devices at the same time. I would not expect that to work.
I just open up the serial monitor, that’s all.
@Michael wrote:
I suggest you use the tv as debug output instead of the serial monitor. Just use tv.println to watch your debug output on the screen.
And as before, the tv.println DOES NOT WORK. NOTHING is being displayed even thought the loop function appears to be running. This is what’s baffling me. If I use an older sketch, or one of yours, it works. Thus the need to get debug info from elsewhere.
@Michael wrote:
Isn’t your gps module getting confused by all debug info you are writing into it?
I thought that might be the case too. It works fine without the VE using both Serial and pserial. When I turn off all the println’s to pserial with the tv enabled nothing happens. None of the tv.println’s work. No so much as a flicker on the display.
Would a video of what is happening be helpful? I can make one of those.
J
July 4, 2011 at 12:03 am #1376MichaelKeymasterPerhaps that’s because I don’t know how to change “tv.set_hbi_hook(pserial.begin(4800));” to “tv.set_hbi_hook(Serial.begin(4800));”. set_hbi_hook is looking for a function, not a serial commands. I don’t understand what’s happening at that low level.
pserial is a polling version of serial communication. We tell the TVout library to invoke this polling library during the horizontal blanking interval of each line. That’s what the set_hbi_hook does: it tells TVout to invoke this hook function during horizontal blanking interval (HBI). If using ordinary Serial, you don’t need to do this because the Serial library will run an interrupt routine when a character is received. Interrupts interfere with the video processing. The TVout library (which I did not write) uses timer interrupts to get the perfect timing of the video lines. If other interrupts are occuring, the timing is messed up. That’s why you can’t use Serial with TVout. You use pserial as a polling substitute. Hope that helps with the understanding.
I just open up the serial monitor, that’s all.
But that means that the Serial monitor program running on your computer and the GPS are both connected to the single UART on the ATmega328. That won’t work reliably (I can’t believe it works at all!). It’s like using one phone line for two conversations. That’s why NewSoftSerial library was invented — so you can use two serial devices. I actually fried an ATmega328 by accidentally opening a Serial monitor when I had a GPS communicating with the UART. (It got very hot!)
And is your GPS module only outputting RMC and GGA sentences or is it by default outputting all? I really matters. When you have the VE shield connected, your ATmega328 processor is VERY busy processing interrupts and generating video and doesn’t have much time to deal with the GPS. Also, your program above is doing a ton of I/O and that interrupt-driven I/O is going to cause the video generation to not run the way it should. It won’t run fast enough to stay in sync with the TV.
July 4, 2011 at 3:00 pm #1377joeyMemberWell, you are quite possibly right Michael on the memory situation.
I rewrote the program using Pstring (wow, what a difference that makes!) and the size didn’t really change. It didn’t fix anything (other than readability).
So I put some conditional defines in and got TV working without the strings.
I’m guessing that I should try to use PROGMEM to store the strings then? I tried to give it a quick spin but while it compiled, it didn’t work with the tv enabled. I’ve ordered a Mega board. Maybe with it’s increase in RAM I can get it working (assuming the VE will work with the mega).
// 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
// flag for conditional compile
#define TVON
// #define FULLTV
#if defined TVON
#include
#include
#endif
#include
#include
#include
#if defined TVON
TVout tv;
#endif
// 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;
#if defined FULLTV
TinyGPS gps;
// declare the GPS variables
char charTimebuffer[6];
PString charTime(charTimebuffer, sizeof(charTimebuffer));
char charDatebuffer[11];
PString charDate(charDatebuffer, sizeof(charDatebuffer));
char gpsCoordsbuffer[15];
PString gpsCoords(gpsCoordsbuffer, sizeof(gpsCoordsbuffer));
char gpsAltbuffer[6];
PString gpsAlt(gpsAltbuffer, sizeof(gpsAltbuffer));
// 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 messageTopbuffer[96];
PString messageTop(messageTopbuffer, sizeof(messageTopbuffer));
char messageBottombuffer[96];
PString messageBottom(messageBottombuffer, sizeof(messageBottombuffer));
char messageLastlinebuffer[96];
PString messageLastline(messageLastlinebuffer, sizeof(messageLastlinebuffer));
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;
//variables created when compiling, used for debugging
//extern int __bss_end;
//extern void *__brkval;
#endif //FULLTV
void setup() {
#if defined TVON
tv.begin(0);
tv.set_hbi_hook(pserial.begin(4800));
initOverlay();
tv.select_font(font6x8);
tv.fill(0);
#else
pserial.begin(4800);
#endif
}
#if defined TVON
// 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;
}
#endif //tvon
//int getMemory() {
// int freeValue;
// if((int)__brkval == 0)
//freeValue = ((int)&freeValue) - ((int)&__bss_end);
// else
// / freeValue = ((int)&freeValue) - ((int)&__brkval);
// return freeValue;
//}
void loop() {
#if defined FULLTV
while(pserial.available()) { // if there is data on the RX pin...
if(gps.encode(pserial.read())) { // if there is a new valid sentence...
getgps(gps); // then grab the data.
}
}
// temperature
// Fancy TMP36 calc which converts to Farenheit and then clips to a 2 digit degree
int temperature = int(((((analogRead(temperaturePin) * .004882814) - .5) *100) *1.8) +32);
// setup the messages for output on the tv
// clear at start of loop
messageTop.begin();
messageBottom.begin();
messageLastline.begin();
//assemble top message
messageTop.print(callsign);
// assemble bottom message
messageBottom.print(charTime);
messageBottom += " ";
messageBottom.print(charDate);
messageBottom += "Z ";
messageBottom.print(temperature);
messageBottom += "F";
// assemble 2nd bottom meessage
messageLastline.print(gpsCoords);
messageLastline.print(gpsAlt);
#else
char messageTop[]="TEST";
char messageBottom[] = "TEST";
char messageLastline[]="TEST";
#endif // FULLTV
#if defined TVON
// 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);
#endif
}
#if defined FULLTV
// 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);
// clear vars at start of loop
gpsCoords.begin();
charTime.begin();
charDate.begin();
gpsAlt.begin();
// let's process!
gpsCoords.print(latitude);
gpsCoords += ", ";
gpsCoords.print(longitude);
// 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);
charTime.print(hour);
charTime += ":";
charTime.print(minute);
charDate.print(month);
charDate += "/";
charDate.print(day);
charDate += "/";
charDate.print(year);
int altitude = int(gps.f_altitude());
gpsAlt.print(altitude);
gpsAlt += "M";
}
#endif //FULLTV
July 4, 2011 at 4:05 pm #1378joeyMemberI did the math and confirmed that I’m running over on memory.
I also recomputed the buffer lengths and I got stuff on the screen now! Yay! I have a strange condition that happens when the GPS is available, the overlay stops.
// 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
#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;
// declare the GPS variables
char charTimebuffer[6];
PString charTime(charTimebuffer, sizeof(charTimebuffer));
char charDatebuffer[11];
PString charDate(charDatebuffer, sizeof(charDatebuffer));
char gpsCoordsbuffer[15];
PString gpsCoords(gpsCoordsbuffer, sizeof(gpsCoordsbuffer));
char gpsAltbuffer[6];
PString gpsAlt(gpsAltbuffer, sizeof(gpsAltbuffer));
// 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 messageTopbuffer[6];
PString messageTop(messageTopbuffer, sizeof(messageTopbuffer));
char messageBottombuffer[24];
PString messageBottom(messageBottombuffer, sizeof(messageBottombuffer));
char messageLastlinebuffer[22];
PString messageLastline(messageLastlinebuffer, sizeof(messageLastlinebuffer));
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;
void setup() {
tv.begin(0);
tv.set_hbi_hook(pserial.begin(4800));
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() {
while(pserial.available()) { // if there is data on the RX pin...
if(gps.encode(pserial.read())) { // if there is a new valid sentence...
getgps(gps); // then grab the data.
}
}
// temperature
// Fancy TMP36 calc which converts to Farenheit and then clips to a 2 digit degree
int temperature = int(((((analogRead(temperaturePin) * .004882814) - .5) *100) *1.8) +32);
// setup the messages for output on the tv
// clear at start of loop
messageTop.begin();
messageBottom.begin();
messageLastline.begin();
//assemble top message
messageTop.print(callsign);
// assemble bottom message
messageBottom.print(charTime);
messageBottom += " ";
messageBottom.print(charDate);
messageBottom += "Z ";
messageBottom.print(temperature);
messageBottom += "F";
// assemble 2nd bottom meessage
messageLastline.print(gpsCoords);
messageBottom += " ";
messageLastline.print(gpsAlt);
// 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);
}
// 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);
// clear vars at start of loop
gpsCoords.begin();
charTime.begin();
charDate.begin();
gpsAlt.begin();
// let's process!
gpsCoords.print(latitude);
gpsCoords += ", ";
gpsCoords.print(longitude);
// 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);
charTime.print(hour);
charTime += ":";
charTime.print(minute);
charDate.print(month);
charDate += "/";
charDate.print(day);
charDate += "/";
charDate.print(year);
int altitude = int(gps.f_altitude());
gpsAlt.print(altitude);
gpsAlt += "M";
}
July 4, 2011 at 4:13 pm #1379MichaelKeymasterThe VE does NOT work on an Arduino Mega!
July 4, 2011 at 4:55 pm #1380joeyMemberAh, well it’s good that I got it working on the Uno then. 🙂
Everything is working as you’d expect up until it does this
while(pserial.available()) { // if there is data on the RX pin...
if(gps.encode(pserial.read())) { // if there is a new valid sentence...
getgps(gps); // then grab the data.
}
}specifically ” if(gps.encode(pserial.read()))” at which point, something bad happens and the overlay disappears on the TV. I’ve been able to tell that it happens on the very first execution. I’m wondering if it’s screwing up the hbi hook?
edit: If I reset the stack when this happens occasionally the overlay will pop up, appear to lose tracking, and scroll up for a split second.
July 4, 2011 at 5:11 pm #1381joeyMemberaw heck, I found it. If I removed some more of the buffer it goes through. So it’s a space issue. 🙁
-
AuthorPosts
- You must be logged in to reply to this topic.