Hi NightCrawler... yes, those 2 lines just print blank lines to make reading the data easier when it's amongst other text on screen...
Cheers
Greg.
Hi NightCrawler... yes, those 2 lines just print blank lines to make reading the data easier when it's amongst other text on screen...
Cheers
Greg.
Thanks for your response greg.
Hey guys... Any further assistance? I haven't been able to sort this one out yet...
Cheers
Greg
I haven't been able to sort this one out yet...
And we haven't been able to see your serial output.
ask and you shall recieve...
I'll break it down line by line so you can see the order more easily. I've "X'd" out my phone number but don't take that personally...
Arduino RX line:-
+CMT: "+61430xxxxxx","","13/03/21,17:24:28+40" [sub]incoming message origin date and time[/sub]
Locate [sub]incoming command[/sub]
$GPSACP: 072449.000,2728.3193S,15302.3512E,6.75,104.0,3,097.58,0.00,0.00,210313,03 [sub]GPS response to command[/sub]
OK
>
>
>
>
+CMGS: 221
OK
AT$GPSACP [sub]Text request in response to "Locate" command[/sub]
AT+CMGS=0430xxxxxx [sub]number to send text response to[/sub]
Current Location, Course, & Speed [sub]actual text output sent to my phone[/sub]
Lat
Lon
COG
Speed Knots
Hope this is clear and helpful.
hmmm... preview didn't work and that's not clear... take 2!
incoming text message (arduino serial RX)
+CMT: "+61430xxxxxx","","13/03/21,17:24:28+40"
Locate
Arduino output to GPS (arduino serial TX)
AT$GPSACP
GPS response to request (arduino RX line)
$GPSACP: 072449.000,2728.3193S,15302.3512E,6.75,104.0,3,097.58,0.00,0.00,210313,03
arduino output text and send command(arduino TX line)
AT+CMGS=0430xxxxxx
Current Location, Course, & Speed
Lat
Lon
COG
Speed Knots
And, which of that serial output came from the TinyGPS library? Isn't that what we are trying to debug?
GPS response to request (arduino RX line)
$GPSACP: 072449.000,2728.3193S,15302.3512E,6.75,104.0,3,097.58,0.00,0.00,210313,03
Are you certain that THIS is what the TinyGPS library is expected to parse?
yes... I know GPS ACP is not a standard tiny GPS sentence... hence my problem.
yes... I know GPS ACP is not a standard tiny GPS sentence... hence my problem.
I know that, too. You modified the TinyGPS library to add support. The first thing to determine is that the TinyGPS library does indeed get the data you expect it to get. Until then, it's all guessing, which isn't useful.
Add Serial.print() statement to TinyGPS to confirm, or refute, that term_complete() gets a string to process that contains what you expect it to contain.
Well part of your problem, is that GPS sentence which you have there, does not actually conform to the NMEA standard. The semi-colon is non-standard, and there is no asterisk preceding the checksum.
That tinygps code is not easy to understand, it does quite a few things which are obscure and tricky and the author of it is clearly a very old-school C and assembly language type of guy. Nevertheless, I have written my own version based on the structure of tinygps, ( because I wanted to extract all the satellite info, which it ignores ), and it all works. And I could certainly implement your string in my system as well, if I had any need to, which I don't. It is certainly possible to work around the non-standard nature of your GPS string, too.
Thanks Gents...
PaulS, I'll add add a line or to that to prove whether or not the data is being processed.
michinyon, I see your point too, I had assumed that GPSACP was in fact in standard format but apparently not! I'll do a bit more research and see if my device can deliver the standard NMEA responses.
Onward and forward!
Back soon with the results!!!
Cheers
Greg.
Eureka!!!... Well almost... I have the GPS data being parsed reliably and all is well except I have a minor instability issue which is I suspect due to RAM shortage. Unfortunately for me the system is a messaging system ad I've implemented a variable called "Message".... All constant Serial.print statements have been placed in program memory (using showString(PSTR("statement here"));)... I'm hoping it's possible to do the same thing (ie:- tuck away in progmem) with variables. showString statement doesn't seem to like variables... Is there a means of achieving this progmem storage of (and I know it sounds weird but...) a constant variable?
To try to clarify, I have a single variable name "message"which, dependent on input status could be any one of 15 different text strings. These 15 or so messages are fixed and never change but as we all know, strings steal RAM unless you can store them in progmem.
Again, any assistance is most welcome...
Cheers
Greg.
Usually strings are the first things to think about putting in progmem but you can store any constant data in progmem. If you're choosing between a number of fixed strings you can either store the progmem pointers in an array and store the array index value in a normal variable, or copy the relevant string out of progmem into an ordinary char array (easier to code but taking up more memory).
Thanks Milton,
I've attempted to implement this method with some unexpected results. As soon as I add the code below all operation of the device seems to stop. Even the setup code won't execute. Undoubtedly this is a result of my inept application of the solution but I'm at a loss as to why.
Everything compiles properly but no go when uploaded to the arduino.
Here's what I've added to set up the tables, and the first line of the setup routine which contains a call for 1 of the message values. You'll see that I've simply REM'd the original message value out...
prog_char message_0[] PROGMEM = "Absconder";
prog_char message_1[] PROGMEM = "Bilge Alarm Clear.";
prog_char message_2[] PROGMEM = "Emergency Pump Stop.";
prog_char message_3[] PROGMEM = "Emergency Bilge Pump Activated.";
prog_char message_4[] PROGMEM = "Bilge Alarm Active.";
prog_char message_5[] PROGMEM = "Bilge Pump Stop.";
prog_char message_6[] PROGMEM = "Bilge Pump Running.";
prog_char message_7[] PROGMEM = "FWD Bilge Alarm Clear.";
prog_char message_8[] PROGMEM = "FWD Emergency Pump Stop.";
prog_char message_9[] PROGMEM = "FWD Emergency Bilge Pump Activated.";
prog_char message_10[] PROGMEM = "FWD Bilge Alarm Active.";
prog_char message_11[] PROGMEM = "FWD Bilge Pump Stop.";
prog_char message_12[] PROGMEM = "FWD Bilge Pump Running.";
prog_char message_13[] PROGMEM = "Hatch Secure.";
prog_char message_14[] PROGMEM = "Unauthorised Access.";
prog_char message_15[] PROGMEM = "Cabin Clear.";
prog_char message_16[] PROGMEM = "Intruder Alert.";
prog_char message_17[] PROGMEM = "Mains Offline.";
prog_char message_18[] PROGMEM = "Mains Available.";
prog_char message_19[] PROGMEM = "Engine Battery Volts Low.";
prog_char message_20[] PROGMEM = "Engine Battery Volts High.";
prog_char message_21[] PROGMEM = "Engine Battery Normal.";
prog_char message_22[] PROGMEM = "House Battery Volts Low.";
prog_char message_23[] PROGMEM = "House Battery Volts High.";
prog_char message_24[] PROGMEM = "House Battery Normal.";
prog_char message_25[] PROGMEM = "Fridge temp High.";
prog_char message_26[] PROGMEM = "Fridge Temp OK.";
prog_char message_27[] PROGMEM = "Cabin Temp High.";
prog_char message_28[] PROGMEM = "Cabin Temp Normal.";
prog_char message_29[] PROGMEM = "All Clear";
prog_char message_30[] PROGMEM = "Lights On";
prog_char message_31[] PROGMEM = "Onboard Mode Active";
prog_char message_32[] PROGMEM = "Surveillence Mode Active";
prog_char message_33[] PROGMEM = "Anchor Watch Mode Active";
prog_char message_34[] PROGMEM = "All Stop";
PROGMEM const char *message_table[] = {
message_0,
message_1,
message_2,
message_3,
message_4,
message_5,
message_6,
message_7,
message_8,
message_9,
message_10,
message_11,
message_12,
message_13,
message_14,
message_15,
message_16,
message_17,
message_18,
message_19,
message_20,
message_21,
message_22,
message_23,
message_24,
message_25,
message_26,
message_27,
message_28,
message_29,
message_30,
message_31,
message_32,
message_33,
message_34
} ;
char buffer [35];
void setup(){
Vessel_Name = strcpy_P(buffer, (char*)pgm_read_word(&(message[0]))); //"Absconder";
If you could point me to where I've messed it up I'd be very grateful.
Cheers
Greg.
Try this:
Vessel_Name = strcpy_P(buffer, (char*)pgm_read_word(message[0])); //"Absconder";
Pete
Thanks Pete,
I made the changes you suggested and it certainly changed things... The code plug went from around 12Kto over 14K! I figure the "(&" points to something somewhere that isn't direct to the stored string???
Alas, the change in operation was not quite what I was hoping for. My otherwise functional code seems to hang at the first call of a message from progmem. As a test I REM'd out the call for vessel name and the next part of the code ran normally. Once another message was called however all serial activity ceased and the arduino rebooted itself. This sequence continued until I de-powered the arduino.
here's a little test sketch to show exactly what's happening... Hopefully someone will see where I'm going wrong...
#include <avr/pgmspace.h>
String message;
String Vessel_Name;
prog_char message_0[] PROGMEM = "Absconder";
prog_char message_1[] PROGMEM = "Bilge Alarm Clear.";
prog_char message_2[] PROGMEM = "Emergency Pump Stop.";
prog_char message_3[] PROGMEM = "Emergency Bilge Pump Activated.";
prog_char message_4[] PROGMEM = "Bilge Alarm Active.";
prog_char message_5[] PROGMEM = "Bilge Pump Stop.";
prog_char message_6[] PROGMEM = "Bilge Pump Running.";
prog_char message_7[] PROGMEM = "FWD Bilge Alarm Clear.";
prog_char message_8[] PROGMEM = "FWD Emergency Pump Stop.";
prog_char message_9[] PROGMEM = "FWD Emergency Bilge Pump Activated.";
prog_char message_10[] PROGMEM = "FWD Bilge Alarm Active.";
prog_char message_11[] PROGMEM = "FWD Bilge Pump Stop.";
prog_char message_12[] PROGMEM = "FWD Bilge Pump Running.";
prog_char message_13[] PROGMEM = "Hatch Secure.";
prog_char message_14[] PROGMEM = "Unauthorised Access.";
prog_char message_15[] PROGMEM = "Cabin Clear.";
prog_char message_16[] PROGMEM = "Intruder Alert.";
prog_char message_17[] PROGMEM = "Mains Offline.";
prog_char message_18[] PROGMEM = "Mains Available.";
prog_char message_19[] PROGMEM = "Engine Battery Volts Low.";
prog_char message_20[] PROGMEM = "Engine Battery Volts High.";
prog_char message_21[] PROGMEM = "Engine Battery Normal.";
prog_char message_22[] PROGMEM = "House Battery Volts Low.";
prog_char message_23[] PROGMEM = "House Battery Volts High.";
prog_char message_24[] PROGMEM = "House Battery Normal.";
prog_char message_25[] PROGMEM = "Fridge temp High.";
prog_char message_26[] PROGMEM = "Fridge Temp OK.";
prog_char message_27[] PROGMEM = "Cabin Temp High.";
prog_char message_28[] PROGMEM = "Cabin Temp Normal.";
prog_char message_29[] PROGMEM = "All Clear";
prog_char message_30[] PROGMEM = "Lights On";
prog_char message_31[] PROGMEM = "Onboard Mode Active";
prog_char message_32[] PROGMEM = "Surveillence Mode Active";
prog_char message_33[] PROGMEM = "Anchor Watch Mode Active";
prog_char message_34[] PROGMEM = "All Stop";
PROGMEM const char *message_table[] = {
message_0,
message_1,
message_2,
message_3,
message_4,
message_5,
message_6,
message_7,
message_8,
message_9,
message_10,
message_11,
message_12,
message_13,
message_14,
message_15,
message_16,
message_17,
message_18,
message_19,
message_20,
message_21,
message_22,
message_23,
message_24,
message_25,
message_26,
message_27,
message_28,
message_29,
message_30,
message_31,
message_32,
message_33,
message_34
} ;
char buffer [35];
void setup(){
Serial.begin(9600);
Vessel_Name = strcpy_P(buffer, (char*)pgm_read_word(message[0])); //"Absconder";
message = strcpy_P(buffer, (char*)pgm_read_word(message[13]));
}
void loop() {
Serial.println ("Vessel Name");
Serial.println (Vessel_Name);
Serial.println ("message");
Serial.println (message);
}
And this is the Serial Monitor output...
Vessel Name
dô?è?àiåsà?Ù?(?g?f?á??????
message
dô?è?àiåsà?Ù?(?g?f?á??????
Vessel Name
dô?è?àiåsà?Ù?(?g?f?á??????
message
dô?è?àiåsà?Ù?(?g?f?á??????
Vessel Name
dô?è?àiåsà?Ù?(?g?f?á??????
message
dô?è?àiåsà?Ù?(?g?f?á??????
Vessel Name
dô?è?àiåsà?Ù?(?g?f?á??????
message
dô?è?àiåsà?Ù?(?g?f?á??????
The device just keeps churning out these 4 lines and quite obviously the progmem calls are not what I'm expecting... Any ideas?
Cheers Greg.
Try this code:
#include <avr/pgmspace.h>
prog_char message_0[] PROGMEM = "Absconder";
prog_char message_1[] PROGMEM = "Bilge Alarm Clear.";
prog_char message_2[] PROGMEM = "Emergency Pump Stop.";
prog_char message_3[] PROGMEM = "Emergency Bilge Pump Activated.";
prog_char message_4[] PROGMEM = "Bilge Alarm Active.";
prog_char message_5[] PROGMEM = "Bilge Pump Stop.";
prog_char message_6[] PROGMEM = "Bilge Pump Running.";
prog_char message_7[] PROGMEM = "FWD Bilge Alarm Clear.";
prog_char message_8[] PROGMEM = "FWD Emergency Pump Stop.";
prog_char message_9[] PROGMEM = "FWD Emergency Bilge Pump Activated.";
prog_char message_10[] PROGMEM = "FWD Bilge Alarm Active.";
prog_char message_11[] PROGMEM = "FWD Bilge Pump Stop.";
prog_char message_12[] PROGMEM = "FWD Bilge Pump Running.";
prog_char message_13[] PROGMEM = "Hatch Secure.";
prog_char message_14[] PROGMEM = "Unauthorised Access.";
prog_char message_15[] PROGMEM = "Cabin Clear.";
prog_char message_16[] PROGMEM = "Intruder Alert.";
prog_char message_17[] PROGMEM = "Mains Offline.";
prog_char message_18[] PROGMEM = "Mains Available.";
prog_char message_19[] PROGMEM = "Engine Battery Volts Low.";
prog_char message_20[] PROGMEM = "Engine Battery Volts High.";
prog_char message_21[] PROGMEM = "Engine Battery Normal.";
prog_char message_22[] PROGMEM = "House Battery Volts Low.";
prog_char message_23[] PROGMEM = "House Battery Volts High.";
prog_char message_24[] PROGMEM = "House Battery Normal.";
prog_char message_25[] PROGMEM = "Fridge temp High.";
prog_char message_26[] PROGMEM = "Fridge Temp OK.";
prog_char message_27[] PROGMEM = "Cabin Temp High.";
prog_char message_28[] PROGMEM = "Cabin Temp Normal.";
prog_char message_29[] PROGMEM = "All Clear";
prog_char message_30[] PROGMEM = "Lights On";
prog_char message_31[] PROGMEM = "Onboard Mode Active";
prog_char message_32[] PROGMEM = "Surveillence Mode Active";
prog_char message_33[] PROGMEM = "Anchor Watch Mode Active";
prog_char message_34[] PROGMEM = "All Stop";
PROGMEM const char *message_table[] = {
message_0,
message_1,
message_2,
message_3,
message_4,
message_5,
message_6,
message_7,
message_8,
message_9,
message_10,
message_11,
message_12,
message_13,
message_14,
message_15,
message_16,
message_17,
message_18,
message_19,
message_20,
message_21,
message_22,
message_23,
message_24,
message_25,
message_26,
message_27,
message_28,
message_29,
message_30,
message_31,
message_32,
message_33,
message_34
}
;
char buffer1[42];
char buffer2[42];
void setup()
{
Serial.begin(9600);
strcpy_P(buffer1, (char*)pgm_read_word(&message_table[0])); //"Absconder";
strcpy_P(buffer2, (char*)pgm_read_word(&message_table[13]));
Serial.println ("Vessel Name");
Serial.println (buffer1);
Serial.println ("message");
Serial.println (buffer2);
}
void loop()
{
}
Pete
Thanks again Pete,
The "message vs message_table" was the problem... I only need the one buffer though as the system only needs to have one message available at any one time...
I'm curious about your other comments though, could you please expand a little for me?
I understand the downside of strings as far as RAM usage goes but I thought that storing this data in progmem eliminated that problem??? Is there a better way to hold all these messages???
Lastly, I'm confused by big enough for the longest message... by my count "FWD Emergency Bilge Pump Activated."; only has 35 characters to store (everything within the quotes including spaces)... Do I need to allow for some overhead data that I'm not aware of? I was trying to be as frugal as possible to minimise the impact on RAM.
Thanks again for the assist and any further info you can give.
Cheers
Greg.
There's a null byte on the end of every C string so the buffer has to be able to hold the longest string plus one character. I usually add a few more just in case later on I add another, longer string to the list.
The strings are held in progmem which does save a lot of ram. But you were then copying two of those strings into two String variables "message" and "Vessel_Name" which are in sram. On their own, doing this once, would be OK, but if you keep copying a different string in, the previous string will be deallocated and then new space allocated for the next string and they might not be in the same space. So now you have unused strings in sram. If the String class doesn't manage memory really well, and it appears that it doesn't, you very soon run out of sram again and get weird errors cropping up. It's best to manage the memory yourself, especially if you're running on a device which only has 2kB to start with.
Pete
Aaaahhhhh, so I could allocate a specific block of say 40 bytes to be used exclusively for this purpose? I'll look around to see if I can find a tutorial or example of this and see if I can implement it... Your explanation might just be the turning point for another issue I'm having...
Thanks again!
Cheers
Greg.