Несколько файлов .ino в одном скетче

arduino-setup

Да, да, я знаю, что люди часто задают подобные вопросы, но я нигде не мог найти ответа.

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

Я пишу программу Брайля для NodeMCU - она принимает сообщение с обслуживаемого сайта и перемещает сервоприводы для эмуляции соответствующего шрифта Брайля. Я хочу иметь 2 файла: один для обслуживания сайта и получения от него входных данных (website.ino), а другой для управления сервоприводами(шрифт Брайля.ino). Единственная проблема в том, что я не могу понять, где объявить/прикрепить сервоприводы.

Я планирую иметь список сервоприводов в braille.ino, который будет зацикливаться на каждом сервоприводе, устанавливаемом на другое значение. Если я объявлю их в файле website.ino (мой "основной" файл, т.е. с setup и loop), мне придется каждый раз передавать их в свою braille функцию. С другой стороны, если я решу объявить их глобальными в своем braille.ino, куда их прикрепить? Можно мне еще один setup на braille.ino?

, 👍11

Обсуждение

Я хотел того же, и моим решением было использовать MS Visual Studio с Arduino IDE от Visual Micro. Это упрощает использование нескольких файлов и имеет множество дополнительных преимуществ. [![введите описание изображения здесь](https://i.stack.imgur.com/YQeBV.png)](https://i.stack.imgur.com/YQeBV.png), @Edgar

просто есть код в "main" .ino, вызывающий функцию, которую вы определяете в любом последующем .ino, @Jaromanda X

Вы можете использовать VS-код с расширением "vscode-arduino". Это позволит вам управлять несколькими файлами .ino в виде вкладок, как это делается в среде IDE Arduino. Плюс преимущества intellisense. Проверьте производителя.профессиональный веб-сайт о том, как: https://maker.pro/arduino/tutorial/how-to-use-visual-studio-code-for-arduino, @Miguel Silva


3 ответа


Лучший ответ:

13

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

Таким образом, вы можете сгруппировать "вспомогательные" функции в разных файлах по категориям - например, файл BrailleServo.c. Они содержат функции и переменные только для этой категории.

Если вы не запрограммировали родной язык C/C++:

  • Поместите функции и переменные в файл BrailleServo.c, а затем повторите заголовок функций в файле BrailleServo.h.
  • Внутри файла BrailleServo.c, вверху, поместите следующую строку:

    #include "BrailleServo.h"
    

    Обратите внимание на кавычки (" "), а не на угловые скобки (< >< >)

  • Внутри файла .ino поместите ту же строку #include. Это говорит модулю, что "в другом месте есть другие функции, и это их определения".

Единственная проблема? Получение глупой среды Arduino, позволяющей добавлять файлы .c и .h в этот каталог. Вы могли бы просто использовать Блокнот, но есть одна хитрость (если вы используете Windows):

  1. Выберите Файл|Открыть...
  2. Щелкните правой кнопкой мыши панель с файлами в ней и выберите Создать >>|Текстовый документ
  3. Дайте ему полное имя и убедитесь, что вы также заменили часть имени .txt на .c или .h. Вы можете получить предупреждение "Если вы измените расширение, файл может быть непригоден для использования" - просто нажмите кнопку ОК.
  4. Выберите новый (пустой) файл на панели файлов, и появится новая вкладка.

Обратите внимание, что 3. выше предполагается, что вы сказали проводнику файлов Windows НЕ скрывать расширения известных типов файлов. Я всегда так делаю - если нет, тебе придется. С помощью:

  • Windows 10: На вкладке Просмотр любой папки установите флажок Расширения имен файлов;
  • Windows 7: На вкладке "Панель управления | Внешний вид и персонализация | Параметры папок"снимитегалочку" Скрыть расширения для известных типов файлов".

Вот три примера:

BrailleServo.h

//
// BrailleServo.h
//

// Call this function once in setup()
void BrailleInit();

// This function activates the six servos to form the passed-in pattern.
void BrailleShow(byte pattern);

BrailleServo.c

//
// BrailleServo.c
//

#include "BrailleServo.h"

// The number of servos
const byte NumServos = 6;

// These are the pins for the six servos
const byte servo[NumServos] = { 3, 4, 6, 7, 9, 10 };

// This initialises the six servos
void BrailleInit() {
   for (byte i=0; i<NumServos; ++i) {
      pinMode(servo[i], OUTPUT);
      // Do what else you need to do with servo[i]
   } // for
} // BrailleInit()

// This is how to use the six servos to form the passed-in pattern
void BrailleShow(byte pattern) {
   // … Complicated code here …
} // BrailleShow(pattern)

Главная.ino

//
// Main.ino
//

#include "BrailleServo.h"

void setup() {
   BrailleInit();
   // Other stuff
} // setup()

void loop() {
   BrailleShow('A');
   delay(1000);
   BrailleShow('B');
   delay(1000);
} // loop()

Кстати, для получения идей вы, возможно, захотите ознакомиться с моим ответом на более общий вопрос Брайля.

,

Большое спасибо! Наверное, я на самом деле не думал о том, чтобы сервоприводы что-то делали, пока они не были прикреплены, но я думаю, что именно это происходит, когда вы работаете сверхурочно. Я не думаю, что буду утруждать себя перекодированием букв, так как у меня уже есть массивы true-false, но все равно спасибо!, @Levi Lesches


0

Я хотел того же, и моим решением было использовать MS Visual Studio с Arduino IDE от Visual Micro. Это упрощает использование нескольких файлов и имеет множество дополнительных преимуществ.

,

Лично я предпочитаю плагин "Stino" для Sublime Text, но это не отвечает на мой вопрос: куда идет настройка? Как мне передать сервоприводы по командной цепочке?, @Levi Lesches

Если вы идете по маршруту MS, код MS Visual Studio (потому что он кроссплатформенный) плюс platformio - особенно если вы используете nodemcu (и другие микроконтроллеры, отличные от arduino), @Jaromanda X


4

Важно знать, что файлы вкладок/ino объединяются в один с помощью конструктора. Порядок объединения такой же, как и порядок вкладок в IDE. Первый-это основной файл ino с тем же именем, что и у проекта. Остальные файлы объединены в алфавитном порядке.

Объединенный файл ino определяет видимость переменных. Все файлы ino "видят" переменные в основном файле ino, но переменные в других файлах ino видны только в файле ino с именами, расположенными далее в алфавитном порядке.

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

Один из способов работы с дополнительными вкладками-это группировать функции xySetup() и xyLoop() в файле xy.ino, а затем вызывать эти функции из основной настройки() и цикла(). Мой основной проект Arduino создан таким образом, так что это большой и сложный пример такого подхода.

Чтобы проиллюстрировать, это результирующий файл cpp, входящий в часть cpp набора инструментов сборки (прокрутите его до конца):

#include "Arduino.h"
#define I2C_ADC121         0x50
#include <Wire.h>
extern const unsigned long EVENTS_SAVE_INTERVAL_SEC;
extern const char eventLabels[];
extern const char* eventLongLabels[];
extern const char* eventLongLabels[];
#define EVENTS_FILENAME "EVENTS.DAT"
#include <Grove_LED_Bar.h>
#include <StreamLib.h>
#include <TimeLib.h>
#include <MemoryFree.h>
#include <UIPEthernet.h>
#define ETHERNET
#include <ArduinoOTA.h>
#include <SD.h>
#define FS SD
#define Serial SerialUSB
#include "consts.h"
#define BLYNK_PRINT Serial
#define BLYNK_NO_BUILTIN // Blynk doesn't handle pins
#include <BlynkSimpleUIPEthernet.h>
#include <RTCZero.h>
#define STATS_FILENAME "STATS.DAT"

void balboaSetup() ;
void balboaReset() ;
void balboaLoop() ;
void battSettLoop() ;
boolean battSettRead(FormattedPrint& out) ;
const char* bit2s(int value, byte mask) ;
int battSettControl(boolean chargeControlOn, boolean dischargeControlOn) ;
int battSettSetLimit(byte reg, int limit) ;
void beeperLoop() ;
void alarmSound() ;
void beep() ;
void beeperTone(int freq, uint32_t time) ;
void blynkSetup() ;
void blynkLoop() ;
void updateWidgets() ;
void buttonSetup() ;
void buttonLoop() ;
void csvLogSetup() ;
void csvLogLoop() ;
void csvLogPrintJson(FormattedPrint& out) ;
void elsensSetup() ;
void elsensLoop() ;
boolean elsensCheckPump() ;
byte overheatedSecondsLeft() ;
int readElSens() ;
unsigned short elsensAnalogRead() ;
void eventsSetup() ;
void eventsLoop() ;
void eventsWrite(int newEvent, int value1, int value2) ;
boolean eventsSaved() ;
void eventsSave() ;
byte eventsRealCount() ;
void eventsPrint(FormattedPrint& stream) ;
void eventsPrint(FormattedPrint& s, int ix) ;
void eventsPrintJson(FormattedPrint& stream) ;
void eventsPrintJson(FormattedPrint& stream, int ix) ;
void eventsBlynk() ;
int eventsCompare(const void * elem1, const void * elem2) ;
void ledBarSetup() ;
void ledBarLoop() ;
void manualRunLoop() ;
byte manualRunMinutesLeft() ;
void modbusSetup() ;
boolean modbusLoop() ;
void modbusClearData() ;
boolean requestSymoRTC() ;
boolean requestInverter() ;
boolean requestMeter() ;
boolean requestBattery() ;
boolean modbusError(int err) ;
int modbusRequest(byte uid, unsigned int addr, byte len, short *regs) ;
int modbusWriteSingle(unsigned int address, int val) ;
int modbusConnection() ;
void pilotLoop() ;
unsigned short power2pwm(int power) ;
void setup() ;
void loop() ;
void shutdown() ;
void handleSuspendAndOff() ;
void clearData() ;
boolean handleAlarm() ;
boolean restHours() ;
boolean turnMainRelayOn() ;
boolean networkConnected() ;
void statsSetup() ;
void statsLoop() ;
int statsEvalCurrentPower() ;
void statsAddMilliwats() ;
void statsSave() ;
int statsConsumedPowerToday() ;
void statsPrint(FormattedPrint& out) ;
void statsPrint(FormattedPrint& out, const char *label, Stats &stats) ;
void statsPrintJson(FormattedPrint& out) ;
void statusLedSetup() ;
void statusLedLopp() ;
void statusLedShortBlink() ;
void susCalibLoop() ;
void telnetSetup() ;
void telnetLoop(boolean log) ;
void valvesBackSetup() ;
void valvesBackReset() ;
void valvesBackLoop() ;
void valvesBackStart(int v) ;
boolean valvesBackExecuted() ;
unsigned short valvesBackTempSensRead() ;
void watchdogSetup() ;
void watchdogLoop() ;
void WDT_Handler(void) ;
void webServerSetup() ;
void webServerLoop() ;
void webServerRestRequest(char cmd, ChunkedPrint& chunked) ;
void webServerServeFile(const char *fn, BufferedPrint& bp) ;
void printValuesJson(FormattedPrint& client) ;
void printAlarmJson(FormattedPrint& client) ;
const char* getContentType(const char* ext);
void wemoLoop() ;
boolean wemoPowerUsage() ;
int wemoRequest(const char* service, const char* action, const char* param, const char* value, char* response, size_t size) ;

#include "Regulator.ino"

#include "Balboa.ino"
#include "BattSett.ino"
#include "Beeper.ino"
#include "Blynk.ino"
#include "Button.ino"
#include "CsvLog.ino"
#include "ElSens.ino"
#include "Events.ino"
#include "LedBar.ino"
#include "ManualRun.ino"
#include "Modbus.ino"
#include "PowerPilot.ino"
#include "Stats.ino"
#include "StatusLed.ino"
#include "SusCalib.ino"
#include "Telnet.ino"
#include "ValvesBack.ino"
#include "Watchdog.ino"
#include "WebServer.ino"
#include "WemoInsight.ino"
,