Display struct member on epaper

Hi. Anyone have any idea why i can't pass a struct member to this function for it to display on an epaper? Ive called char arrays with u8g2Fonts.print() and display.print() before, also regular text. I know the struct members have the info in them because they read out in the serial monitor but when i try to call the atruct members in this function they wont display, it just skips over and is blank on the scree , but the "TEST" text displays as normal. Any help appreciated, I'm going crazy. Ive tried casting to string etc but nothing ever comes up. The file is long so i only posted this snippet but ill put the entire thing if needed. Thank you.

struct myStruct { // creating a struct to store the individual words of the label
  char number[10];
  char id[10];
  char type[10];
  char description[45];
  char sig[10];
  char date[25];
};

struct myStruct words;
// String  str = "1615 GL


void displayText()
{
   display.setRotation(1);
  display.setPartialWindow(180, 0, 146, 128);
    uint16_t bg = GxEPD_WHITE;
  uint16_t fg = GxEPD_BLACK;
  u8g2Fonts.setForegroundColor(fg);         // apply Adafruit GFX color
  u8g2Fonts.setBackgroundColor(bg);
  u8g2Fonts.setFont(u8g2_font_nokiafc22_tf);
  display.firstPage();
  do{
    display.fillScreen(GxEPD_WHITE);
   u8g2Fonts.setCursor(180,10);
   u8g2Fonts.print(words.sig);
      u8g2Fonts.setCursor(180,20);
   u8g2Fonts.print("TEST");
    }while (display.nextPage());
 }

Where do you define the value of words.sig ?

Rather than a snippet, or "the entire thing", please make a complete sketch that compiles, runs and illustrates the problem.

This is known as an MRE, minimal reproducible example, and is a good way to be sure you've actually isolated the true problem, and a good place for us to start thinking about it (your problem) seriously.

Yeah, we could do the same thing. Save N of us the trouble of doing it N times by doing it once!

TIA

a7

#include <qrcode.h>
#include <GxEPD2_BW.h>
#include <U8g2_for_Adafruit_GFX.h>
#include "GxEPD2_display_selection_new_style.h"
#define DEBUG 1
#if DEBUG
#define PRINTS(s)     do { Serial.print(F(s)); } while (false)
#define PRINT(s, v)   do { Serial.print(F(s)); Serial.print(v); } while (false)
#else
#define PRINTS(s)
#define PRINT(s, v)
#endif
U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;
U8G2_FOR_ADAFRUIT_GFX u8g2;
QRCode QR;
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <WebSerial.h>
#include "data.h"
#define LED 2
AsyncWebServer server(80);
const char* ssid = "";          // Your WiFi SSID
const char* password = ""; 
const uint16_t MSG_BUF_SIZE = 150;
char mesg[MSG_BUF_SIZE] = { '\0' }; // Serial input message buffer
const uint8_t QR_VERSION = 4;
const uint8_t QR_QUIET_ZONE = 2;    // quiet zone all around
const uint8_t LINES_COUNT = 20;
const uint8_t LINE_CONTENT_SIZE = 60;
char individual_labels[LINES_COUNT][LINE_CONTENT_SIZE]={NULL}; // a 2D array to store the splitted lines from the text stored in the header file
struct myStruct { // creating a struct to store the individual words of the label
  char number[10];
  char id[10];
  char type[10];
  char description[45];
  char sig[10];
  char date[25];
};

struct myStruct words;
// String  str = "1615 GL


void displayText()
{
   display.setRotation(1);
  display.setPartialWindow(180, 0, 146, 128);
    uint16_t bg = GxEPD_WHITE;
  uint16_t fg = GxEPD_BLACK;
  u8g2Fonts.setForegroundColor(fg);         // apply Adafruit GFX color
  u8g2Fonts.setBackgroundColor(bg);
  u8g2Fonts.setFont(u8g2_font_nokiafc22_tf);
  display.firstPage();
  do{
    display.fillScreen(GxEPD_WHITE);
   u8g2Fonts.setCursor(180,10);
   u8g2Fonts.print(String(words.sig));
      u8g2Fonts.setCursor(180,20);
   u8g2Fonts.print("TEST");
    }while (display.nextPage());
 }






bool readSerial(void)
{
  static char* cp = mesg;
  bool gotNewData = false;
 
  while (Serial.available())
  {
    *cp = (char)Serial.read();
    if ((*cp == '\n') || (cp - mesg >= MSG_BUF_SIZE - 2)) // end of message character or full buffer
    {
      *cp = '\0'; // end the string
      // restart the index for next filling spree and 
      // flag we have a message waiting
      cp = mesg;
      gotNewData = true;
    }
    else  // move char pointer to next position
      cp++;
  }
   
  return(gotNewData);
}
 
void word_grabber(char *arr, struct myStruct words)
{
  char * pch; // a pointer to keep track of current location
  Serial.printf ("Splitting the string \"%s\" into single words:\n",arr);
  // give it a read if you want to more about this function: https://cplusplus.com/reference/cstring/strtok/
  pch = strtok (arr," ");
  unsigned char rep = 0;
  bool date_key = true;
  while (pch != NULL)
  {
    if (rep == 0) 
    {
      strcpy(words.number, pch);
      Serial.printf ("Number: %s\n",words.number);
    }
    else if (rep == 1)
    {
      strcpy(words.id, pch);
      Serial.printf ("ID: %s\n",words.id);
    }
    else if (rep == 2)
    {
      strcpy(words.type, pch);
      Serial.printf ("Type: %s\n",words.type);
    }
    else if (rep == 3)
    {
      strcpy(words.description, pch);
      Serial.printf ("Description: %s\n",words.description);
    }
    else if (rep == 4)
    {
      strcpy(words.sig, pch);
      Serial.printf ("Sig: %s\n",words.sig);
    }
    else
    {
      if (date_key) {strcat(words.date, pch);
        strcat(words.date, " ");
        date_key = false;
      }
      else {
        strcat(words.date, pch);
        Serial.printf("Date: %s\n", words.date);
      }
    }
    pch = strtok (NULL, " ");
    rep++;
  }
}

void recvMsg(uint8_t *data, size_t len){
  WebSerial.println("Received Data...");
  char web_buffer[MSG_BUF_SIZE]= { '\0' };
  for(int i=0; i < len; i++){
    web_buffer[i] = char(data[i]);
    if (i==len-1) web_buffer[i+1]=='\0';
  }
   displayQRCode(web_buffer, 0,0);
  WebSerial.println(web_buffer);
  Serial.printf("The data received from web is: %s\n",web_buffer);
  word_grabber(web_buffer,words);
  if (!strcmp(web_buffer,"ON")){
    digitalWrite(LED, HIGH);
  }
  if (!strcmp(web_buffer,"OFF")){
    digitalWrite(LED, LOW);
   
  }
  
}

void lines_grabber(String data)
{
  uint8_t rep=0;
  char saved_data[data.length() + 1];
  data.toCharArray(saved_data, saved_string.length() + 1);
  char* pch = NULL;

  pch = strtok(saved_data, "\r\n");

  while (pch != NULL)
  {
      strcpy(individual_labels[rep],pch);
      Serial.printf("%d: %s\n",rep+1, individual_labels[rep]);
      pch = strtok(NULL, "\r\n");
      rep++;
  }
}
void lines_splitter(uint8_t x, uint8_t y)
{
  for (uint8_t rep = 0; rep < x ; rep++)
  {
    if (individual_labels[rep] == NULL) continue;
    word_grabber(individual_labels[rep],words);
  }
}
void printQRBlock(uint16_t x, uint16_t y, uint16_t size, uint16_t col)
// Draw a square block of size pixels. Drawing individual pixels as this is faster
// that line segments and much faster that a filled rectangle.
{
  for (uint16_t i = 0; i < size; i++)
    for (uint16_t j = 0; j < size; j++)
      display.drawPixel(x + i, y + j, col);
}




void displayQRCode(char *msg, uint16_t x0, uint16_t y0)
// Paged display of the QR code with top left corner at (x0,y0) 
// on the display
{
   display.setRotation(1);
  display.setFullWindow();
  uint8_t QRData[qrcode_getBufferSize(QR_VERSION)];
  uint8_t blockSize;
  uint8_t page = 0;
 
  qrcode_initText(&QR, QRData, QR_VERSION, ECC_LOW, msg);
  PRINT("\n\nQR Size: ", QR.size);
  PRINT("\nLocation: ", x0);
  PRINT(",", y0);
  PRINT("\nDisplay Height: ", display.height());
 
  blockSize = (display.height() - (2 * QR_QUIET_ZONE)) / QR.size;
  PRINT("\nBlock Size: ", blockSize);
 
  Serial.print(F("\nGenerating QRCode Image - "));
  Serial.print(mesg);
  display.firstPage();
  do
  {
    page++;
    // Space all around
    display.fillRect(x0, y0, 
                     x0 + QR.size + (2 * QR_QUIET_ZONE), y0 + QR.size + (2 * QR_QUIET_ZONE),
                     GxEPD_WHITE);
 
    // For each vertical module
    for (uint8_t y = 0; y < QR.size; y++)
    {
      // Eor each horizontal module
      for (uint8_t x = 0; x < QR.size; x++)
      {
        if (qrcode_getModule(&QR, x, y))
          printQRBlock(x0 + (x * blockSize) + QR_QUIET_ZONE, 
                       y0 + (y * blockSize) + QR_QUIET_ZONE, 
                       blockSize, 
                       (qrcode_getModule(&QR, x, y)) ? GxEPD_BLACK : GxEPD_WHITE);
      }
    }
    } while (display.nextPage());

  Serial.print(F("\nEnd"));
  PRINT(" @ page ", page);
  
  
}



void setup()
{
  Serial.begin(115200);
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
  Serial.print(F("\n QR Code Generator\nEnter Data into Serial Monitor to Generate New QR Code\nEnsure line ending is newline"));
  display.init();
  delay(200);

  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.printf("WiFi Failed!\n");
    return;
  }

  // WebSerial is accessible at "<IP Address>/webserial" in browser
  WebSerial.begin(&server);
  WebSerial.msgCallback(recvMsg);
  server.begin();
  WebSerial.println("Hello!");

  u8g2Fonts.begin(display); // connect u8g2 procedures to Adafruit GFX
  delay(1000);
    SPI.end(); // release standard SPI pins,
  //SPI: void begin(int8_t sck=-1, int8_t miso=-1, int8_t mosi=-1, int8_t ss=-1);
  SPI.begin(13, 12, 14, 15); // map and init SPI pins SCK(13), MISO(12), MOSI(14), SS(15)
 lines_grabber(saved_string);
 
}


void loop() {
  
  if (readSerial())
  {
    displayQRCode(individual_labels[0], 0, 0);
    word_grabber(individual_labels[0], words);
    displayText();
   
   
  
   
   
  }}

Here is the main code. data.h contains:

String saved_string PROGMEM = R"(
1615 GL Ov Head NW 20 August
1615 GL  Ov in NW 20 August
1615 GL Ov Vent NW 20 August
1615 GL Ov Sit NW 20 August
1615 GL Ov Horizo NWO 20 August
1615 GLP02 Ov Horiz NW 20 August
)"; 

Sorry for not posting this originally. Everything works for me in this code except for this one part for displaying the struct members inside of the displayText(), and I don't know why. Also I moved stuff around a bunch trying different things to make this work so it's not aesthetically pleasing right now to some I'm sure.

   u8g2Fonts.print(String(words.sig));

Why the cast to String ?

You don't seem to be able to make your mind whether to use Strings or strings and keep converting between the two. Why not use one data type throughput the sketch ?

Have you tried printing pch before copying it to words.sig ?

That was just one of my many attempts to get that print() to work there, since everything I have tried it just comes up blank from the print(), but the test text works. Really confusing considering my previous version of this could print char arrays no problem. I haven't tried printing pch first, that is worth a try though. Will report back.

Good thought, but that didn't work either. I know it is something simple that I'm missing here...

I am so sure that in a small program with a null terminated character string fitting into sig this single line of code would work just fine that I am going to content myself with watching the problem come from somewhere very else.

a7

Hello

void word_grabber(char *arr, struct myStruct words)

This is wrong, you have to pass a reference to the struct :

void word_grabber(char *arr, struct myStruct & words)

1 Like

THANK YOU!!! It works as expected now. Cant believe I missed that, thank you so much, I have been pulling my hair out for several days on this. Legend

So you might have made your own test to confirm the obvious, now obvious to you, that you were fishing for red herring, and misdirecting us…

Many times I have found my own problem whilst preparing the case for presentation here. Never mind precisely how many times. :expressionless:

a7

edit: never mind. Just a difference between C and C++. I could waste your time on what I found, but suffice it to say it is one of the several ways IMO that C++ fails to carry over some of the best basic reliable concepts from C... please no language wars!

I'm having trouble understanding what was broken and why what fixed it did. Fix it.

Don't waste time, anyone, please, explaining it to me, I like to figure it out…

@bdoggdavis - if you would be so kind as to grab a minute and post your sketch that compiles and works that was the result of this inquiry I could see the fix in context.

TIA

a7

But there is nothing in C that cannot be done in C++, how would you have done it with C ? You would have to pass a myStruct pointer to the function, or change the function so it returns a new myStruct. With C++ you can pass by reference to make things a bit easier

By taking the address of the struct explicitly in the call, and declaring the function as receiving a pointer, and using that pointer in the function.

a7

You could do the same in C++. C++ just provides another way to do it (variable references).

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.