How to create a large String separated with line breaks

I'm on the way on creating a method for building PDF reports with Arduino and ESP32.
One of the main requierments it's to add to the code the lines that will define the .PDF wich is a large code separated with line breaks such as:

%PDF-1.7
%‚ýþ
3 0 obj 
<<
/CreationDate (D:20210823131906-05'00')
/ModDate (D:20210823131906-05'00')
/Producer <6954657874ae20372e312e3220a9323030302d323031382069546578742047726f7570204e5620284147504c2d76657273696f6e29>
>>
endobj
1 0 obj 
<<
/Pages 2 0 R
/Type /Catalog
>>
endobj
2 0 obj 
<<
/Count 2
/Kids [ 4 0 R 6 0 R ]
/Type /Pages
>>
endobj
4 0 obj 
<<
/Contents 5 0 R
/MediaBox [ 0 0 595 842 ]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 8 0 R
/F2 9 0 R
/F3 10 0 R
/F4 11 0 R
>>
>>
/TrimBox [ 0 0 595 842 ]
/Type /Page
>>
endobj
5 0 obj 
<<
/Length 3799
>>
stream
30 740 m
550 740 l
S
30 665 m
550 665 l
S
30 608 m
550 608 l
S
30 543 m
550 543 l
S
q
BT
/F1 20 Tf
186 785.34 Td
5 Tc
(DATA REPORT)Tj
ET
Q
q
BT
/F2 11 Tf
36 760.39 Td
( )Tj
ET
Q
q
BT
/F2 11 Tf
36 743.9 Td
(Información del archivo)Tj
ET
Q
q
BT
/F3 8 Tf
36 722.96 Td
(Fecha de creación del archivo:        12/08/2021 16:59:08)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 711.3 Td
(Unidad:                                             ISUZUS)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 699.64 Td
(Ruta:                                                 NOVAC guadalajara)Tj
ET
Q
q
BT
/F3 8 Tf
256 713.97 Td
(Chofer:                     Angel Alberto Castellanos)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
256 702.31 Td
(Copiloto:                  scarlett johansson)Tj
ET
Q
q
BT
/F3 6 Tf
36 689.66 Td
(Nota: Todas las horas se basan en UTC-5: 00 y en formato de 24 horas \(MM/DD/YY HH:MM:SS\))Tj
ET
Q
q
BT
/F2 11 Tf
36 667.35 Td
(Información del dispositivo)Tj
ET
Q
q
BT
/F3 8 Tf
36 646.41 Td
(Nombre del dispositivo:     M_TFT_M)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 634.75 Td
(Intervalo de registro:         1 min)Tj
ET
Q
q
BT
/F3 8 Tf
216 646.08 Td
(Retraso de inicio:          0 min)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
216 634.42 Td
(Descripción:                 Lectura de temperatura)Tj
ET
Q
q
BT
/F2 11 Tf
36 611.21 Td
(Resumen de registro)Tj
ET
Q
q
BT
/F3 8 Tf
36 590.27 Td
(Inicio de grabado:             12/08/2021 16:59:08)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 578.61 Td
(fin de grabado:                  12/08/2021 18:06:00)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 566.94 Td
(Duración del grabado:      00d 01h 06m 52s)Tj
ET
Q
q
BT
/F3 8 Tf
216 591.28 Td
(Numero de lecturas:        429)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
216 579.62 Td
(Temperatura maxima:      17.0)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
216 567.95 Td
(Temperatura minima:       16.5)Tj
ET
Q
q
BT
/F3 8 Tf
336 592.29 Td
(Temperatura promedio:   16.75)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
336 580.62 Td
( )Tj
ET
Q
q
BT
/F3 8 Tf
336 568.96 Td
( )Tj
ET
Q
q
BT
/F2 11 Tf
36 545.75 Td
(Tiempo de alarma)Tj
ET
Q
q
BT
/F3 8 Tf
36 524.81 Td
(Mayor a 8 C:                   00/00/00 00:19:00)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 513.15 Td
(Menor a 2 C:                  00/00/00 00:15:00)Tj
ET
Q
q
BT
/F3 8 Tf
236 545.49 Td
(Numero de infracciones)Tj
ET
Q
q
BT
/F3 8 Tf
236 524.82 Td
(5)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
236 513.16 Td
(0)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
236 501.49 Td
( )Tj
ET
Q
q
BT
/F3 8 Tf
236 489.83 Td
( )Tj
ET
Q
q
BT
/F3 8 Tf
236 478.17 Td
( )Tj
ET
Q
q
BT
/F4 6 Tf
36 460.23 Td
(FECHA )Tj
22.332001 0 Td
(\t)Tj
6.672 0 Td
(\t)Tj
6.672 0 Td
(   HORA)Tj
22.668001 0 Td
(\t)Tj
6.672 0 Td
(\t)Tj
6.672 0 Td
(   AMB)Tj
18.666 0 Td
(\t)Tj
6.672 0 Td
( EVAP  CAJA)Tj
37.674 0 Td
(\t)Tj
6.672 0 Td
(S4  )Tj
10.674 0 Td
(\t)Tj
6.672 0 Td
(  S5)Tj
( )Tj
ET
Q
q
.......................................(

One method will be using a file.write(dataFile.println(String); ) for every new line. I find this a bit tedious taking in count that the PDF code could be very extensive, more than 1k lines, so i was wondering if maybe i can create a big String that contains the code with the linkes breaks and everything...maybe using Tabs? Or copying the whole text from another .txt file? I would appreciate any help on this. If you are interested on creating PDF reports with arduino i can give you a hand, im not an exper(yet) but i can share what i found! :slight_smile:

Is this what you're looking for?

char *lineWithLineBreak = "Hello\nWorld";

The \n is the linefeed character; \r is the carriagereturn character. The println functions add a carriage return and a linefeed.

1 Like

use C++ capability called a Raw string literal

here is an example:

create a new sketch (.ino) with this code

#include "pdf.h"

void setup() {
  Serial.begin(115200);
  Serial.println(F("\n\n--- PDF HEADER ---"));

  Serial.println((const __FlashStringHelper*) pdfHeader);
}

void loop() {}

now, create a new tab in that sketch and call it pdf.h

in this second tab, you paste all your text directly into a raw literal. A raw literal looks like this

R"delimiter(raw_characters)delimiter"

so you start with R and a opening quote, you put some text you want to use as a delimiter, I used --8<--8<-- (representing small scissors) but you can put what you want, then open a parenthesis.
Whatever comes after the parenthesis is your string and you can add returns, quotes without escaping them etc... whatever is there is just considered as part of the variable.
then you close the parenthesis and have the delimiter again and close the quotes.

so mine looks like this R"--8<--8<--( your text goes here)--8<--8<--"

of course, be smart with the delimiter, if ever )--8<--8<--" could occur in your text then compiler would get confused...

// C++ raw string literals cf http://en.cppreference.com/w/cpp/language/string_literal
// on AVR USE PROGMEM with Program Space Utilities http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

const char pdfHeader[] PROGMEM = R"--8<--8<--(%PDF-1.7
%‚ýþ
3 0 obj 
<<
/CreationDate (D:20210823131906-05'00')
/ModDate (D:20210823131906-05'00')
/Producer <6954657874ae20372e312e3220a9323030302d323031382069546578742047726f7570204e5620284147504c2d76657273696f6e29>
>>
endobj
1 0 obj 
<<
/Pages 2 0 R
/Type /Catalog
>>
endobj
2 0 obj 
<<
/Count 2
/Kids [ 4 0 R 6 0 R ]
/Type /Pages
>>
endobj
4 0 obj 
<<
/Contents 5 0 R
/MediaBox [ 0 0 595 842 ]
/Parent 2 0 R
/Resources <<
/Font <<
/F1 8 0 R
/F2 9 0 R
/F3 10 0 R
/F4 11 0 R
>>
>>
/TrimBox [ 0 0 595 842 ]
/Type /Page
>>
endobj
5 0 obj 
<<
/Length 3799
>>
stream
30 740 m
550 740 l
S
30 665 m
550 665 l
S
30 608 m
550 608 l
S
30 543 m
550 543 l
S
q
BT
/F1 20 Tf
186 785.34 Td
5 Tc
(DATA REPORT)Tj
ET
Q
q
BT
/F2 11 Tf
36 760.39 Td
( )Tj
ET
Q
q
BT
/F2 11 Tf
36 743.9 Td
(Información del archivo)Tj
ET
Q
q
BT
/F3 8 Tf
36 722.96 Td
(Fecha de creación del archivo:        12/08/2021 16:59:08)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 711.3 Td
(Unidad:                                             ISUZUS)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 699.64 Td
(Ruta:                                                 NOVAC guadalajara)Tj
ET
Q
q
BT
/F3 8 Tf
256 713.97 Td
(Chofer:                     Angel Alberto Castellanos)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
256 702.31 Td
(Copiloto:                  scarlett johansson)Tj
ET
Q
q
BT
/F3 6 Tf
36 689.66 Td
(Nota: Todas las horas se basan en UTC-5: 00 y en formato de 24 horas \(MM/DD/YY HH:MM:SS\))Tj
ET
Q
q
BT
/F2 11 Tf
36 667.35 Td
(Información del dispositivo)Tj
ET
Q
q
BT
/F3 8 Tf
36 646.41 Td
(Nombre del dispositivo:     M_TFT_M)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 634.75 Td
(Intervalo de registro:         1 min)Tj
ET
Q
q
BT
/F3 8 Tf
216 646.08 Td
(Retraso de inicio:          0 min)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
216 634.42 Td
(Descripción:                 Lectura de temperatura)Tj
ET
Q
q
BT
/F2 11 Tf
36 611.21 Td
(Resumen de registro)Tj
ET
Q
q
BT
/F3 8 Tf
36 590.27 Td
(Inicio de grabado:             12/08/2021 16:59:08)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 578.61 Td
(fin de grabado:                  12/08/2021 18:06:00)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 566.94 Td
(Duración del grabado:      00d 01h 06m 52s)Tj
ET
Q
q
BT
/F3 8 Tf
216 591.28 Td
(Numero de lecturas:        429)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
216 579.62 Td
(Temperatura maxima:      17.0)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
216 567.95 Td
(Temperatura minima:       16.5)Tj
ET
Q
q
BT
/F3 8 Tf
336 592.29 Td
(Temperatura promedio:   16.75)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
336 580.62 Td
( )Tj
ET
Q
q
BT
/F3 8 Tf
336 568.96 Td
( )Tj
ET
Q
q
BT
/F2 11 Tf
36 545.75 Td
(Tiempo de alarma)Tj
ET
Q
q
BT
/F3 8 Tf
36 524.81 Td
(Mayor a 8 C:                   00/00/00 00:19:00)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
36 513.15 Td
(Menor a 2 C:                  00/00/00 00:15:00)Tj
ET
Q
q
BT
/F3 8 Tf
236 545.49 Td
(Numero de infracciones)Tj
ET
Q
q
BT
/F3 8 Tf
236 524.82 Td
(5)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
236 513.16 Td
(0)Tj
( )Tj
ET
Q
q
BT
/F3 8 Tf
236 501.49 Td
( )Tj
ET
Q
q
BT
/F3 8 Tf
236 489.83 Td
( )Tj
ET
Q
q
BT
/F3 8 Tf
236 478.17 Td
( )Tj
ET
Q
q
BT
/F4 6 Tf
36 460.23 Td
(FECHA )Tj
22.332001 0 Td
(\t)Tj
6.672 0 Td
(\t)Tj
6.672 0 Td
(   HORA)Tj
22.668001 0 Td
(\t)Tj
6.672 0 Td
(\t)Tj
6.672 0 Td
(   AMB)Tj
18.666 0 Td
(\t)Tj
6.672 0 Td
( EVAP  CAJA)Tj
37.674 0 Td
(\t)Tj
6.672 0 Td
(S4  )Tj
10.674 0 Td
(\t)Tj
6.672 0 Td
(  S5)Tj
( )Tj
ET
Q
q
.......................................(
)--8<--8<--";

if you compile that and open the Serial monitor at 115200 bauds, you'll see the full thing being printed.

on an ESP32 you don't need the PROGMEM nor the cast to (const __FlashStringHelper*), the compiler will take a const char array into flash I think

1 Like

'\n' (linefeed/Newline) is the C syntax for the code 0x0A
'\r' (carriage return) is the C syntax for the code 0x0D
println() method sends only 0x0D (experimentally seen) which means that println() adds only carriage return.

You need to revise the way you draw conclusions... Your experiments are misleading you... The code is the ultimate documentation...

size_t Print::println(void)
{
  return write("\r\n");
}

1. From I2C Master, I executed the following codes:

void loop()
{
  Wire.beginTransmission(8);
  Wire.println();
  Wire.endTransmission();
  delay(1500);
}

2. At the I2C Slave side, I executed the following codes:

void loop()
{
  if (flag == true)
  {
    Serial.println(x1, HEX);
    flag = false;
  }
}

void receiveEvent(int howMany)
{
  x1 = Wire.read();
  flag = true;
}

3. The Slave's Serial Monitor Shows:

23:49:07.799 -> D

come on, you are better than this... :wink:
think a bit about your code... how many bytes did you read (versus how many were sent)?

I have got it now!

23:52:49.976 -> D
23:52:49.976 -> 2 ( = howMany)

Yes! Two bytes are coming from Master. I am going to print A (0x0A) for '\n'.

here you go !!

(for testing purpose it's OK to print those two bytes in the Wire ISR context, that will be OK experimentally :wink: )

void receiveEvent(int howMany)
{
  n = howMany;
  Serial.println(n, DEC);
  x1 = Wire.read();
  Serial.println(x1, HEX);
  Serial.println(Wire.read(), HEX);
  flag = true;
}

Output:

23:59:53.350 -> 2
23:59:53.350 -> D
23:59:53.350 -> A

One should have enough courage to doubt things and then educate oneself.

Of course ! (As long as you trust the code you write to prove your point is OK).

I prefer to go check what the source code says should happen - most of the time it is what happens :slight_smile:

1 Like

Thanks, it worked perfectly!

great - have fun