Char arr[] в String пустая строка

Здравствуйте!
Пытаюсь получить из char[512] String, но на выходе пустая строка.
Суть задачи - получить по http строку, вывести её в QR на дисплей.

Использую Arduino Uno.

#include "TFT.h"
#include "SPI.h"
#include <EtherCard.h>
#include "qrcode.h"
#include <EEPROM.h>
#include "assets.h"

#define DATA_FLAG 0xAA  // Маркер, указывающий наличие сохраненных данных в EEPROM

#define cs 7   // пин для подключения CS
#define dc 6   // пин для подключения A0
#define rst 5  // пин для подключения reset



struct NetConfig {
  byte myip[4];
  byte mymac[6];
};



// Функция сохранения настроек в EEPROM
void saveSettings(const NetConfig &cfg) {
  EEPROM.write(0x0, DATA_FLAG);  // Записываем маркер, указывающий наличие данных
  EEPROM.put(0x1, cfg);          // Сохраняем данные в EEPROM, начиная с адреса 0x1
}

// Функция загрузки дефолтных настроек
void loadDefaults(NetConfig &cfg) {
  // ethernet interface mac address, must be unique on the LAN
  byte defaultMac[] = { 0x74, 0x69, 0x69, 0x2D, 0x30, 0x31 };
  byte defaultIp[] = { 192, 168, 7, 2 };
  // Устанавливаем дефолтные значения
  memcpy(cfg.myip, defaultIp, 4);
  memcpy(cfg.mymac, defaultMac, 6);

  // Сохраняем дефолтные значения в EEPROM
  saveSettings(cfg);
}

// Функция загрузки настроек из EEPROM
void loadSettings(NetConfig &cfg) {
  if (EEPROM.read(0x0) == DATA_FLAG) {  // Проверяем наличие маркера
    EEPROM.get(0x1, cfg);               // Если маркер есть, загружаем настройки из EEPROM
  } else {
    loadDefaults(cfg);  // Если маркера нет, загружаем дефолтные настройки
  }
}

NetConfig cfg;


int16_t w, h;


static uint32_t timer;
static uint32_t httpTimer;

#define BUFFERSIZE 1200

byte Ethernet::buffer[BUFFERSIZE];

BufferFiller bfill;

TFT screen = TFT(cs, dc, rst);


static word sendOk() {
  bfill = ether.tcpOffset();
  bfill.emit_p(PSTR(
    "HTTP/1.0 200 OK\r\n"
    "Content-Type: application/json\r\n"
    "Pragma: no-cache\r\n"
    "\r\n"
    "{\"message\":\"OK\"}"));
  return bfill.position();
}

static word sendErr() {
  bfill = ether.tcpOffset();
  bfill.emit_p(PSTR(
    "HTTP/1.0 503 Service Unavailable\r\n"
    "Content-Type: application/json\r\n"
    "Pragma: no-cache\r\n"
    "\r\n"
    "{\"message\":\"device is busy\"}"));
  return bfill.position();
}


String dataString;
boolean isWelcomeScreen = false;

static void showCode(String &amount) {

  generateQRCode(amount);
}

static void welcome() {
  isWelcomeScreen = true;
  // цвет экрана дисплея ( r , g , b )
  screen.background(0, 0, 0);

  screen.drawBitmap(32, 0, ia_ic, 128, 128, 0xFFFFFF);
}

void generateQRCode(String &amount) {
  isWelcomeScreen = false;
  // Создаем QR-код
  QRCode qrcode;
  uint32_t str_len = amount.length() + 1;
  char am[str_len];
  amount.toCharArray(am, str_len);
  char *data = am;

  const uint8_t ecc = 0;  //самый низкий уровень исправления ошибок
  const uint8_t version = 5;

  uint8_t qrcodeData[qrcode_getBufferSize(version)];
  qrcode_initText(&qrcode,
                  qrcodeData,
                  version, ecc,
                  data);

  // Calculate the scale factor
  int scale = min(w / qrcode.size, h / qrcode.size);

  // Calculate horizontal shift
  int shiftX = (w - qrcode.size * scale) / 2;

  // Calculate horizontal shift
  int shiftY = (h - qrcode.size * scale) / 2;


  screen.background(255, 255, 255);

  screen.stroke(0, 0, 0);
  screen.fill(0, 0, 0);
  for (uint8_t y = 0; y < qrcode.size; y++) {
    for (uint8_t x = 0; x < qrcode.size; x++) {
      bool mod = qrcode_getModule(&qrcode, x, y);
      if (mod) {
        screen.fillRect(15 + shiftX + x * scale, shiftY + y * scale, scale, scale, 0x0000);
      }
    }
  }
}


void setup() {

  Serial.begin(57600);
  Serial.println(F("\nStart..."));

  delay(1000);
  screen.begin();

  w = screen.width();
  h = screen.height();

  screen.background(0, 0, 0);
  screen.setTextSize(1);
  screen.stroke(255, 255, 255);
  screen.text("Loading...", 45, 64);
  delay(1000);


  // Загружаем настройки из EEPROM или устанавливаем дефолтные
  loadSettings(cfg);
  Serial.println(F("\nSettings loaded!"));

  // Change 'SS' to your Slave Select pin, if you arn't using the default pin
  if (ether.begin(sizeof Ethernet::buffer, cfg.mymac, SS) == 0) {
    Serial.println(F("Failed to access Ethernet controller"));
    screen.background(0, 0, 0);
    screen.text("ERROR: Failed to access Ethernet controller", 45, 64);
    delay(5000);
  } else {
    Serial.println(F("\nEthernet controller OK!"));
  }

  if (!ether.dhcpSetup()) {
    Serial.println(F("DHCP failed"));
    screen.background(0, 0, 0);
    screen.text("ERROR: DHCP failed", 45, 64);
    delay(5000);
  } else {
    Serial.println(F("\nDHCP OK!"));
  }

  Serial.println(F("\nNetwork settings apply..."));
  ether.staticSetup(cfg.myip);
  ether.hisport = 8484;


  Serial.print(F("Serial port speed: "));
  Serial.println(F("57600"));
  Serial.println(F("Ethernet config: "));

  ether.printIp("IP:  ", ether.myip);
  ether.printIp("GW:  ", ether.gwip);
  ether.printIp("DNS: ", ether.dnsip);

  Serial.println(F("Started!"));
  welcome();

}

void loop() {

  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);

  if (pos) {

    char *data = (char *)Ethernet::buffer + pos;

    char body[512];
    char *command;
    int idx = 0;
    bool headersEnds = false;
    while ((command = strtok_r(data, "\n", &data)) != NULL) {
      if ((strlen(command) == 1) && (command[0] == 0x0D)) {
        headersEnds = true;
        idx++;
        continue;
      }
      if (headersEnds) {
        strcat(body, command);
        strcat(body, "\n");
      }
      idx++;
    }


    Serial.println(body);

    dataString = String(body);
    dataString.trim();
    Serial.println(dataString);

    if (millis() < httpTimer) {
      ether.httpServerReply(sendErr());  // send web page data
      dataString = "";
    } else {
      timer = millis() + 1000;
      ether.httpServerReply(sendOk());  // send web page data
    }
    httpTimer = millis() + 3000;
    //memset((char *)Ethernet::buffer, 0, sizeof((char *)Ethernet::buffer));
    //data = NULL;
  }

  if (dataString.startsWith("https://") && millis() > timer) {
    timer = millis() + 300000;
    showCode(dataString);
    dataString = "";
  } else if (!isWelcomeScreen && millis() > timer) {
    welcome();
    dataString = "";
  }


  if (Serial.available() > 0) {
    String stringVariable = Serial.readString();
    if (stringVariable.startsWith("set_default")) {
      loadDefaults(cfg);
      Serial.println(F("settings reset"));
    } else if (stringVariable.startsWith("set_ip")) {
      Serial.println(F("Setings reset"));
      stringVariable.replace("set_ip", "");
      stringVariable.trim();
      if (stringVariable != "") {
        Serial.print(F("Set IP: "));
        Serial.println(stringVariable);
        char charBuf[50];
        stringVariable.toCharArray(charBuf, 50);
        ether.parseIp(ether.myip, charBuf);
        memcpy(cfg.myip, ether.myip, 4);
        saveSettings(cfg);
      }
    }
  }
}

С такой работой с памятью - ни разу не удивительно. Посчитайте сколько памяти Вы одномоментно пытаетесь использовать и сравните с тем, сколько у Вас всего.

3 лайка
Скетч использует 26596 байт (82%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1819 байт (88%) динамической памяти, оставляя 229 байт для локальных переменных. Максимум: 2048 байт.

При таком раскладе могут быть такие ошибки?
Спасибо.

с этими стрингами вечная проблема (у мужчин)
смотрим тут код SPI Slave

Sample Code for ATtiny85 as SPI slave device:

#include<avr/io.h>
String received[200];
Скетч использует 1574 байт (19%) памяти устройства. Всего доступно 8192 байт.
Глобальные переменные используют 1221 байт (238%) динамической памяти, оставляя -709 байт для локальных переменных. Максимум: 512 байт.

2 лайка

Вы считать умеете? Вам компилятор сказал, что у Вас осталось свободно 229 байтов. Вы пытаетесь создать String на 512 (в строке №239). Когда свободно 229, а создать пытаетесь на 512 – Вам точно хватит? Или может не хватить?

5 лайков

Arduino UNO. Неоднократно проверено, что более, чем при 75% появляется красное сообщение о том, что программа может работать некорректно. А может и работать. Проверено.

Проверено?

я выше уже высказывался, но повторю прямо кодом, компилятор конечно умён но по сравнению с писавшими на ассемблере - дурак дураком!

#include <avr\io.h>

//String received[1000];
uint8_t received[1000];

void setup() {
  DDRB = (1 << PB1);          //Setting direction of PB1
  USICR = (1 << USIWM0);      //Choosing SPI aka three wire mode
}

void loop() {
  uint8_t i = 0;
  while (1)
  {
    if ((USISR & (1 << USIOIF)) == 1)    //Checking USI data counter overflow flag to detect the end of transmission every byte
    {
      received[i] = USIBR; //Reading received byte from USIBR buffer register
      if (i < 1000) 
        i = i + 9;
     else 
        i = 0;
        USISR |= (1 << USIOIF); //Clearing counter overflow flag
      }
    }
  }
Скетч использует 258 байт (3%) памяти устройства. Всего доступно 8192 байт.
Глобальные переменные используют 9 байт (1%) динамической памяти, оставляя 503 байт для локальных переменных. Максимум: 512 байт.

Тот, кто не использует результаты вычислений.

я другое имел ввиду, ну да ладно…

static uint8_t received[1000];

Смотрю на строки №№ 12 и 18, и ведь действительно!

А компилятор-то в чём дурак? В том, что он проанализировал Вашу программу и выбросил из неё всё ненужное и никогда не используемое (включая массив received)? Так его за это хвалят обычно.

так код не мой, это так учат, ссылка выше…
Ведают что творят но стигут с этого купоны ? (С) В.Высоцкий

Никак не пойму, почему он не используется? Вроде до 255 байт должен…
P…S.)))))

Т.е. вообще всю программу)))

Посмотрите внимательно на строку №15.

(я про код из №9, если что)

Ну, “дурак дураком” может и учить кого-то, кто ж ему запретит?

Еще раз внимательно посмотри на строчки, на которые тебе ЕП указал.
это не “учат”, это ты полный бред написал.

Тебе много раз советовали не выступать по программным вопросам, ты бы прислушался

Извините, я может позже разберусь. Пока для меня стр. 15 -
это проверка флага окончания передачи байта. Вроде всё норм. Только индекс массива uint8_t, не хватит до 1000, да и принятые данные нигде не используются дальше

а этого мало? :slight_smile:
Это делает бессмысленными все рассуждения @ua6em на тему размера кода

Так , а может я хочу отладить кусок кода, посмотреть регистры в Протеусе? Если так подходить - вся программа лишняя))