6

I'm developing a program that uses the HTML server in the WiFi101 library.

My hardware does not have SD card storage so all source html needs to be stored as strings in the sketch at compile time. To aid in development I want to keep my html files separate from the sketch and include them at compile time.

Is there a way to use #include in the Arduino IDE and assign the included file to a string/char array constant? If so can the path to the included file be relative to the sketch's path?

Notes: Similar question on Stack overflow: https://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char

Edit: There are lots of great answers here to solve this in a more robust fashion. The correct thing to do is setup a proper build system. If I were to set this up I'd be temped to try something like Gulp since you could easily minify/lint your web content. As this is a small project I ended up just running the HTML through a minifier service and copy/pasted into strings.

4
  • look at the toneMelody example in the IDE
    – jsotola
    Jan 27, 2019 at 8:58
  • Check this. Not sure it is easy to adapt that to the Arduino IDE though. Jan 27, 2019 at 9:12
  • No way for what you want in the Arduino IDE. UECIDE supports it though... - although UECIDE doesn't support the SAMD boards yet.
    – Majenko
    Jan 27, 2019 at 11:01
  • 1
    on SAMD Arduino architecture you could use FlashStorage instead of SD card
    – Juraj
    Jan 27, 2019 at 11:12

4 Answers 4

1

This will probably not work with the Arduino IDE. If you are willing to go through a Makefile-based workflow, you can install this generic Arduino Makefile, which should make things easier.

With that Makefile installed in /usr/share/arduino/Arduino.mk, the following test worked on an Arduino Uno. It is based on the objcopy trick from the article Embedding of binary data into programs.

Project's Makefile:

BOARD_TAG    = uno
MONITOR_PORT = /dev/ttyACM0
OTHER_OBJS   = text.o

include /usr/share/arduino/Arduino.mk

text.o: text.txt
    avr-objcopy -I binary -O elf32-avr -B avr:5 $< $@

text.txt:

Hello, World!

include-blob.ino

extern "C" const uint8_t _binary_text_txt_start[];
extern "C" const uint8_t _binary_text_txt_size;

void setup() {
    Serial.begin(9600);
    Serial.write(_binary_text_txt_start, (size_t) &_binary_text_txt_size);
}

void loop(){}

The program just prints “Hello, World!”, but if you modify text.txt and retype make, it will print whatever you had in this file. Please note that the text is not NUL-terminated, so you have to use the _binary_*_size symbol to know its size.

5

I found another way to include a literal file (html, css, or other) and assign it to a constant string without resorting to make files:

Add one line of code on top of your html (css, js, etc) file, and another at the bottom, and save it with an extra .h extension. Then include that file in de Arduino IDE. This could easily be done by a (manually executed) script, every time those files are changed.

const char *indexHtml = R"====( // added by script
<html> <!-- original .html file -->
.
.
.
</html> <!-- end .html -->
)===="; // added by script

The variable name can be derived from the original filename. The result is saved with an extra .h extension. In the .ino (or .cpp) you can then include this file:

#include index.html.h

This will compile in the Arduino IDE.

1

C++ has 'raw string literals'. You can put a constant string, without escaping special characters, into the source code between an opening and closing 'tag'. You can choose the tag to be something that is not in the raw string. In following example the tag is =====.

const char* s1 = R"=====(Hello
"World")=====";

is same as

const char* s2 = "Hello\n\"World\"";

This way you can put your large strings into separate .h files and include them. On AVR use PROGMEM to save RAM.

4
  • 1
    How does that help you include the contents of a file into that string literal?
    – Majenko
    Jan 27, 2019 at 11:08
  • @Majenko, the h file is The File then.
    – Juraj
    Jan 27, 2019 at 11:09
  • 1
    But the h file isn't the file. The .html file is the file. The OP doesn't want to have to manually convert that .html file into a header file for inclusion (and I can understand that if there are lots of HTML files that he wants to edit often).
    – Majenko
    Jan 27, 2019 at 11:18
  • @Majenko, this is an option if he doesn't want to use a SD card or other file system
    – Juraj
    Jan 27, 2019 at 11:27
0

An easy way to do this is to write a C program to convert your files that you want included into your source into a form that looks like:

byte file_001[] = { 0x00, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0A,
                    0x01, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0C,

                    ...

                    0x03, 0x01, 0x02, 0x04, 0x0A, 0x00, 0x01, 0x02, 0x04, 0x0C };

The converted file can contain binary data without issue instead of just ASCII.

You can then access the file directly using: file_001[index]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.