Pages: [1]   Go Down
Author Topic: Behaviour of Multiple Tabs in IDE & compilation  (Read 2567 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi All,

I've been using arduino for ages (even made the cheatsheet for it!), but this has got me scratching my head a little to figure out the 'right' way to do it, and more importantly to explain to others how to do the same.

I've got a slab of code that compiles successfully in the main sketch, and I'm trying to break it out into different files to make it more elegant.

According to http://www.arduino.cc/en/Guide/Environment, you can choose no extension (i.e. pde/ino), or .c, .cpp, .h. No problem. I'd prefer to use the native ino format (since then I don't have to do all sorts of preprocessor stuff to check if my code's already defined, and include the arduino libs manually, etc.).

If I use the 'new tab' function and make a file 'radio', for example, then remove the radio code and put it there, it will give compile errors that are consistent with it compiling the second 'radio' tab after the main one. If I move my global variables to the main tab it compiles, and finds the methods in the second tab without issue. But it's inelegant to have all my globals related to the second tab cluttering up my first.

Is there a way to make the second tab compile first? I've tried putting #include "radio", or #include "radio.ino" at the top of my main tab, and they didn't work. I could of course turn 'radio' into separate '.cpp' and '.h files, but that's unwieldy and almost impossible to explain easily to newbs.

Cheers,
Gavin

Code below, for ref, but it's more advice on the philosophy I'm after, rather than this specific example:
Code:
/******************************************************/
/*********     Hobby RC Radio code          ***********/
/******************************************************/
boolean RC_RX_healthy = false;

const int RC_pitch_pin = 12; //Arduino digital pins. Inputs by default
const int RC_yaw_pin = 11;
const int RC_aux_pin = 10;

int RC_pitch = 0;
int RC_yaw = 0;
int RC_aux = 0;

int RC_MAX = 1887; 
int RC_MIN = 1084; //set these to your RX's limits. Will depend on hardware.

int read_servo(int servo_pin, int servo_min, int servo_max){
  // Read a standard RC hobby servo signal on a digital pin.
  // Limits to 
  int servo_val = pulseIn(servo_pin, HIGH, 20000);
  if (servo_val == 0) {
    return -1;
  }
  servo_val = constrain(servo_val,servo_min,servo_max);
  servo_val = map(servo_val,servo_min, servo_max,0,255);
  return servo_val;
}

void read_RC_RX(){
  //Read from the reciever, but if any is invalid or times out, then short circuit and declare invalid. 
  int yaw = 0;
  int pitch = 0;
  int aux = 0;

  RC_RX_healthy = true;
  // Pitch
  if (RC_RX_healthy){
    pitch = read_servo(RC_pitch_pin, RC_MIN, RC_MAX);
    if (pitch >=0){
      RC_pitch = pitch;
    }
    else {
      RC_RX_healthy = false;
    }
  }
  // Yaw
  if (RC_RX_healthy){
    yaw = read_servo(RC_yaw_pin, RC_MIN, RC_MAX);
    if (yaw >=0){
      RC_yaw = yaw;
    }
    else {
      RC_RX_healthy = false;
    }
  }
  // Aux
  if (RC_RX_healthy){
    aux = read_servo(RC_aux_pin, RC_MIN, RC_MAX);
    if (aux >=0){
      RC_aux = aux;
    }
    else {
      RC_RX_healthy = false;
    }
  }
  if ( ! RC_RX_healthy){
    //Pitch invalid, RX probably off or no signal, avoid using data.
    RC_pitch = 0;
    RC_yaw = 0;
    RC_aux = 0;
    return;
  }
}

/******************************************************/
/*********     Main code                    ***********/
/******************************************************/

void setup(){
  Serial.begin(115200); 

}

void loop(){
  //Serial.println("hello world");
  int a  = analogRead(1);
  int b  = analogRead(2);
  read_RC_RX();

  Serial.print(a);
  Serial.print("\t  ");
  Serial.print(b);
  Serial.print("\t  ");
  Serial.print(a);
  Serial.print("\t  ");
  Serial.println(b);
  delay(10);
  if (  RC_RX_healthy){
    //do stuff
  }
}
Logged

SE USA
Offline Offline
Faraday Member
**
Karma: 41
Posts: 3783
@ssh0le
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
consistent with it compiling the second 'radio' tab after the main one.

thats cause that is exactly what it does

if your going to reference variables in the main tab that are not in the radio tab its going to barf, if you want to define everything in radio and have the main tab access it, you need to write a library.
Logged


Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

IMHO the best practice is to have only one .ino file and one or more .h/.cpp couples for other code.

Example:

Main sketch (.ino file):
Code:
#include "simpleMath.h"

int n = 0;

void setup() {
    Serial.begin(9600);
}


void loop() {
    Serial.println(sum(n, n));
    n++;
    delay(1000);
}

The "library" header file, simpleMath.h, contains function prototypes:
Code:
#ifndef _SIMPLE_MATH_H
#define _SIMPLE_MATH_H

int sum(int a, int b);

#endif

The "library" implementation file, simpleMath.cpp, contains the actual code:
Code:
#include "simpleMath.h"

int sum(int a, int b) {
    return a + b;
}

Global variables belong to the sketch file (the .ino file). The .h/.cpp files only contain functions that can be called by the main sketch code.

Here I've made a (stupidly) simple example with just one function prototype and its implementation. In C++land you usually have a class definition inside a .h and its implementation in the corresponding .cpp file. A "counter class" example would be easy to write, but that would introduce OOP which is quite a subject in itself... smiley
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 613
Posts: 49343
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
if your going to reference variables in the main tab that are not in the radio tab its going to barf, if you want to define everything in radio and have the main tab access it, you need to write a library.
You don't need to go that far. A simple header file, included on all tabs, is sufficient. And, it stays local to the sketch.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
if your going to reference variables in the main tab that are not in the radio tab its going to barf, if you want to define everything in radio and have the main tab access it, you need to write a library.
You don't need to go that far. A simple header file, included on all tabs, is sufficient. And, it stays local to the sketch.

Would it contain declarations like: extern int global_counter = 0; ?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 613
Posts: 49343
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Whether the declaration needs to contain the extern keyword, or not depends on whether the variable is actually used in multiple files, or not.

When a sketch has multiple tabs, and the extension on two or more is .ino, the .ino files are combined into one .cpp file for compilation. In that case, the extern keyword is not needed.
Logged

Pages: [1]   Go Up
Jump to: