Electronics > Beginners
Arduino Code - volts/amps/power monitor
<< < (8/10) > >>
Rick Law:

--- Quote from: metrologist on March 12, 2018, 08:53:14 pm ---I started off reading fixed point math and that will have to wait.

One idea I had was to build a string and then send that to the serial and SD ports when needed.

String data = "";
data += count;
...
(that ^ wipes out my remaining program space)
...
...
I also implemented the below, but not because I understand it...

--- End quote ---

re: "I also implemented the below, but not because I understand it..."
Actually, I would suggest not to add anything that you don't understand.  It is your program so you need to understand the content and the reason(s) of why certain code is there.
I suggested #define there really for in case you do it again elsewhere such as in debug-print of info.  It would be more harm then good to have things you don't really understand.  Wait till you understand it and make the decision on if it is worthwhile.

re: "(that ^ wipes out my remaining program space)"
Three things that may help you get space back
(1) Check your IDE/C++ compiler and see if it have a flag to optimize space utilization.  If I recall right, gcc (used in Arduino) has -Os to "optimize for size".

(2) Initialization of variables takes a good chuck of space.  If you don't really need that, don't initialize it.

(3) Your Serial.print is killing you.  You have a load of them!  Paulca's suggestion (to solve another issue) in using snprintf (reply #30 in this thread) may be of help to solve that other issue and change the situation here, but I doubt you would have the space for it since you are running out now.

--- Quote from: paulca on March 12, 2018, 07:52:00 pm ---...
char buffer[1024];
memset( buffer, 0, 1024 );
snprintf( buffer, 1024, "%d \t averages %.2fV %.2fA %.2fAh %2.fW %.2fWhr ...
...

--- End quote ---
Your serial print appears to be always printing a value then a literal such as this snip I took from your code:
  void serial(void){
    Serial.print(amps);
    Serial.print("A  ");
    Serial.print(ah);
    Serial.print("Ah  ");
You have a lot of such pairs, so you will save a lot of space by creating a subroutine that print a pair like this:
   void serialPrintPair(float value,char *label) {
      Serial.print(value);
      Serial.print(label);
   }
Now for each such pair of calls, you reduced it to a single call.  That will save you a chunk.  Adding a function do add some bytes-used.  So it takes a few pairs to first pay for the added overhead of having a new function.  After paying the overhead, the rest is pure gravy.

(4) Note if there is a generated byte count displayed after compilation.  Arduino IDE does that (if indeed you are using that IDE).   If you want more information about what use what, there may be a way with your IDE to generates listing files.  When I was coding for ATTINY 13 with gcc (directly without IDE), the assembler listing file was critical in help me fit things into 1K space.  I don't know what is your IDE.  Do some research and see if/how you can grab the listing file.  If all you want out of it is to manage space, you don't have to understand the details of the code generated - you just note the space generated for that line of source.
metrologist:
I'd rather understand the define than avoid it as it looks like it will have a lot of utility.

I also tried creating a float array and string array rather than individual variables. That was so I could loop an index for both serial and SD card outputs. That made the code more difficult to understand and it actually made the compiled code a little larger. I selected a reduced font set and I'm back down to ~23kB.
Rick Law:

--- Quote from: metrologist on March 14, 2018, 09:05:22 pm ---I'd rather understand the define than avoid it as it looks like it will have a lot of utility.
...

--- End quote ---

The way #define is used here is simple to understand so let's see if I can present it as so for you.

#define is a way to ask the pre-compiler part of the compile process to do text replacement/modification.  The pre-compiler hands over a modified source file to the compiler to compile.

// ====================================
// Simple case:
// ====================================
In its simplest form:
#define myDigitalRead digitalReadV2
Every time when it sees the word myDigitalRead in your source (other than comments), it is replaced with the word digitalReadV2

Imagine you have these functions in your code:
    digitalReadV1(value1, value2...) // functioning old version
    digitalReadV2(value1, value2...) // working on this new version
and elsewhere in the codes, you have many calls it to all over the place:
   result = myDigitalRead(something, something...)
All occurrences will turn into:
   result = digitalReadV2(something, something...)

Now, if you want to call the old function again, all you have to do is change the #define statement to:
#define myDigitalRead digitalReadV1
Now all occurrences will turn into:
   result = digitalReadV1(something, something...)


// -----------------------------------------------------------
// I have two type of I2C with different addresses and size
// and the code supports them
#define LCDxSize 20
#define LCDySize 4
#define LCDAddress 0xfb  // I2C address of current LCD installed
// with all my codes using the #defined value above, I can change LCD without
// hunting all over my code when I switch LCD

// ====================================
// Now more complicated #define with parameter:
// ====================================


#define myDoublePrint(label,value)      Serial.print(label);Serial.print(value);
// now, you can just use myDoublePrint and the pre-compiler will convert that
// into two Serial.print for you.
// This would be a good way to compare memory use by make double calls verses
// changing the #define and make it call a function that do the two printing.

//
// ----------- Example: -----------
// make the choice by commenting out one of the #define below
#define myDoublePrint(label,value)      { Serial.print(label);Serial.print(value); }
#define myDoublePrint(label,value)      myNewFunction((label),(value))
   void myNewFunction(char *label,float value) {
      Serial.print(label);Serial.print(value);
   }
//-------------------------------------------------------

Hope that helps you understand simple #define.  If it does, you may even use
#if def(something)
   some codes here in between
#endif
And then there are more complicated ways of using #define to achieve more...  When you feel comfortable with using #define, lots of fun to research what else can be done

By the way, which IDE are you using?
metrologist:
Thanks, Rick. I had thought of #define as a constant and typically saw it used to define a led pin#, but I see how it's being used now.

I am using the Arduino IDE 1.06 and often Notepad++.
Rick Law:

--- Quote from: metrologist on March 15, 2018, 02:49:00 pm ---Thanks, Rick. I had thought of #define as a constant and typically saw it used to define a led pin#, but I see how it's being used now.

I am using the Arduino IDE 1.06 and often Notepad++.

--- End quote ---

You are welcome.  Since you are using Arduino, like most library and IDE, #define is also use to control what source codes are applicable.  For example, things like which register and which bits are used for, say, controlling PWM are typically #defined somewhere.

It will be helpful if you look into #if, #elif, and #endif along with #if def() and #if ndef().  When you have some understanding of those pre-processor commands, if will help you understand Arduino headers files.  You can make out more of what they do.
Navigation
Message Index
Next page
Previous page
There was an error while thanking
Thanking...

Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod