Как разбить программу на несколько файлов

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

Доброго времени суток!

Помогите разбить программу на три файла.

Вот известный пример:

//Sample using LiquidCrystal library 
#include <LiquidCrystal.h> 
/******************************************************* 
This program will test the LCD panel and the buttons 
Mark Bramwell, July 2010 
********************************************************/ 
// select the pins used on the LCD panel 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 
// define some values used by the panel and buttons 
int lcd_key     = 0; 
int adc_key_in  = 0; 
#define btnRIGHT  0 
#define btnUP     1 
#define btnDOWN   2 
#define btnLEFT   3 
#define btnSELECT 4 
#define btnNONE   5 
// read the buttons 
int read_LCD_buttons() 
{ 
adc_key_in = analogRead(0);      // read the value from the sensor   
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741 
// we add approx 50 to those values and check to see if we are close 
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result 
if (adc_key_in < 50)   return btnRIGHT;   
if (adc_key_in < 195)  return btnUP;   
if (adc_key_in < 380)  return btnDOWN;   
if (adc_key_in < 555)  return btnLEFT;   
if (adc_key_in < 790)  return btnSELECT;     
return btnNONE;  // when all others fail, return this... 
} 
void setup() 
{ 
lcd.begin(16, 2);              // start the library 
lcd.setCursor(0,0); 
lcd.print("Push the buttons"); // print a simple message 
} 
void loop() 
{ 
lcd.setCursor(9,1);            // move cursor to second line "1" and 9 spaces over 
lcd.print(millis()/1000);      // display seconds elapsed since power-up 
lcd.setCursor(0,1);            // move to the begining of the second line 
lcd_key = read_LCD_buttons();  // read the buttons 
switch (lcd_key)               // depending on which button was pushed, we perform an action 
{ 
  case btnRIGHT: 
    { 
    lcd.print("RIGHT "); 
    break; 
    } 
  case btnLEFT: 
    { 
    lcd.print("LEFT   "); 
    break; 
    } 
  case btnUP: 
    { 
    lcd.print("UP    "); 
    break; 
    } 
  case btnDOWN: 
    { 
    lcd.print("DOWN  "); 
    break; 
    } 
  case btnSELECT: 
    { 
    lcd.print("SELECT"); 
    break; 
    } 
    case btnNONE: 
    { 
    lcd.print("NONE  "); 
    break; 
    } 
} 
} 

Хочу разделить его на файлы примерно так:

File_1.ino

/******************************************************* 
This program will test the LCD panel and the buttons 
Mark Bramwell, July 2010 
********************************************************/ 
void setup() 
{
 
init_LCD();
} 
void loop() 
{ 
lcd.setCursor(9,1);            // move cursor to second line "1" and 9 spaces over 
lcd.print(millis()/1000);      // display seconds elapsed since power-up 
lcd.setCursor(0,1);            // move to the begining of the second line 
lcd_key = read_LCD_buttons();  // read the buttons 
switch (lcd_key)               // depending on which button was pushed, we perform an action 
{ 
  case btnRIGHT: 
    { 
    lcd.print("RIGHT "); 
    break; 
    } 
  case btnLEFT: 
    { 
    lcd.print("LEFT   "); 
    break; 
    } 
  case btnUP: 
    { 
    lcd.print("UP    "); 
    break; 
    } 
  case btnDOWN: 
    { 
    lcd.print("DOWN  "); 
    break; 
    } 
  case btnSELECT: 
    { 
    lcd.print("SELECT"); 
    break; 
    } 
    case btnNONE: 
    { 
    lcd.print("NONE  "); 
    break; 
    } 
} 
} 

File_2.cpp

#include <LiquidCrystal.h> 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 
// define some values used by the panel and buttons 
int lcd_key     = 0; 
int adc_key_in  = 0; 
#define btnRIGHT  0 
#define btnUP     1 
#define btnDOWN   2 
#define btnLEFT   3 
#define btnSELECT 4 
#define btnNONE   5 

File_3.cpp

int read_LCD_buttons() 
{ 
adc_key_in = analogRead(0);      // read the value from the sensor   
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741 
// we add approx 50 to those values and check to see if we are close 
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result 
if (adc_key_in < 50)   return btnRIGHT;   
if (adc_key_in < 195)  return btnUP;   
if (adc_key_in < 380)  return btnDOWN;   
if (adc_key_in < 555)  return btnLEFT;   
if (adc_key_in < 790)  return btnSELECT;     
return btnNONE;  // when all others fail, return this... 
} 

void init_LCD()
{
lcd.begin(16, 2);              // start the library
lcd.setCursor(0,0);
lcd.print("Push the buttons"); // print a simple message
}

 

olegab
Offline
Зарегистрирован: 09.04.2013

сделайте библиотеку

http://www.arduino.ru/Hacking/LibraryTutorial

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

В программировании на C++ не силен. Пробовал сделать библиотеку. Не получилось. Да и не очень это удобно с точки зрения Arduino.

Мне надо просто разбить на файлы, которые будут лежать в одном каталоге.

Если не трудно: не надо давать советов, лучше покажите как это делается. Как оформить так, что бы не выдавало ошибок. Идея такая: один файл главный, один файл с описанием глобальных переменных (путь это будет *.h или *.cpp) и один или несколько файлов для функций, которые используют глобальные переменные.

Как из данного примера сделать то, что я хочу?

Покажите пожалуйста на конкретном примере.

step962
Offline
Зарегистрирован: 23.05.2011

Это

Oleg_SS пишет:

не надо давать советов

и это

Цитата:
 лучше покажите как это делается.

как бы противоречит друг другу...

Поэтому на вопрос

Цитата:
Как оформить так, что бы не выдавало ошибок. Идея такая: один файл главный, один файл с описанием глобальных переменных (путь это будет *.h или *.cpp) и один или несколько файлов для функций, которые используют глобальные переменные.

Как из данного примера сделать то, что я хочу?

Покажите пожалуйста на конкретном примере.

посоветую разнести куски в разные .pde-файлы, причем главный из них (с функциями setup() и loop()) должен иметь то же имя, что и каталог проекта.

Показывать не буду - для следования вышеуказанному совету не требуется особых познаний/умений.

И еще посоветую - пользоваться в IDE кнопочкой вверху справа ("стрелка вправо"). Там как раз скрывается меню, необходимое для создания/удаления файлов проекта.

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

Мдяааа... Все с точностью наоборот.

Попросил не советывать - посветывали. Попросил показать - не показали.

Спасибо!

Неужели так трудно привести пример кода, который можно скопировать и запустить?

step962
Offline
Зарегистрирован: 23.05.2011

"пример кода, который можно скопировать и запустить" - в вашем первом посте.

Осталось положить куски в три файла с расширением .pde

 

maksim
Offline
Зарегистрирован: 12.02.2012

 Начиная с версии IDE 1.0 файлы имеют расширение .ino

mixail844
Offline
Зарегистрирован: 30.04.2012

эээм,вомозжно просто скажем делите ваш проэкт на 3 файла,один из них основной (содержит setup() и loop())

остальным двум присваиваете имена с окончанием .h или .c (хотя думаю там вообще не принципиально с каким окончанием можно даже .txt)и затем в основном файле прописываете 

#include " имя первого файла,включая окончание"
#include "имя второго файла,включая окончание"
//естественно файлы должны лежать в одной папке с основным файлом

думаю как то так,хотя не проверял

maksim
Offline
Зарегистрирован: 12.02.2012

Ну так проверьте, а после того как не скомпилируется отпишитесь... Делается как написал step962 только с разными расширениями в зависимости от версии IDE.

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

Если это было бы так просто, я бы не задавал вопросы.

Попробуйте сами скомпилировать пример из первого поста. Выдвет кучу ошибок. Это и понятно, поскольку надо все это еще оформить. Вот я и прошу, помогите избавиться от ошибок.

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

mixail844 пишет:

эээм,вомозжно просто скажем делите ваш проэкт на 3 файла,один из них основной (содержит setup() и loop())

остальным двум присваиваете имена с окончанием .h или .c (хотя думаю там вообще не принципиально с каким окончанием можно даже .txt)и затем в основном файле прописываете 

#include " имя первого файла,включая окончание"
#include "имя второго файла,включая окончание"
//естественно файлы должны лежать в одной папке с основным файлом

думаю как то так,хотя не проверял

Это не поможет! Попробуйте

ustas
Offline
Зарегистрирован: 12.03.2012

ой.. а чего так сложно-то?

Все гораздо проще реализуется. 

1. Создаете (или открываете готовый) скетч

2. Нажимаете комбинацию кнопок CTRL+Shift+N (или мышкой правее вкладки на выпадающий список - "Новая закладка")

3. Вводите имя "дополнительного" файла (только имя, расширение файла среда сама подставит). И нажимаете "ОК".

Все. Проект разнесен на несколько файлов. Переключение между ними с помощью закладок в среде. В компляции участвуют все.

 

leshak
Offline
Зарегистрирован: 29.09.2011

Да не покажешь, не выложешь это на форум. Потому как сильно зависит имено от файловой системы. И начинайте разбиратся не громоздким примером (где вы могли нахомутать в чем-то помимо разбиения на файлы), а с каким-то простеньким. Где в отдельный файл вынесена функция типа printHelloWorld(), и в главно - она вызывается.

Общая идея "разбивки" - такая.

1. Главный файл (в котором setup() и loop()) должен по имени совпадать с именем папки в котором все это лежит. Это самое главное.
2. Все остальные .ino/.pde, .cpp,.h - просто ложим в ту же папку.
3. .h файлы - нужно подключать через include.
4. .ino/.pde файлы - "подключатся сами" (в момент компиляции IDE просто объеденит их с главным файлом, для компилятора это будет "один большой скетч". Правда порядок подключения - IDE будет сама выбирать (скорее всего - тупо по алфавиту).
5. В .h файлах, возможно еще потребутеся делать #include "Arduino.h" или #include "WProgram.h"  (в зависимости от того какая у вас версия), что-бы использоватся в .h/.cpp ардуиновские типы, константы, функции.

Вообщем если хотите что-бы вам помогли, то
1. Не рассказывайте как именно должны помогать. Возможно и со способом помощи вы ошибаетесь.
2. Скажите конкретно какие именно ошибки вы видите.
2. Сделайте упрощенный скетч. Использующий только Serial. Без всяких экранов и стронних библиотек проч. - что-бы любой мог запустить его у себя и увидеть те же ошибки что и вы. Вообщем вывернете наоборот свое "привести пример кода, который можно скопировать и запустить". Вы его приведите, а мы посмотрим "что с ним не так".

А по поводу "вашего примера" из стартового поста. Вам нужно либо читать как соотносятся .h/.cpp. Кроме .cpp файлов - нужно создать соотвествующие им .h файлы, где эти функции будут объявлены.

Либо... попробуйте просто переименовать  File_2.cpp и File3_.cpp в File_2.ino и File3_.ino

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

Разбил программу на 4 файла:

Test.ino

//Sample using LiquidCrystal library 
#include <LiquidCrystal.h> 
#include "Test1.cpp" 
#include "Test2.cpp" 
#include "Test3.cpp"/
******************************************************* 
This program will test the LCD panel and the buttons 
Mark Bramwell, July 2010 
********************************************************/ 
void setup() 
{ 
print_lcd(); 
} 

void loop() 
{ 
lcd.setCursor(9,1);            // move cursor to second line "1" and 9 spaces over 
lcd.print(millis()/1000);      // display seconds elapsed since power-up 
lcd.setCursor(0,1);            // move to the begining of the second line 
lcd_key = read_LCD_buttons();  // read the buttons 
switch (lcd_key)               // depending on which button was pushed, we perform an action 
{ 
  case btnRIGHT: 
    { 
    lcd.print("RIGHT "); 
    break; 
    } 
  case btnLEFT: 
    { 
    lcd.print("LEFT   "); 
    break; 
    } 
  case btnUP: 
    { 
    lcd.print("UP    "); 
    break; 
    } 
  case btnDOWN: 
    { 
    lcd.print("DOWN  "); 
    break; 
    } 
  case btnSELECT: 
    { 
    lcd.print("SELECT"); 
    break; 
    } 
    case btnNONE: 
    { 
    lcd.print("NONE  "); 
    break; 
    } 
} 
} 

Test1.cpp

// select the pins used on the LCD panel 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 
// define some values used by the panel and buttons 
int lcd_key     = 0; 
int adc_key_in  = 0; 
#define btnRIGHT  0 
#define btnUP     1 
#define btnDOWN   2 
#define btnLEFT   3 
#define btnSELECT 4 
#define btnNONE   5 

Test2.cpp

// read the buttons 
int read_LCD_buttons() 
{ 
adc_key_in = analogRead(0);      // read the value from the sensor   
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741 
// we add approx 50 to those values and check to see if we are close 
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result 
if (adc_key_in < 50)   return btnRIGHT;   
if (adc_key_in < 195)  return btnUP;   
if (adc_key_in < 380)  return btnDOWN;   
if (adc_key_in < 555)  return btnLEFT;   
if (adc_key_in < 790)  return btnSELECT;     
return btnNONE;  // when all others fail, return this... 
} 

Test3.cpp

void print_lcd() 
{ 
lcd.begin(16, 2);              // start the library 
lcd.setCursor(0,0); 
lcd.print("Push the buttons"); // print a simple message 
} 

Выдает ошибку:

In file included from Test.ino:4:
/Test2.cpp: In function 'int read_LCD_buttons()':
Test2.cpp:4: error: 'analogRead' was not declared in this scope

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

не видит. попробуйте уговорить что она есть. объявите ее в самом начале.

типа так.

#include <LiquidCrystal.h>
int read_LCD_buttons(void);
#include "d:\test\test\Test1.cpp"
#include "d:\test\test\Test2.cpp"
#include "d:\test\test\Test3.cpp"

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

Test.ino

//Sample using LiquidCrystal library 
#include <LiquidCrystal.h> 
#include "Test1.cpp" 
#include "Test2.cpp" 
#include "Test3.cpp" 
/******************************************************* 
This program will test the LCD panel and the buttons 
Mark Bramwell, July 2010 
********************************************************/ 
void setup() 
{ 
print_lcd(); 
} 

void loop() 
{ 
lcd.setCursor(9,1);            // move cursor to second line "1" and 9 spaces over 
lcd.print(millis()/1000);      // display seconds elapsed since power-up 
lcd.setCursor(0,1);            // move to the begining of the second line 
lcd_key = read_LCD_buttons();  // read the buttons 
switch (lcd_key)               // depending on which button was pushed, we perform an action 
{ 
  case btnRIGHT: 
    { 
    lcd.print("RIGHT "); 
    break; 
    } 
  case btnLEFT: 
    { 
    lcd.print("LEFT   "); 
    break; 
    } 
  case btnUP: 
    { 
    lcd.print("UP    "); 
    break; 
    } 
  case btnDOWN: 
    { 
    lcd.print("DOWN  "); 
    break; 
    } 
  case btnSELECT: 
    { 
    lcd.print("SELECT"); 
    break; 
    } 
    case btnNONE: 
    { 
    lcd.print("NONE  "); 
    break; 
    } 
} 
} 

Test1.cpp

#include <LiquidCrystal.h> 

// select the pins used on the LCD panel 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 
// define some values used by the panel and buttons 
int lcd_key     = 0; 
int adc_key_in  = 0; 
#define btnRIGHT  0 
#define btnUP     1 
#define btnDOWN   2 
#define btnLEFT   3 
#define btnSELECT 4 
#define btnNONE   5 

Test2.cpp

#include "Arduino.h" 
// read the buttons 
int read_LCD_buttons() 
{ 
adc_key_in = analogRead(0);      // read the value from the sensor   
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741 
// we add approx 50 to those values and check to see if we are close 
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result 
if (adc_key_in < 50)   return btnRIGHT;   
if (adc_key_in < 195)  return btnUP;   
if (adc_key_in < 380)  return btnDOWN;   
if (adc_key_in < 555)  return btnLEFT;   
if (adc_key_in < 790)  return btnSELECT;     
return btnNONE;  // when all others fail, return this... 
} 

Test3.cpp

void print_lcd() 
{ 
lcd.begin(16, 2);              // start the library 
lcd.setCursor(0,0); 
lcd.print("Push the buttons"); // print a simple message 
} 

Ошибка:

Test2.cpp: In function 'int read_LCD_buttons()':
Test2.cpp:5: error: 'adc_key_in' was not declared in this scope
Test2.cpp:8: error: 'btnNONE' was not declared in this scope
Test2.cpp:9: error: 'btnRIGHT' was not declared in this scope
Test2.cpp:10: error: 'btnUP' was not declared in this scope
Test2.cpp:11: error: 'btnDOWN' was not declared in this scope
Test2.cpp:12: error: 'btnLEFT' was not declared in this scope
Test2.cpp:13: error: 'btnSELECT' was not declared in this scope
Test2.cpp:14: error: 'btnNONE' was not declared in this scope

 

maksim
Offline
Зарегистрирован: 12.02.2012

Перестаньте заниматься херней!!! хотя... можете продолжать если нравится. Вам уже 4 человека (ustasstep962leshak и я) написали как это делается, а вы все .cpp файлы пытаетесь подключить...

Глобальные переменные должны быть объявлены в основном файле:

#include <LiquidCrystal.h> 
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 
/******************************************************* 
 * This program will test the LCD panel and the buttons 
 * Mark Bramwell, July 2010 
 ********************************************************/

// define some values used by the panel and buttons 
int lcd_key     = 0; 
int adc_key_in  = 0; 

void setup() 
{
  init_LCD();
} 
void loop() 
{ 
  lcd.setCursor(9,1);            // move cursor to second line "1" and 9 spaces over 
  lcd.print(millis()/1000);      // display seconds elapsed since power-up 
  lcd.setCursor(0,1);            // move to the begining of the second line 
  lcd_key = read_LCD_buttons();  // read the buttons 
  Print();
} 

File_1.ino

#define btnRIGHT  0 
#define btnUP     1 
#define btnDOWN   2 
#define btnLEFT   3 
#define btnSELECT 4 
#define btnNONE   5 

File_2.ino

int read_LCD_buttons() 
{ 
adc_key_in = analogRead(0);      // read the value from the sensor   
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741 
// we add approx 50 to those values and check to see if we are close 
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result 
if (adc_key_in < 50)   return btnRIGHT;   
if (adc_key_in < 195)  return btnUP;   
if (adc_key_in < 380)  return btnDOWN;   
if (adc_key_in < 555)  return btnLEFT;   
if (adc_key_in < 790)  return btnSELECT;     
return btnNONE;  // when all others fail, return this... 
} 

void init_LCD()
{
lcd.begin(16, 2);              // start the library
lcd.setCursor(0,0);
lcd.print("Push the buttons"); // print a simple message
}

void Print()
{
    switch (lcd_key)               // depending on which button was pushed, we perform an action 
  { 
  case btnRIGHT: 
    { 
      lcd.print("RIGHT "); 
      break; 
    } 
  case btnLEFT: 
    { 
      lcd.print("LEFT   "); 
      break; 
    } 
  case btnUP: 
    { 
      lcd.print("UP    "); 
      break; 
    } 
  case btnDOWN: 
    { 
      lcd.print("DOWN  "); 
      break; 
    } 
  case btnSELECT: 
    { 
      lcd.print("SELECT"); 
      break; 
    } 
  case btnNONE: 
    { 
      lcd.print("NONE  "); 
      break; 
    } 
  } 
}

__Alexander
Offline
Зарегистрирован: 24.10.2012

Я кажись понял в чем фигня. ИДЕ подтягивает все файлы в папке, инклуд игнорит. Кладем их в отдельную папку и дело в шляпе, тогда они подтянуться через инклуд. Тогда лучше смело спрыгивать с иде на голый winavr, зачем такие извращения.

 

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

maksim пишет:

Перестаньте заниматься херней!!! хотя... можете продолжать если нравится. Вам уже 4 человека (ustasstep962leshak и я) написали как это делается, а вы все .cpp файлы пытаетесь подключить...

Извините, но я по-моему говорил, что С не знаю, и вообще я не программист. Поэтому мне что cpp,  что ino все равно. По человечески ведь прошу, приведите работающий код. Если это трудно, то лучше не отвечайте и закроем тему. И не надо ругаться. Если будет работающий пример, то потом по тихоньку буду его разбирать. А следующим этапом перейду на создание классов.

leshak
Offline
Зарегистрирован: 29.09.2011

Максим-то ругается не потому что вы не знаете, а потому что не читаете что вам пишут. "не программист" - не является оправданием в нежелании разбиратся. Вот вы загуглили, за это время что такое .h и как они работают в паре с .cpp? Похоже что нет. 

Вам то может и нет разницы, что .cpp, что .ino . А вот компилятору - есть. И что-то мне подсказывает что из двух вариантов:
1. Уговорить компилятор не видеть разницы и
2. Вам разобратся в разнице и использовать нужно расширение 

второй вариант выглядит реальней. 

Вот я написал что инклудами подключаются только .h файлы, почему вы пытались .cpp подключить?

Я написал каждому .cpp файлу нужен свой .h файл (и его подключать), вы завели его (а для этого нужно таки загуглить что это за зверь)?

Ладно. Специально для тех кто не хочет разбиратся (хотя если вы хотите с классами, в будущем работать все равно прийдется) - есть специально "Арудино Путь". Просто сделать расширение файло .ino (и ничего не инклудить). Все файлы .ino из папки прикомпиляции IDE невидимо для вас объединит в одну (и это тоже писал). 

Вот Максим прочитал "Либо... попробуйте просто переименовать  File_2.cpp и File3_.cpp в File_2.ino и File3_.ino" и сделал это. И у него скомпилировалось (хотя, конечно он знал это и без чтения). Потому что он програмист? 

leshak
Offline
Зарегистрирован: 29.09.2011

Кстати перед тем как переходить к разбирательству с классами почитать Создание библиотек для Arduino из раздела сайта Программирование

Собственно это и есть пример "как создать класс". Разница только в том - куда вы положите  .h/.cpp файлы. Если в папку с проектом, то это будет обычный классы. Если же вы положите в какую-то подпапку arduino/libraries - то они же станут носить гордое имя "библиотеки".

Если совсем кратко:

1. .h файл - заголовочный. Содержит "декларацию", какие типы, функции, классы у нас есть. Это как-бы обещание "мы вот эти функции/классы где-нибудь реализуем". Вот его и нужно инклудить.
2. .cpp файл. А это - выполнение обещаний. В него мы ложим реализацию функций/классов (и он - тоже должен делать инклуд .h файла). Сам .cpp  инклудить не нужно. Достаточно что-бы он лежал в папке скетча. 

Вот если мы в .h файле что-то "пообещаем", а ни в одном .cpp файле не выполним обещание - тогда будет ошибка.

В качестве "примера" - вы можете пойти в папку arduino, зайти в libraries и походить по библиотекам. Посмотреть как выглядят внутри .h / .cpp файлы.

Кстати - весьма эффективный способ учится. Смотреть чужой код. Если не понятно/не известно - гуглить "а че это за штука такая и зачем она тут".

__Alexander
Offline
Зарегистрирован: 24.10.2012

leshak пишет:

Вам то может и нет разницы, что .cpp, что .ino . А вот компилятору - есть. И что-то мне подсказывает что из двух вариантов:

Нет. Копилятору тоже побарабану расширение файлов. Это только для людей. Компилятор всё равно создает один большой файл из всех разных, включая эти разные файлы там где есть include.

leshak пишет:

Вот если мы в .h файле что-то "пообещаем", а ни в одном .cpp файле не выполним обещание - тогда будет ошибка.

Наоборот, если сделаем не пообещав, то будет ошибка.

Даже не так. Если мы будем вызывать функции, которые выше главной функции main, то можно не "обещать", если ниже, то надо описать прототип функуции. и не важно в каком файле, главное выше main.

 

 

leshak пишет:

Вот Максим прочитал "Либо... попробуйте просто переименовать  File_2.cpp и File3_.cpp в File_2.ino и File3_.ino" и сделал это. И у него скомпилировалось (хотя, конечно он знал это и без чтения). Потому что он програмист? 

Ну я вот (на скрине видно) и .cpp скомпилил... я не программист?

leshak пишет:

Все файлы .ino из папки прикомпиляции IDE невидимо для вас объединит в одну (и это тоже писал). 

А вот и правильный ответ! С какого буя эта ИДЕ компилит всё что в папке? Стандарт Си предпологает компиляцию файлов, которые указаны в include. И тот-же winavr, что использует эта иде, тоже стандартный.

Поэтому я задал вполне логичный вопрос, зачем морочиться с этой ИДЕ, если человек хочет делать как положено?

Но то, что этот человек не видит ответов это да, есть.

olegab
Offline
Зарегистрирован: 09.04.2013

Библиотека с примером. только смените расширение на rar и разверните в каталог с библиотеками

/sites/default/files/u4655/testlib.jpg

Oleg_SS
Offline
Зарегистрирован: 22.04.2013

Очень много букв написали. В книгах букв еще больше! По поводу желания разбираться: интересно, а я чем занимаюсь?

Теперь резюме:

Наконец то я получил работающий код собранный из нескольких файлов. Да действительно расширение играет роль, т.к. если взять эти файлы с работающим кодом и переименовать их с расширением cpp (только первому оставить ino), то копиляция уже будет с ошибками. А делал я это потому, что в одной очень умной книжке прочитал, что все остальные подключаемые файлы должны быть написаны на C++ и иметь соответствующие имена.

Теперь о порядке подключения и именования файлов: если писать в такой упрощенной методике как у меня, то файлы должны именоваться в алфавитном порядке в соответствии с их употреблением. Файл, содержащий описание переменных должен идти первым по алфавиту. "Инклюдить" ничего не надо!!! Если именовать файлы в другом порядке, то приходится делать ссылки типа extern.

Вот собственно и все правила. Потрачено три дня переписки и разборок. Если бы уважаемый maksim раньше привел свой пример, времени бы было потрачено меньше. Что собственно я и добивался от вас всех.

Теперь о том, что я не умею читать. Внимательно перечитайте сами, что я у вас всех просил и что вы мне написали и сравните что ответил уважаемый maksim. Ему спасибо, хоть он и не очень хорошо выражается.

Да вот еще __Alexander тоже натолкнул меня на некоторые мысли. Тоже спасибо!

Все тема закрыта.

 

Клапауций
Offline
Зарегистрирован: 10.02.2013

Oleg_SS пишет:
Помогите разбить программу на три файла.

Oleg_SS пишет:
Все тема закрыта.

Категорически не согласен - требую продолжения банкета и рассказа о разбиении программы на 2,5 файла!

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

Доброго времени суток. Заинтересовался разбивкой файла на части. Вроде понял один способ и попробовал вынести в новый Таб (вкладку) часть файла, например, нужную функцию. При этом Ардуино Иде сама сохраняет нужную вкладку с расширением ino и все компилируется без вопросов. Но интересно разбить на файлы с расширением .h/.cpp. Пока не получается. Хотя какой-то простенький работает, типа:

Главный файл

#include "file1.h"

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
ppp();
}

void loop() {
  // put your main code here, to run repeatedly:

}

file1.h

#include "Arduino.h"

void ppp();

file1.cpp

#include "file1.h"

void ppp() {
Serial.println("da-da-da");
}

Но разбить свой файл по тому же принципу пока не получилось. Может кто глянет и покажет как разбить мой файл?

#include <ESP8266WiFi.h>                                                    // Библиотека для создания Wi-Fi подключения (клиент или точка доступа)
#include <WiFiClient.h>

char* array_ssid[] = {"ssid1", "ssid2", "ssid3", "ssid4"};              // Массив необходимых ссидов
char* array_pass[] = {"pass1", "pass2", "pass3", "pass4"};              // Массив необходимых паролей к этим ссидам

int count_ssid = sizeof(array_ssid) / sizeof(array_ssid[0]);                // Размер массива ссидов

// Функция скарирования и подключения к найденной известной сети из нашего списка, другие будут игнорится
void conekt_to_wifi(int networksFound) {                                    //
  uint8_t tries = 100;                                                      // Количество попыток подключения
  if (WiFi.status() != WL_CONNECTED) {                                      // Проверяем, есть ли вообще подключение, если нет, то в следующей строке запускаем сканирование
  Serial.println("not connekt");
  for (int i = 0; i < networksFound; i++) {                                 // Перебираем полученные точки доступа
    for (int j = 0; j < count_ssid; j++) {                                  // Перебираем в нашем списке точек доступа и проверяем условия

        if (WiFi.status() == WL_CONNECTED) {                                // Сперва проверяем, если все же есть подключение, то выходим из цикла. Нужно для проверки при разрывах
        break;
//        WiFi.scanDelete();
//          return true;
        }
        else if (WiFi.SSID(i) == array_ssid[j]) {                           // Если нет подключения, то сравниваем с нашим списком
        Serial.println("\nOne of our ssid was found = " + WiFi.SSID(i));
        WiFi.begin(array_ssid[j], array_pass[j]);                                             // Стартуем подключение к точке доступа
        Serial.printf("waiting");
        while (--tries){
        while (WiFi.status() != WL_CONNECTED) {                             // Зупускаем ожидание поднятия вайфай сервера
        delay(1000); 
        Serial.print(".");        
        }
      }
      Serial.println("connekt" + String(array_ssid[j]));                
        Serial.println(WiFi.localIP());                                      // Распечатываем полученный айпишник
      }      
    }
  }
    if (WiFi.status() != WL_CONNECTED) {                                      // Доп. роверка и отчет, если нет точек из нашего списка
      Serial.println("\nNo famouse wifi");
    }
  } else {
Serial.println("connekt");
  }
}

void setup() {
  WiFi.persistent(false);
  Serial.begin(9600);
  WiFi.mode(WIFI_OFF);                                                        // Останавливаем вайфай
  delay(1000);
  WiFi.mode(WIFI_STA);                                                        // Запускаем вайфай в режиме клиента
  Serial.println("\nOur mac = " + WiFi.macAddress());                         // Выводим мак адрес
  conekt_to_wifi(WiFi.scanNetworks());                                       // Стартуем функцию сканирования сети и поиска нужной сети
}

void loop() {
   conekt_to_wifi(WiFi.scanNetworks());                                       // Стартуем в цикле функцию сканирования сети и поиска нужной сети
}

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Что именно не получилось? 

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

Хотел вынести функцию conekt_to_wifi() в отдельный файл и подключить его. Пробовал разные варианты, получал разные ошибки. То дважды объявлял переменные, то наоборот не объявлены, то ещё какие-то.

sadman41
Offline
Зарегистрирован: 19.10.2016

Руководствуйтесь этим правилом: все переменные, функции и объекты должны быть объявлены ранее их использования. 

b707
Offline
Зарегистрирован: 26.05.2017

DyadyaGenya пишет:

Хотел вынести функцию conekt_to_wifi() в отдельный файл и подключить его. Пробовал разные варианты, получал разные ошибки.

главное правило - выносимая в отдельный файл функция не должна использовать никаких "внешних" переменных, структур, данных... а у вас ваша функция нуждается в массивах ssid и pass, например.

Если функции нужны какие-то данные из других частей программы - они должны передаваться как параметры. Глобальные переменные в других файлах НЕ РАБОТАЮТ!

То же самое с результатом работы функции - функция не должна менять какие-то глобальные переменные, все что она выполнила - должно передаваться через возвращаемые значения или через параметры, переданные по ссылке.

Кстати, кто мешает в вашем случае поместить ssid и pass в тот же файл, что и саму функцию?

Вообще, чтобы разбивать программу на отдельные файлы - ее, программу, надо с самого начала проектировать с расчетом на это.

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

b707 пишет:

 

Кстати, кто мешает в вашем случае поместить ssid и pass в тот же файл, что и саму функцию?

В принципе никто не мешает. Я делал такой вариант, были другие ошибки. С другой стороны, хотелось бы в одном месте видеть все вводимые, получаемые данные, а их обработку делать в другом месте. Тем более, что уж если начать разделять файл, то потом его нужно будет поделить больше чем на две части, разбить на группы функций.

И в принципе понимаю, что программу нужно планировать с самого начала. Но я ведь только учусь. Я эту программу не сразу написал. И она требует доработки. Хотя уже в такой стадии, что уже можно пробовать её разбивать. Вот когда научусь писать программы, тогда и начну изначально писать именно с разбивкой, если она того будет требовать.

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

Пробую, только не совсем понятно, что в каком порядке объявляется, когда файл разбит. Возможно я не правильно понял ситуацию, но ведь для этого и делают два файла .h/.cpp. В одном объявляют, в другом реализуют/используют. А вот как они соотносятся с главным файлом, для меня пока не понятно

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

b707 пишет:

Глобальные переменные в других файлах НЕ РАБОТАЮТ!

Как так? А модификатор extern ?

test.ino:

#include "ext.h"

uint32_t ExternalVarible;

void setup() {
  Serial.begin(9600);
  ExternalVarible = 0;
  tt ();
}

void loop() {

}

ext.h:

extern uint32_t ExternalVarible;

void tt ( )  {
 ExternalVarible = 7;
 Serial.print(ExternalVarible);
}

Не проверял, но компилируется и где-то уже использовал подобное...

b707
Offline
Зарегистрирован: 26.05.2017

DyadyaGenya пишет:

b707 пишет:

 

Кстати, кто мешает в вашем случае поместить ssid и pass в тот же файл, что и саму функцию?

В принципе никто не мешает. Я делал такой вариант, были другие ошибки. С другой стороны, хотелось бы в одном месте видеть все вводимые, получаемые данные, а их обработку делать в другом месте.

другой путь - передавать нужные данные из основной программы в функцию как параметры. Но тогда надо думать о правильной организации данных. Например все те же массивы ssid и pass у вас организованы не слишком удобно - как массивы неопределенного числа ссылок на строки неизвестного размера... придется передавать не только ссылки на данные, но и их размер как отдельный параметр. Впрочем, для ссылок на массивы это стандартная практика

Green
Offline
Зарегистрирован: 01.10.2015

Лень читать.) Нужно разбивать на файлы по логике. К примеру led.cpp и led.h описание и т.д. Это как положено. Другое дело что Арудино позволяет создавать множество ino файлов, которые собирает автоматом. Это для ленивых, но временами, удобно.)

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

b707 пишет:

другой путь - передавать нужные данные из основной программы в функцию как параметры. Но тогда надо думать о правильной организации данных. Например все те же массивы ssid и pass у вас организованы не слишком удобно - как массивы неопределенного числа ссылок на строки неизвестного размера... придется передавать не только ссылки на данные, но и их размер как отдельный параметр. Впрочем, для ссылок на массивы это стандартная практика

Сейчас как раз пробую с этим разобраться и ещё с многомерными массивами. Ну как сейчас... Типа в ближайших планах. Но пока примеров маловато. Не все понимаю.

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

Green пишет:

Лень читать.) Нужно разбивать на файлы по логике. К примеру led.cpp и led.h описание и т.д. Это как положено. Другое дело что Арудино позволяет создавать множество ino файлов, которые собирает автоматом. Это для ленивых, но временами, удобно.)

Это вы про себя, что вам лень читать? Бывает. Только не понятно, что конкретно вам лень читать.

Я то с вами согласен. Самый простой способ тупо разбить файл на нужное число частей, допустим по одному файлу на одну функцию и сохранить с расширением ino. Об этом варианте я написал выше. Он работает. Но мне интересно разобраться с разбивкой на файлы .h/.cpp

b707
Offline
Зарегистрирован: 26.05.2017

многомерные массивы.... не увлекайтесь ими.

Массивы a[2][2] и b[4] организованы в памяти одинаково и занимают одинаковое место, но если передавать данные между процедурами или писать на носители - одномерный значительно проще и удобнее

DyadyaGenya
Offline
Зарегистрирован: 23.06.2022

Пока что я не понял, как организовать цикл перебора многомерного массива, а там будет видно. И конечно, может окажется, что в данной ситуации одномерный выгоднее. Но очень хотелось бы больше удобств при добавлении данных. Чтоб не по отдельности добавлять ссид в один массив, потом к нему пароль в другой массив, а сразу парой, типа ключ:значение или индекс:значение или словарь:список. Кому как удобней и привычней понимать.

Да и если вдруг как-то эти данные придется использовать в джсоне, то удобней именно многмерный массив. Но я до конца структуру программы не продумал. Это ж для Ардуино, фактически Си. Мне тут все новое.

Тем более, что читал, вроде есть возможность на некоторые платы делать заливку через вэб. Да и вообще, мало ли что захочу передать через вэб. Вот, пока тренируюсь

Green
Offline
Зарегистрирован: 01.10.2015

Дядя Гена, тренируйтесь. "Не дойдёт через голову - дойдёт через..." руки. А не дойдёт - тогда ой.(