Offline
Newbie
Karma: 1
Posts: 14
|
 |
« on: February 13, 2011, 07:23:07 am » |
Hello, as an exercise I've written a sketch to take ascii data in on the serial port on an Arduino Uno and convert it to Morse code. I'm finding that if I comment out some of the code in a routine producing help text it works, if not commented out, it does not. The code is here: http://petezilla.webdev.fire/public/embedded/arduino/morse(too long to sensibly post in the forum). The block of code I've commended out runs from lines 256 - 278. I'm wondering if the micro-controller is running out of memory? I've produced the sketch with no particular regard for memory useage. However, the code resides in program memory, not SRAM, so I'm not certain it is a SRAM issue. Thoughts?
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Faraday Member
Karma: 15
Posts: 2852
Gorm deficient
|
 |
« Reply #1 on: February 13, 2011, 07:31:40 am » |
Link is broken/incomplete
|
|
|
|
|
Logged
|
Per Arduino ad Astra
|
|
|
|
Netherlands
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #2 on: February 13, 2011, 07:48:15 am » |
Are you in the default arduino environment programming? If so, you can see in the bottom of the screen how large your sketch is and how much memory available is.
Are you dynamically allocating memory with malloc functions?
|
|
|
|
|
Logged
|
|
|
|
|
UK
Offline
Faraday Member
Karma: 15
Posts: 2852
Gorm deficient
|
 |
« Reply #3 on: February 13, 2011, 07:53:49 am » |
If you have any large tables that aren't defined as being in PROGMEM, then they will use RAM.
|
|
|
|
|
Logged
|
Per Arduino ad Astra
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6809
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #4 on: February 13, 2011, 08:11:51 am » |
To find out what RAM is being used
open a DOS window navigate to the build folder, (to find this hold SHIFT while compiling your code). The path will be something like
C:\Users\<yourname>\AppData\Local\Temp\build3014820664802798593.tmp
run
avr-size <yourprogname>.cpp.elf
You'll get a result like this
text data bss dec hex filename 1010 0 9 1019 3fb <yourprogname>.cpp.elf
If data and bss add up to anything like maybe 1800 (hard to tell what, it depends on the program) you're in trouble
______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6809
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #6 on: February 13, 2011, 10:29:41 am » |
With the code commented out
text data bss dec hex filename 9656 760 201 10617 2979 blink.cpp.elf
with code included
text data bss dec hex filename 9860 1550 201 11611 2d5b blink.cpp.elf
That's 1751 bytes of RAM used not counting the stack. It's getting in the dodgy area.
Try just removing a few lines to see if that fixes the probem.
______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 1
Posts: 14
|
 |
« Reply #7 on: February 13, 2011, 10:30:15 am » |
If you have any large tables that aren't defined as being in PROGMEM, then they will use RAM.
I have used a number of strings, using the string object. They are not especially large, but on the other hand there is not a lot of SRAM. The code I comment out to make things work is in the serial routines, with fixed strings. Given that my variables are altered during the course of running the program it would not be a good idea to use PROGMEM I would have thought. I wonder however whether putting the help information below into a variable stored in program memory might help. Another solution, probably the best, would be to put it into the EEPROM. However, I'm not sure if there is a way that data could be included in the sketch. I assume I'd have to upload it separately. However, I'm assuming it is a memory issue - am I right? Routine below: void help() { Serial.println("~"); Serial.println("~USB ASCII to Morse converter."); Serial.println("~"); Serial.println("~Help:"); Serial.println("~ ##H: Print help (upper case H)."); Serial.println("~ ##1: Rate 5 words per minute"); Serial.println("~ ##2: Rate 10 words per minute"); Serial.println("~ ##3: Rate 15 words per minute"); Serial.println("~ ##4: Rate 20 words per minute"); Serial.println("~ ##5: Rate 40 words per minute"); /* If the following is not commented out then the arduino produces no output. */ /* Serial.println("~"); Serial.println("~Add # to the end of a line to repeat message."); Serial.println("~A # before any letter omits spaces to they can be run-"); Serial.println("~together to generate prosigns, e.g. #CT (start of message)."); Serial.println("~Carriage return (13) causes message to be transmitted."); Serial.println("~"); Serial.println("~Commands and Messages:"); Serial.println("~Lines beginning in tilde ~ are information"); Serial.println("~Prompt for user input is >"); Serial.println("~Messages:"); Serial.println("~ <Ready = Awaiting commands or data."); Serial.println("~ <Sending = Sending morse."); Serial.println("~ <Wait = Please do not send data, buffers near full."); Serial.println("~ <Overrun = Too much information in buffers. Contents "); Serial.println("~ deleted without being sent. Send data again"); Serial.println("~ in smaller chunks."); Serial.println("~"); Serial.println("~Basic idea is you send data, when a <Wait is received then"); Serial.println("~continue passing current word then hit return to send chunk"); Serial.println("~before sending more data."); Serial.println(""); */ }
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 1
Posts: 14
|
 |
« Reply #8 on: February 13, 2011, 10:47:04 am » |
With the code commented out
text data bss dec hex filename 9656 760 201 10617 2979 blink.cpp.elf
with code included
text data bss dec hex filename 9860 1550 201 11611 2d5b blink.cpp.elf
That's 1751 bytes of RAM used not counting the stack. It's getting in the dodgy area.
Try just removing a few lines to see if that fixes the probem.
______ Rob
Interesting, with the help commented out as below I can send 10 characters but with 20 it hangs. I suspect that this is it running out of memory - perhaps a buffer over-run type problem, not that I have a fixed length buffer, but I do have finite ram. void help() { Serial.println("~"); Serial.println("~USB ASCII to Morse converter."); Serial.println("~"); Serial.println("~Help:"); Serial.println("~ ##H: Print help (upper case H)."); Serial.println("~ ##1: Rate 5 words per minute"); Serial.println("~ ##2: Rate 10 words per minute"); Serial.println("~ ##3: Rate 15 words per minute"); Serial.println("~ ##4: Rate 20 words per minute"); Serial.println("~ ##5: Rate 40 words per minute"); /* If the following is not commented out then the arduino produces no output. */ Serial.println("~"); Serial.println("~Add # to the end of a line to repeat message."); Serial.println("~A # before any letter omits spaces to they can be run-"); Serial.println("~together to generate prosigns, e.g. #CT (start of message)."); Serial.println("~Carriage return (13) causes message to be transmitted."); Serial.println("~"); Serial.println("~Commands and Messages:"); Serial.println("~Lines beginning in tilde ~ are information"); Serial.println("~Prompt for user input is >"); /* Serial.println("~Messages:"); Serial.println("~ <Ready = Awaiting commands or data."); Serial.println("~ <Sending = Sending morse."); Serial.println("~ <Wait = Please do not send data, buffers near full."); Serial.println("~ <Overrun = Too much information in buffers. Contents "); Serial.println("~ deleted without being sent. Send data again"); Serial.println("~ in smaller chunks."); Serial.println("~"); Serial.println("~Basic idea is you send data, when a <Wait is received then"); Serial.println("~continue passing current word then hit return to send chunk"); Serial.println("~before sending more data."); Serial.println(""); */ }
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX
Offline
Faraday Member
Karma: 41
Posts: 5165
CMiYC
|
 |
« Reply #9 on: February 13, 2011, 11:05:04 am » |
If so, you can see in the bottom of the screen how large your sketch is and how much memory available is.
This is not the case. This message is the amount of Flash (or program) storage being used and what is left. It has nothing to do with the RAM at Runtime. It is entirely possible to have a sketch that takes up 15k of Flash/Program Memory and only use a couple hundred bytes of RAM.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 137
Posts: 19006
I don't think you connected the grounds, Dave.
|
 |
« Reply #10 on: February 13, 2011, 12:02:04 pm » |
All those Serial.print strings are wasting RAM - move them to PROGMEM.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Offline
Newbie
Karma: 1
Posts: 14
|
 |
« Reply #11 on: February 13, 2011, 12:21:36 pm » |
All those Serial.print strings are wasting RAM - move them to PROGMEM.
You mean something like the string demo in: http://www.arduino.cc/en/Reference/PROGMEMFrom what you are suggesting then, if I have a line: Serial.println("Hello world!"); then the complied program puts "Hello world!" in RAM, uses it and does not release it? Just curious.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Offline
Brattain Member
Karma: 137
Posts: 19006
I don't think you connected the grounds, Dave.
|
 |
« Reply #12 on: February 13, 2011, 12:34:00 pm » |
then the complied program puts "Hello world!" in RAM, uses it and does not release it? How could it "release it"?
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Offline
Newbie
Karma: 1
Posts: 14
|
 |
« Reply #13 on: February 13, 2011, 01:38:15 pm » |
then the complied program puts "Hello world!" in RAM, uses it and does not release it? How could it "release it"? Perhaps a bad choice of words. However, the implication that my many Serial.println command consume RAM implies that those RAM locations are not reused. I.e. Say "Hello World" is written to memory locations say 100-110 (decimal). These are now output to serial. Now I want to send to the serial port "Hello world again" that implies that instead of writing from program memory to RAM "Hello World Again" in memory locations say 100-116 that it is writing them in locations 111-127. 100-110 is not being re-used. Seems odd to me. Pete
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX
Offline
Faraday Member
Karma: 41
Posts: 5165
CMiYC
|
 |
« Reply #14 on: February 13, 2011, 01:47:37 pm » |
It would stand to reason that the complier would only store one copy of a constant, but I do not know if this is the case. In your code each of your string constants are different.
The complier does not know how many times a constant (string or otherwise) will be used (what if there was a loop?), so the constant has to be stored in RAM at all times.
By moving the (string) constants into PROGMEM, you never actually copy the constant into RAM.
|
|
|
|
|
Logged
|
|
|
|
|
|