Arduino IDE saving global variables in another tab

Thread Starter

zazas321

Joined Nov 29, 2015
637
Hey. I am trying to clean up my code. My program is getting bigger and bigger to the point where its hard for me to understand where is what. I have created multiple tabs and stored different functions in seperate tabs instead of keeping everything in my main .ino file.

The last thing I would like to sort are the global variables. I have many definitions and declarations in my main .ino file and ideally would like to move those variables somewhere else.

I have tried to create a seperate tab named variables and put all my variables there, but in my main tab, these variables are not recognised..

This is whats left of my main arduino file after I have moved the functions to seperate tabs:
Code:
#include <NeoPixelBus.h>
#include <cJSON.h>
#include <cJSON_Utils.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>



#include <WiFi.h>//esp32
#include <HTTPUpdate.h>//esp32  
#include <HTTPClient.h>//esp32
#include <PubSubClient.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>




//GPIO PINS DECLARATION
#define BUZZER 15 // pin D8
#define SENSOR 25 //pin D6
#define SCL   22 //pin D1
#define SDA    21 //pin D2
#define BUTTON1   14 //pin D5
#define PixelPin  27  // make sure to set this to the correct pin, ignored for Esp8266
//END OF GPIO PIN DECLARATION



//OLED declarations
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
//end of OLED declarations


//LED strip declarations
#define PixelCount  6 // this example assumes 4 pixels, making it smaller will cause a failure
#define colorSaturation 20
//end of LED strip declarations


int frequency = 1000; //buzzer frequency

//variables for non blocking delay
unsigned long lastMsg = 0;
//end of variables for non blocking delay

// Update these with values suitable for your network.
const char* ssid = "id";
const char* password = "pass";
const char* mqtt_server = "192.168.1.144"; // address of rpbi

int sensor = 0;             // variable to read sensor output
int sensor_prev_state=HIGH; // set the initial previous state to HIGH
int number_to_pick = 0;     // initial number to pick (gets updated by receiving mqtt message)
char current_status[100]="IDLE";

typedef struct {
  char item[100];
  char serial[100];
  int quantity;
}item_inside_struct;
item_inside_struct item_inside;


//MQTT TOPICS
char status_topic[30];
char ping_topic[30];
char item_inside_topic[30]; // this describes what item is inside box
char number_to_pick_topic[40];
char ota_topic[40];
char next_device_topic[40];
//END OF MQTT topics
char DEVICE_ID[10] = "device5/";








WiFiClient espClient;
PubSubClient client(espClient);
MySQL_Connection conn((Client *)&espClient);
NeoPixelBus<NeoGrbFeature, NeoEsp32Rmt0800KbpsMethod> strip(PixelCount, PixelPin);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);


void setup() {

      
  configure_topics(); // function to create all topics for specific device number
  OLED_setup();
  strip.Begin();
  GPIO_SETUP(); // function to set INPUT/OUTPUT ports
  Serial.begin(115200);
  setup_wifi(); // function to connect to wifi
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  toggle_led_strip(purple,5);

}

void loop() {
  if (!client.connected()){
    reconnect();
  }
  client.loop();
  //Read_sensor();//READING SENSOR EVERY 
  //check_rotary();

  unsigned long 
  now = millis();

  if (now - lastMsg > 10) {
    lastMsg=now;
    Read_sensor();//READING SENSOR EVERY 50MS


  }
 
 
}








void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  char message[length + 1];
  strncpy (message, (char*)payload, length);
  message[length] = '\0';
  Serial.println(message);

  if (strcmp(topic, ping_topic) == 0){ 
    
    if (strncmp(message, "ON", 2) == 0){
      digitalWrite(LED_YELLOW, 1);
      Serial.println("red led_turned_on");
    } 
    if (strncmp(message, "OFF", 3) == 0){
      digitalWrite(LED_YELLOW, 0);
      Serial.println("red led_turned_off");
    }
  }
  if (strcmp(topic, status_topic) == 0){ 
    if (strncmp(message, "GOOD_JOB", 8) == 0){
      strncpy(current_status,"IDLE",4);
      toggle_led_strip(blue,5);           
    }
    if (strcmp(message, "ACTIVE") == 0){
      //current_status="ACTIVE";
      strncpy(current_status,"ACTIVE",6);
      LED_strip_ON(green,number_to_pick);
      Serial.println(current_status); 
    }
  }
  
  if (strcmp(topic,number_to_pick_topic) == 0){ //if number_to_pick received, means the complecataion has been scanned and initiate the pick_to_light
    number_to_pick = atoi(message);
    //Serial.print("number to pick = ");
    //Serial.println(number_to_pick);
    OLED_display(item_inside.quantity,number_to_pick);

    }

    
  if (strcmp(topic,ota_topic) == 0){ 
    start_OTA();    
    }

  if (strcmp(topic,item_inside_topic) == 0){ //if number_to_pick received, means the complecataion has been scanned and initiate the pick_to_light
    parse_item_inside((char*)payload);
  }
}










void reconnect() {
   
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      //client.publish(status_topic, "connected");
      // ... and resubscribe

      client.subscribe(ping_topic); 
      client.subscribe(number_to_pick_topic); // listens for device_active flag which means that person need to take item from this box!!
      client.subscribe(item_inside_topic);    // listens for item_inside message from raspberry pi. We can know what item is assigned to each device
      client.subscribe(ota_topic);
      client.subscribe(status_topic);         // Listens for the status of this particular device
      //client.subscribe(next_device_topic);         // Listens for the status of this particular device

      LED_strip_ON(black,6);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(2000);
    }
  }
}


For example, my LED tab looks like that:
Code:
void toggle_led(int led, int number){
      for(int i=0;i<=number;i++){
      digitalWrite(led, 1);
      delay(100);
      digitalWrite(led, 0);
      delay(100);
      }
      }


void toggle_led_strip(RgbColor colour,int number){
      for(int i=0;i<=number;i++){
        strip.SetPixelColor(0, colour);
        strip.SetPixelColor(1, colour);
        strip.SetPixelColor(2, colour);
        strip.SetPixelColor(3, colour);
        strip.SetPixelColor(4, colour);
        strip.SetPixelColor(5, colour);
        strip.Show();
        delay(500);
        strip.SetPixelColor(0, black);
        strip.SetPixelColor(1, black);
        strip.SetPixelColor(2, black);
        strip.SetPixelColor(3, black);
        strip.SetPixelColor(4, black);
        strip.SetPixelColor(5, black);
        //delay(1);
          strip.Show();
          delay(500);
      }
      }

void clear_LED_strip(int number){
  for (int i=0;i<number;i++)
         strip.SetPixelColor(i, black);
        //delay(1);
          strip.Show();
}

void LED_strip_ON(RgbColor colour,int number){
    for (int i=0;i<number;i++)
         strip.SetPixelColor(i, colour);
          strip.Show();
}
The variables that I need for LED are:
Code:
RgbColor red(colorSaturation, 0, 0);
RgbColor green(0, colorSaturation, 0);
RgbColor blue(0, 0, colorSaturation);
RgbColor white(colorSaturation);
RgbColor black(0);
RgbColor purple(colorSaturation, 0, colorSaturation);
HslColor hslRed(red);
HslColor hslGreen(green);
HslColor hslBlue(blue);
HslColor hslWhite(white);
HslColor hslBlack(black);

#define PixelCount  6 // this example assumes 4 pixels, making it smaller will cause a failure
#define colorSaturation 20
I dont really want to keep those variable declarations in my main ino file because it makes it messy. I would ideally keep those variables on my LED tab but that does not work.
 

Irving

Joined Jan 30, 2016
948
If your LED tab is LED.c, put all your globals for LED in LED.h and include it at the top of LED.c and any other .c or .ino file in your project that needs to know about them.

You should probably consider making LED a class and making your globals member variables accessed as properties.

AFAIK you can only have one .ino file in your project.
 

Thread Starter

zazas321

Joined Nov 29, 2015
637
If your LED tab is LED.c, put all your globals for LED in LED.h and include it at the top of LED.c and any other .c or .ino file in your project that needs to know about them.

You should probably consider making LED a class and making your globals member variables accessed as properties.

AFAIK you can only have one .ino file in your project.
Creating a new tab in Arduino IDE does not allow me to create a .c and .h files. Instead, it just creates an .ino format file.

My working directory looks like that:

1597142574449.png

I am unsure how do I create .h and .c files for arduino. Do I just create a txt file and name it .h .c ?
 

Irving

Joined Jan 30, 2016
948
I wasn't sure from memory if you could have multiple .ino files. If so just create the .h file in a text editor (if you don't already have it, I recommend notepad++ as it understands and colour codes .c and .h files).
 
As Irving said create a file in a text editor and under your sketch menu click "Add File". If you're still working on the PI an even easier route is "touch filename" in a shell and do the add file in Arduino IDE.
 

Thread Starter

zazas321

Joined Nov 29, 2015
637
I am still trying to find a most convenient way to structure my source and header files for my arduino project. I have mangaed to make some progress but I have a question though:

I have a function to read sensor value and it is using global variables as inputs. I would like to make a seperate source and header file for this since I might have new functions for sensor readings later.

My sensor.cpp file:
Code:
extern char current_status[20];
extern int sensor;           // variable to read sensor output
extern int sensor_prev_state; // set the initial previous state to HIGH
extern int next_flag;
extern int confirmation_counter;
#include "sensor.h"


void Read_sensor(){
  if (strncmp(current_status, "PILDYMAS", 8) != 0){
  sensor=digitalRead(SENSOR);//ALWAYS TAKE SENSOR READING EVERY 50MS
  //IF ITEM ACTIVATED, SET GREEN LIGHT AND WAIT FOR PERSON TO TOGGLE THE DEVICE
  
    if(sensor==LOW && sensor_prev_state==HIGH){ // IF SENSOR IS TRIGGERED ON
      sensor_prev_state=LOW; // set the previous state to LOW
      if (strncmp(current_status,"ACTIVE",6)!=0){ // IF NUMBER TO PICK ITEMS IS 0, SET RED LIGHT TO SHOW OPERATOR WRONG BOX
        //tone(BUZZER, frequency);
        LED_strip_ON(red,6);
        
      }   
    }
      
    
    else if(sensor==HIGH && sensor_prev_state==LOW){ //sensor deactivated
      if(number_to_pick > 0 && strncmp(current_status,"ACTIVE",6)==0){ // if we still need to take items from this box after
        clear_LED_strip(6,black);
        number_to_pick--;
        eeprom_quantity--;
        Serial.print("eeprom_quantity");
        Serial.println(eeprom_quantity);
        sensor_prev_state = HIGH;
        //CHECKIF NUMBER TO PICK GOT DECREMENTED TO 0 HERE 
        if(number_to_pick==0){ // if we finished collecting items from this box, blink yellow LED to notify operator 
          strcpy(current_status,"DONE");
          int address=0;
          Serial.print("writing to 0 address quantity");
          Serial.println(eeprom_quantity);
          EEPROM.writeUShort(address, eeprom_quantity);   
          address += sizeof(unsigned short);
          EEPROM.commit();
          client.publish("global/device_status/Done",DEVICE_ID);
          create_JSON_object_pildymas("global/device_status/Done",false);
          done_flag=1;
          confirmation_counter=0;
          return;
        }
        toggle_led_strip(yellow,black,1);
        strcpy(current_status,"WAIT");
        client.publish("global/device_status/Next",DEVICE_ID);//MAKE SURE THE RASPBERRY PI RECEIVES THIS MESSAGE BY WAITING FOR RESPONSE
        // IF THE RESPONSE IS NOT RECEIVED, RESEND THIS MESSAGE AGAIN
        next_flag=1;
        confirmation_counter=0;
        
        
      }
        else if(strncmp(current_status,"ACTIVE",6)!=0){
          //noTone(BUZZER);
          LED_strip_ON(black,6);       
          sensor_prev_state = HIGH;
        }
    }
  }
}

my sensor.h file:
Code:
#ifndef sensor_h
#define sensor_h

#define SENSOR 25 //pin D6
#define SENSOR2 26 //pin D6
#define BUZZER 33 // pin D8
#define FREQUENCY = 1000

void Read_sensor();
//void tone() ;
//void noTone();


#endif
1. I have set all my global variables in my main .ino file as following:
Code:
int sensor = 0;             // variable to read sensor output
int sensor_prev_state=HIGH; // set the initial previous state to HIGH
and just include them as extern in my sensor source file. Is that a correct way to do?


2. I am getting weird compile issues such as:
Code:
'digitalRead' was not declared in this scope
'strcmp' was not declared in this scope
Why would that happen? Do I have to manually add libraries for these basic functions in my source file? (I do not need to use any libraries for these functions when I use them in my main.ino file).
 
Sounds like a missing include line. I can't remember which it is (not home at the moment)... Whichever is the main esp header needs to be in sensor.cpp also
 

Irving

Joined Jan 30, 2016
948
I think you have to include 'arduino.h' in your .h or .cpp file

here's a partial example from one of mine ....

Code:
*    Globals.h
*
*/

#ifndef _GLOBALS_h
#define _GLOBALS_h

#include <Arduino.h>    // data types (uint8_t...)

// global variables

....

//global routines
// STORES SERIAL STRINGS IN PROGMEM, SAVES 3KB RAM
#define MYSERIAL Serial

#define  FORCE_INLINE __attribute__((always_inline)) inline

FORCE_INLINE void serialprintPGM(const char *str)
{
    char ch = pgm_read_byte(str);
    while (ch)
    {
        MYSERIAL.write(ch);
        ch = pgm_read_byte(++str);
    }
}
#define MYSERIAL_PRINT(x) MYSERIAL.print(x);
#define MYSERIAL_PRINT_F(x,y) MYSERIAL.print(x,y);
#define MYSERIAL_PRINTLN(x) do {MYSERIAL.print(x);MYSERIAL.write('\n');} while(0)

#define MYSERIAL_PRINT_PGM(x) serialprintPGM(PSTR(x));
#define MYSERIAL_PRINTLN_PGM(x) do{serialprintPGM(PSTR(x));MYSERIAL.write('\n');} while(0)


// SOFTWARE VERSION NUMBER
#define VERSION_N  1.2            // 11/08/16

#endif /*_GLOBALS_h*/
 
@zazas321 I did a little digging today trying to find a way to make my own build files and such to get away from the Arduino IDE. I found a few things that could work (with some tweaking), but I finally settled on using Eclipse as the IDE. It took a little more digging and playing around to make it work, but so far I like it. Just thought I'd mention it. If you feel like giving it a go I can fill in some details the instructions I found online have left out (mainly because they're old)
 

djsfantasi

Joined Apr 11, 2010
6,718
Thanks for the update.

I only deal with the Arduino IDE. So I can’t help you. With the Arduino IDE, I have no issues that are similar to your problem. Since you’ve moved on to the Eclipse IDE, I can’t help. Good luck.
 
I thought maybe the OP would like to give something else a try. The Arduino IDE does work good, but it lacks some features I've grown to like in other programs. I personally use Kate for most of my programming when I can and write my own build scripts and such. Certain things like the ESPs and newer PICs just don't quite work that way (at least that I haven't found a way yet or have put time into looking)
 
Top