Pages: [1]   Go Down
Author Topic: How divide a sketch  (Read 678 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, i wanted to know if it´s possible divide a sketch. I mean  I want to make a sketch with main program and then create other sketch with all the functions i use in the main sketch, is that possible? is only to avoid use a very long main sketch. Thanks for all =D
Logged

BCC AZ USA
Offline Offline
Edison Member
*
Karma: 35
Posts: 1213
It gets hot so it must be working
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Look into #include directive.  It is not just for libraries.
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26970
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You can also use Tabs within the IDE, the button for them is over on the right hand side.
For larger programs, I make a few:
main tab is the file name, I put some note there.
then a_presetup, all the # stuff, pin assigments, variable declarations
b_setup, this is void setup
c_void, the main sketch, maybe broken up also
d_more_void for example
e_functions
f_more_functions

sometimes I'll have a tab with just
void loop()
{

and then later

}// end void loop

so that  CTRL-T, autoformat, will work correctly on the intermediate tabs and not choke on a missing { or }
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12631
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You can also use Tabs within the IDE, the button for them is over on the right hand side.
For larger programs, I make a few:
main tab is the file name, I put some note there.
then a_presetup, all the # stuff, pin assigments, variable declarations
b_setup, this is void setup
c_void, the main sketch, maybe broken up also
d_more_void for example
e_functions
f_more_functions


This sounds alarmingly as if you are splitting function implementations across files, which is a very poor idea IMO. If a function is getting unwieldy, it should be refactored into multiple functions (which may be stored in the same file, or separate files).
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Atlanta, USA
Offline Offline
Edison Member
*
Karma: 53
Posts: 1790
AKA: Ray Burne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@CrossRoads:
The multiple program file extensions are "*.ino" ?

@PeterH:
Am I remembering correctly that Arduino GUI does not prototype functions for all but the main INO ?  I cannot remember if this was a pre-1.0 issue or if it is even still an issue.

Thx


Ray
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26970
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sounds only. In actual implementation it has worked out quite well.
The tabs are broken up into complete sections that can stand alone.
I think they all appear in the directory as .ino.  I open the main file, the tabs are there for editing. 
I think if you try to open one of the tabs that the main file and all tabs open anyway.

Largest was 7 tabs that compile to 13000+ bytes and works well.
Naming them alphabetically seems to keep the program flow I wanted.
I don't actually have any functions outside of setup & loop (they are technically functions, yes?), it's more state machine like with a check for a flag to indicate if the code in a tab is to run or not:
100mS elapsed? update time counters, set the display update flag.
Serial message recieved? update stuff as needed, set the display update flag.
RF message received? update stuff as needed, set the display update flag.
Update flag set? Clear it and update the display with data set elsewhere.

So most of the time it's 4 checks to see that nothing has happened, resulting in a very responsive system when something does happen.

In my programming of Arduino since summer-ish 2010, I have not written any function outside of setup & loop, only 2 ISRs for interrupts (one to wake from sleep for a remote, and one to deal with PCINTs from 3 rotary encoders). Everything else has been setting flags and then acting on them, which results in function-like operation I suppose without all the time of popping stuff on & off the stack and all that goes on with a function call.
Works for me.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Atlanta, USA
Offline Offline
Edison Member
*
Karma: 53
Posts: 1790
AKA: Ray Burne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
In actual implementation it has worked out quite well.

I have also used the technique a few times when writing long code.  I never had an issue the few times, but the function prototyping "thing" came to mind because I answered a post a day or two ago in that regard.  I have never tried to "break" the automatic prototyping... I guess this is one of those Ummmm issues.


Ray
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26970
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The way I understand it, prototyping for functions is the same as declaring variable types (byte, int, etc), and the IDE is pretty good at doing that automatically, but if you do it explicitly then you get what you want.
Now, since I have never actually written a function (outside of a couple of ISRs and used a couple volatile variables ), I have never run into any issues with that.
I also globally declare all my variables so I don't run into scope issues, and any one piece of the sketch can use data from any other part of the sketch.
As I've said before, it works for me in this embedded world.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Atlanta, USA
Offline Offline
Edison Member
*
Karma: 53
Posts: 1790
AKA: Ray Burne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I also globally declare all my variables so I don't run into scope issues, and any one piece of the sketch can use data from any other part of the sketch.

And this is what I was attempting to convey to the new member CactusFace in a separate but related post, but I come from languages with strong scoping rules and I generally go lightly on global vars, not consciously, but just a habit.

So, back to the original question....

Can you break-up your sketch into multiple modules?  Yes, you can by making new tabs in the Arduini GUI and giving the tabs filenames ending in the ".ino" extension.  Keep void loop() and void setup() in the default automatically created) module.

If your functions are simple, there should be no problems.  But, read this: http://forum.arduino.cc/index.php?topic=45874.0
Your mileage may vary!


Ray
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26970
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You don't have to give the tabs .ino names,the IDE does that by itself when you save the file.
This is what a program might look like, and what results are these files.


* use_of_tabs.jpg (69.95 KB, 960x720 - viewed 24 times.)
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12631
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's your sketch and whatever works for you at the end of the day, but even on the small programs suitable to be run on an Arduino it is IMO worth writing structured code and that would normally eliminate the need for very long functions. I'd prefer functions to be small enough to see the whole thing on the screen, and IMO if it's too long to be stored in a single file it's certainly too long to be a single function. If you're offended by the thought of a extra function call you can always declare them as inline functions, but I would have thought the overhead of a function call was irrelevant in all but the most performance-critical applications.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 534
Posts: 26970
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's an example of what I would put in a tab. By your explanation this would be broken up into numerous somethings.
I'd rather see one tab that performs a task, maybe split in two if it was too tedious to scroll thru, and the 2nd would just be a continuation of the first.  What I really despise is trying to read some code that's been functionalized to death and it becomes a struggle just to find the functions just to see what is going on.
Software engineers seem to enjoy that tho.  Not my cup of tea (not that I drink tea, unless it has lemon & sugar to cover up the tea taste smiley-cool

Code:
//d_serial_receive

// see if data came in, add to end of the array, or adjust movement
if (Serial.available()>0){
  incomingByte = Serial.read();
  goodFont = 3;

  // mapping from incoming character to font_array or other commands: \ + = < >
  // invalid characters are not defined and are ignored
  switch(incomingByte){
  case 0x20:
    fontArrayPointer = 0; // space
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x21:
    fontArrayPointer = 5; // !
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x27:
    fontArrayPointer = 10; // '
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x2c:
    fontArrayPointer = 15; // ,
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x23:
    fontArrayPointer = 20; // #
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x28:
    fontArrayPointer = 25; //  dash -
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x29:
    fontArrayPointer = 30; //  dash )
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x2d:
    fontArrayPointer = 35; //  dash (
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x2e:
    fontArrayPointer = 40; // period .
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x2f:
    fontArrayPointer = 45; // slash /
    goodFont = 1; // good character to add to displayArray
    break;
  case 0x30:
    fontArrayPointer = 50; // 0
    goodFont = 1; // good character to add to displayArray
    break;
:
bunch deleted to fit the post limits
:
  case 0x5c:
    // use 0x5c '\' for backspace to delete characters
    move_control = backspace;
    goodFont = 2; // not a character to add to displayArray
    break;
  case 0x50:
    // capital P for switch to PC data entry
    // need 3 in a row
    PCmode = PCmode +1;
    if (PCmode == 3){
      //dataEntry = PC;
      PCmode = 0;
      //Serial.println ("Clearing EEPROM length ");
      EEPROM.write(0,0);
      EEPROM.write(1,0);
      //Serial.println("Resetting display ");
      displayStart = 1;
      displayEnd = 8;
      for (x = 0;x<1024;x=x+1){
        displayArray[x] = 0;
      }
    }
    break;
  case 0x53:
    // capital S for saving to EEPROM
    SaveMode = SaveMode + 1;
    if (SaveMode == 3){
      //dataEntry = Memory;
      SaveMode = 0;
      // save length in EEPROM, write displayArray to EEPROM
      Serial.print ("saving to EEPROM, displayEnd = ");
      EEPROM.write(0, (lowByte (displayEnd)));
      EEPROM.write(1, (highByte (displayEnd)));
      Serial.print (EEPROM.read(1));
      Serial.print (" ");
      Serial.println (EEPROM.read(0));
      for (x = 2; x<(arraySize); x=x+1){
        EEPROM.write(x, displayArray[x]);
        Serial.print(x);
        Serial.print (" ");
        Serial.println (EEPROM.read(x));
      }

      Serial.print ("EEPROM address 0 = ");
      Serial.println (EEPROM.read(0));
      Serial.print ("EEPROM address 1 = ");
      Serial.println (EEPROM.read(1));

      highEEPROM = EEPROM.read(1);
      lowEEPROM = EEPROM.read(0);
      EEPROMend = (highEEPROM<<8) + lowEEPROM;
      Serial.print ("EEPROMend = ");
      Serial.println (EEPROMend);

    }
    break;
  } // end switch

  // is there room to add characters?
  // array defined as arraySize/6 characters long
  //
  if ((displayEnd < (arraySize - 6)) && (goodFont ==1)){
    goodFont = 0; // reset for next pass
    // add in 6 bytes, 5 from fontArray in PROGMEM & 1 spacer column

    displayArray[displayEnd] = pgm_read_byte(&fontArray[fontArrayPointer]); // font column0
    displayArray[displayEnd+1] = pgm_read_byte(&fontArray[fontArrayPointer+1]); // font column1
    displayArray[displayEnd+2] = pgm_read_byte(&fontArray[fontArrayPointer+2]); // font column2
    displayArray[displayEnd+3] = pgm_read_byte(&fontArray[fontArrayPointer+3]); // font column3
    displayArray[displayEnd+4] = pgm_read_byte(&fontArray[fontArrayPointer+4]); // font column4
    displayArray[displayEnd+5] = 0x00; // spacer/blank column
    displayEnd = displayEnd + 6; // move end out

    updateDisplay = 1;  // send to MAX7219s
  } // end add character
}// end serial available
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12631
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

By your explanation this would be broken up into numerous somethings.

Yes, absolutely - and a quick skim through the code suggests that would not be hard to do and would IMO make the logic much clearer.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pages: [1]   Go Up
Jump to: