Оптимизация работы с картами SD

yarus
Offline
Зарегистрирован: 17.06.2017

Помогите, пожалуйста, оптимизировать работу с либой SD (максимально ее уменьшить, а то жрет много): в частности мне не нужны функции записи, стирания и работы с каталогами...

Как бы ее почистить от этого, либо вставить в код только те функции, которые требуются? (я не силен в С++).

sadman41
Offline
Зарегистрирован: 19.10.2016

Компилятор и так выкидывает функции, которые остались невостребованны при написании исхрдного текста.

yarus
Offline
Зарегистрирован: 17.06.2017

Тогда переиначу вопрос:

можно ли програмно отключить (до перезагрузки) всё это с целью экономии RAM после чтения инфы с карты?

sadman41
Offline
Зарегистрирован: 19.10.2016

Отключить что? На недостаток какого ресурса жалуетесь?

Всё, понял. Надо в либе посмотреть деструктор - если он имеется и возвращает память, то вызывать его.

yarus
Offline
Зарегистрирован: 17.06.2017

вот это-то, наверное, мне и надо... Вот только в какой либе он есть и как им пользоваться? (я уже писал, что в с++ не силен)... :(

Конкретно, у меня с карты читается строковая переменная. Вот, после ее прочтения и присвоения ее значения имеющейся переменной, всё предыдущее надо бы очищать  и отключать SD.

sadman41
Offline
Зарегистрирован: 19.10.2016

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

yarus
Offline
Зарегистрирован: 17.06.2017

Я пробовал SD и SDFAT

sadman41
Offline
Зарегистрирован: 19.10.2016

В отсутствии ссылки на библиотеку - это просто набор букв.

yarus
Offline
Зарегистрирован: 17.06.2017

сейчас поищу, хотя обе с гитхаба...

Вот ссылка на SD.h: https://github.com/arduino-libraries/SD

А вот на sdfat.h: https://github.com/greiman/SdFat

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Сходу не вижу никаких перспектив.

yarus
Offline
Зарегистрирован: 17.06.2017

очень жаль... А есть какие-нибудь иные либы, где это есть?

sadman41
Offline
Зарегистрирован: 19.10.2016

Я не в курсе, подождем ещё кого-нить.

Может вам стоит прооптимизировать другие места?

yarus
Offline
Зарегистрирован: 17.06.2017

Везде, где смог, пооптимизировал, даже кое-где вставил строчки голого С++ вместо ардуино-команд...

Всё равно маловато RAM...

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Не думаю, что вы освободите достаточно памяти, но...
Есть процедура SD.end().
Дальше из .cpp выпиливаете строчку с объявлением этой самой SD. Ищите в конце. Объявляейте этот обьект у себя в коде используя new например.Или локально в какой-то подпрограмме.

yarus
Offline
Зарегистрирован: 17.06.2017

Нельзя ли подсказать как? У меня всё чтение происходит с процедуре SETUP, а дальше работа с картой мне уже не нужна, можно, даже её полностью отключить после присвоения переменной значения, прочитанного из файла.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ну дык где ваша процедура ?

 

yarus
Offline
Зарегистрирован: 17.06.2017
Вот весь код программы:

#include <CyberLib.h>
#include <SPI.h>
#include <SdFat.h>
SdFat SD;
//#include <SD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

#define PIN 2
Adafruit_NeoPixel strip = Adafruit_NeoPixel(150, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(15, 10, PIN,
  NEO_MATRIX_BOTTOM     + NEO_MATRIX_LEFT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
  NEO_GRB            + NEO_KHZ800);


int x    = matrix.width();
File myFile;
String dd;

void setup() {
DDRB = DDRB | B00000100;
//pinMode(10,OUTPUT);
  matrix.cp437(true);
  strip.begin();
  matrix.begin();
  matrix.setTextWrap(false);
  matrix.setBrightness(200);
  matrix.setTextColor(matrix.Color(245,0,0));
  if (!SD.begin(4)) {
    //Serial.println("initialization failed!");
    return;
  }

  // open the file for reading:
  myFile = SD.open("text.txt");
  if (myFile) {
 //myFile.seek(0);
dd=readLine();
dd=dd.substring(4, dd.length());

    myFile.close();
  } else {
    // if the file didn't open, print an error:
  }}


void loop() {

Start
  colorWipe(strip.Color(255, 0, 0), 100); 
   showText(dd,matrix.Color(245,0,0), 100, 255);
 snake ( 200);
  stars(100, 30);
//  FullRainbow(60);
  rainbow(60); 
//  showText(dd,matrix.Color(0,255,0), 60, 100);
 theaterChase(strip.Color(255, 255, 255), 30);
 // theaterChase(strip.Color(255, 255, 255), 30);
End  
}

// ----------- Заполнение цветом  --------------
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}
// ----------- Заполнение цветом  --------------

// ----------- Змейка --------------
void snake ( byte t)
{
  for (byte x=0; x<150; x++)
  {
    strip.setPixelColor(x,255,255,255);
    strip.setPixelColor(x-1,80,80,80);
    strip.setPixelColor(x-2,30,30,30);
    strip.setPixelColor(x-3,5,5,5);
    strip.setPixelColor(x-4,0,0,0);
    strip.show();
    delay_ms (t);
  }
}
// ----------- Змейка --------------

// -------- Бегущая строка -----------
void showText( String t, uint16_t color, byte wait, byte len){
  matrix.setTextColor(color);
  while (--x > (len*(-1)))
  {
    matrix.fillScreen(0);
    matrix.setCursor(x, 0);
    matrix.print(utf8rus(t));
    matrix.show();
    delay_ms(wait);
  } 
    x = matrix.width(); 
}
 // -------- Бегущая строка -----------
/*
// --------- FULLRAINBOW --------------- 
void FullRainbow(uint8_t wait) {
  uint16_t i, j;
  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(j & 255));
    }
    strip.show();
    delay(wait);
  }
}*/
// --------- FULLRAINBOW --------------- 

void rainbow(byte wait) {
  uint16_t i, j;

  for(j=0; j<255; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay_ms(wait);
  }
}
/*
void star(byte wait) {
  byte i, j;
  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay_ms(wait);
  }
}
*/
void stars (byte t, byte pause){
  byte x=0;
  byte y=0;
  while (t > 0){
    for ( byte i=0; i<strip.numPixels(); i++){
      y = random(0,2);
      if (y>0) 
      {
        strip.setPixelColor(i,255,255,255);
      }
      else 
      {
        strip.setPixelColor(i,0, 0, 0);
      }
    }
    strip.show();
    t--;
    delay_ms(pause); 
    
  }
  
}

// ----------- Сияющий эффект ---------------
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<50; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay_us(wait);

      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}
// ----------- Сияющий эффект ---------------


// ------------Отображение русского шрифта------------- 
String utf8rus(String source)
{
  byte i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }
          if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
          break;
        }
        case 0xD1: {
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB8; break; }
          if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
          break;
        }
      }
    }
    m[0] = n; target = target + String(m);
  }
return target;
}
// ------------Отображение русского шрифта------------- 


String readLine() {
   String received = "";
   char ch;
   while(myFile.available()){
    ch = myFile.read();
    if(ch == '\n') {
     return String(received);
    } else {
     received+=ch;
    }
   }
   return "";
}


// ------------ Генератор радуги ------------- 
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

 

b707
Онлайн
Зарегистрирован: 26.05.2017

В 10 раз проще не трахаться с оптимизацией чужой библиотеки, а просто перенести код на платку СТМ32. Размер чуть больше Нано. стоит даже дешевле - а памяти ровно в 10 раз больше.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

STM32 - Да, только тогда придется сменить шилд.

Лучше сразу выбрать ESPшку.

А пока В файле библиотеки SD.cpp находите строку 

SDClass SD;

Коментируете или удаляете ее.

void setup(){
   SDClass SD;
   SD.begin();
   // тут картой кручу верчу
   SD.end();
}

void loop(){
   // ТУТ объекта SD уже нет
   // все занимаемое им озу свободно
   // во флеше куски кода от ваших танцев в сетапе
   // так что делайте это только если вам мало озу
   //  в остальных случаях это не поможет
}
 
yarus
Offline
Зарегистрирован: 17.06.2017

Пробовал, но не могу найти адекватных библиотек типа неоматрикс и неопиксель для STM32...

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

yarus пишет:

Пробовал, но не могу найти адекватных библиотек типа неоматрикс и неопиксель для STM32...

А для ESP они есть :) И у ESP32 два ядра. Там сетевые функции работают на другом ядре и ваше ресурсов не потребляют .

yarus
Offline
Зарегистрирован: 17.06.2017

Конечно,...

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

yarus пишет:

Конечно,...

Чего конечно. Реально. Причем сетевые библиотеки для ESP32 полностью совместимы со стандартными ардуиновскими. Если для 8826 была полная голиматья, то тут все красиво. Все стандартные примеры работают легко.

yarus
Offline
Зарегистрирован: 17.06.2017

Вот, когда получу ещё несколько ESP-шек, тогда и сделаю на них... а пока она у меня в единственном числе...

yarus
Offline
Зарегистрирован: 17.06.2017

после из

Выдает вот такую ошибку:

 exit status 1

'class SDLib::SDClass' has no member named 'end'
 
yarus
Offline
Зарегистрирован: 17.06.2017

brokly пишет:

STM32 - Да, только тогда придется сменить шилд.

Лучше сразу выбрать ESPшку.

А пока В файле библиотеки SD.cpp находите строку 

SDClass SD;

Коментируете или удаляете ее.

void setup(){
   SDClass SD;
   SD.begin();
   // тут картой кручу верчу
   SD.end();
}

void loop(){
   // ТУТ объекта SD уже нет
   // все занимаемое им озу свободно
   // во флеше куски кода от ваших танцев в сетапе
   // так что делайте это только если вам мало озу
   //  в остальных случаях это не поможет
}
 

После выполнения этих изменений выпадает ошибка: exit status 1

'class SDLib::SDClass' has no member named 'end'
 
brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

ну значит в вашей библиотеки этого метода нет. Просто удалите 5 строчку

А вообще, что у вас за библиотека. 

В SD.h все есть.

public:
  // This needs to be called to set up the connection to the SD card
  // before other methods are used.
  boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN);
  boolean begin(uint32_t clock, uint8_t csPin);
  
  //call this when a card is removed. It will allow you to insert and initialise a new card.
  void end();

 

b707
Онлайн
Зарегистрирован: 26.05.2017

yarus пишет:

Пробовал, но не могу найти адекватных библиотек типа неоматрикс и неопиксель для STM32...

есть неадекватные

https://github.com/rogerclarkmelbourne/WS2812B_STM32_Libmaple

yarus
Offline
Зарегистрирован: 17.06.2017

b707 пишет:

yarus пишет:

Пробовал, но не могу найти адекватных библиотек типа неоматрикс и неопиксель для STM32...

есть неадекватные

https://github.com/rogerclarkmelbourne/WS2812B_STM32_Libmaple

Хорошо, с неопикселем (под STM32) разобрались, а где взять неоматрикс?

yarus
Offline
Зарегистрирован: 17.06.2017

brokly пишет:

ну значит в вашей библиотеки этого метода нет. Просто удалите 5 строчку

А вообще, что у вас за библиотека. 

В SD.h все есть.

public:
  // This needs to be called to set up the connection to the SD card
  // before other methods are used.
  boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN);
  boolean begin(uint32_t clock, uint8_t csPin);
  
  //call this when a card is removed. It will allow you to insert and initialise a new card.
  void end();

 

Библиотека та, на которую я давал ссылку... Метод там только объявлен, но никак не описан, потому и не работает...

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А ну да . Глубоко не вникал.

yarus
Offline
Зарегистрирован: 17.06.2017

В этом-то всё и дело... не пашет... :(

sadman41
Offline
Зарегистрирован: 19.10.2016

SD-то обязательна? Мошт попроще придумать, раз не выходит?

__Alexander
Offline
Зарегистрирован: 24.10.2012

yarus пишет:

В этом-то всё и дело... не пашет... :(

Если у вас на карточке этот файл единожды создан и не удаляется, а только меняется содержимое, то прочтите его на низком уровне, прочитав сектор. Вся работа уложиться в десяток строк работы с SPI. Созданный файл в системе фат не меняет своего адреса пока не будет удален.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Так любой может написать. Прям Америку открыл. Ты покажи как этот сектор найти, как прочитать. Как найти следующий. Пять строк говоришь. Ну-ну....

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

yarus пишет:

В этом-то всё и дело... не пашет... :(


Чего именно не пашет то ? У меня все ок.

__Alexander
Offline
Зарегистрирован: 24.10.2012

brokly пишет:
Так любой может написать. Прям Америку открыл. Ты покажи как этот сектор найти, как прочитать. Как найти следующий. Пять строк говоришь. Ну-ну....

Всмысле найти? Можно карточку всунуть в комп и увидеть программой, например winhex. Если такой возможности нет, то пишем в файл уникальные данные и их ищем начиная с нулевого сектора. Разве это сложно?


void mmc_read_block(unsigned char *cmd,unsigned char *Buffer,unsigned int Bytes)
{ 
if (mmc_write_command (cmd) != 0)
{
return;
}
while (SPIReadChar(0xFF) != 0xfe){};

for (unsigned int a=0;a<Bytes;a++)
{
*Buffer++ = SPIReadChar(0xFF);
}
//CRC-Byte auslesen
SPIReadChar(0xFF);
SPIReadChar(0xFF);
MMC_Disable();

return;
}

unsigned char mmc_read_sector (unsigned long addr,unsigned char *Buffer)
{ 
unsigned char cmd[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; 

addr = addr << 9; //addr = addr * 512

cmd[1] = ((addr & 0xFF000000) >>24 );
cmd[2] = ((addr & 0x00FF0000) >>16 );
cmd[3] = ((addr & 0x0000FF00) >>8 );

    mmc_read_block(cmd,Buffer,512);

return(0);
}

 

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

del

yarus
Offline
Зарегистрирован: 17.06.2017

попробуйте скомпилить прогу с командой SD.end()

у вас выскочит ошибка!

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

yarus пишет:

попробуйте скомпилить прогу с командой SD.end()

у вас выскочит ошибка!


Читайте внимательно. Выбросьте эту строку из своего скетча. Уже писал. Вы не читаете что ли? В таком случае вам советов больше не даю.

yarus
Offline
Зарегистрирован: 17.06.2017

sadman41 пишет:

SD-то обязательна? Мошт попроще придумать, раз не выходит?

 

В это-то и вся задумка: менять строку без пепрепрошиски устройства...

 

sadman41
Offline
Зарегистрирован: 19.10.2016

yarus пишет:

sadman41 пишет:

SD-то обязательна? Мошт попроще придумать, раз не выходит?

В это-то и вся задумка: менять строку без пепрепрошиски устройства...

Тогда надо сидеть, башку чесать. Самое простое, конечно, сменить МК. У микро про, к примеру, не 2Кб Озу, а 2.5Кб.

yarus
Offline
Зарегистрирован: 17.06.2017

sadman41 пишет:

yarus пишет:

sadman41 пишет:

SD-то обязательна? Мошт попроще придумать, раз не выходит?

В это-то и вся задумка: менять строку без пепрепрошиски устройства...

Тогда надо сидеть, башку чесать. Самое простое, конечно, сменить МК. У микро про, к примеру, не 2Кб Озу, а 2.5Кб.

К сожалению, прихлдится работать с тем, что есть в наличии...

 

sadman41
Offline
Зарегистрирован: 19.10.2016

К сожалению чудес не бывает. Или меняете МК или становитесь хорошим программистом. 

yarus
Offline
Зарегистрирован: 17.06.2017

придётся упирать на 2й вариант, хотя смена МК тоже в перспективе (например, STM32 или ESP8266)...

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

yarus пишет:

хотя смена МК тоже в перспективе (например, STM32 или ESP8266)...

Это не поможет. Не зная как работает карта на низком уровне, Вы все равно поставите левую библиотеку и у она у вас сожрет всю память. Хоть на стм, хоть на есп. Так что, вариант только второй.

yarus
Offline
Зарегистрирован: 17.06.2017

Тогда подскажите нормальную, не "левую" библиотеку (ксли таковая есть в природе)...

negavoid
Offline
Зарегистрирован: 09.07.2016

Да любая библиотека отожрёт 512 байт под буфер сектора, ибо так правильнее. Но __Alexander вам привел пример, как считывать сектора напрямую (и тоже с буфером :), но его легко переделать под побайтовое чтение и уже эти байты на лету обрабатывать.

byte data = SPIReadChar(0xFF);

 

yarus
Offline
Зарегистрирован: 17.06.2017

Ясно. Спасибо всем за помощь. Вопрос решился (вроде) при помощи перехода на ESP8266, да еще и с управлением по wifi.

Так, что, тему, наверное, можно закрывать... Большое спасибо всем откликнувшимся. :)

negavoid
Offline
Зарегистрирован: 09.07.2016

ESP8266 - весьма капризный процессор, а становиться хорошим программистом вы не хотите. Ждём вас в следующих темах "оптимизация работы с wemos(nodemcu) ..." :)

yarus
Offline
Зарегистрирован: 17.06.2017

Дело в том, что изучать новый язык мне уже поздновато, а так - с удовольствием !

А на esp8266 (NODEMCU) у меня уже несколько месяцев работают интернет-синхронизированные часы-погодная станция со счетчиком подписок 2х каналов ютуба...