Проблемы со скетчем

Haloween
Offline
Зарегистрирован: 07.11.2017

Есть скетч:

 

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
//#include <math.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(8,7,6,5,4);

#define DS1307_I2C_ADDRESS 0x68
byte tuch=0;
byte t[13]={};
byte tolshina[13]={6,9,12,14,15,17,18,19,20,21,24,27,30};

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.write(0);
   Wire.write(decToBcd(second));    
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));     
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}

void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{

  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f); 
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}

void setup()     
 { 
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();

   Serial.begin(9600);
  second = 00;
  minute = 52;
  hour = 23;
  dayOfWeek = 7;
  dayOfMonth = 5;
  month = 11;
  year = 17;
 //setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);

 byte i;
  if (!SD.begin(10)) {
    Serial.println(F("initialization failed!"));
    return;
  }
  Serial.println(F("initialization done."));

 for (i=0; i<=11; i++)
  {t[i]=0;}     
   display.begin();
//  display.cp437(true);       
 display.setContrast(55);display.clearDisplay();display.fillScreen(WHITE);  
                display.display();

                display.setTextSize(1);display.setCursor(0,0);display.print("W O R K");
 display.setTextSize(2);
     display.setCursor(0, 8);display.print(tolshina[0]);display.setCursor(27,8);display.print("x");
    display.display();
 //  Serial.begin(9600);

 }
 
 void loop()

{
  
 /*  if (micros() - LastTime > 280000)
  { // a = analogRead (A0);//BS=digitalRead(*/
      if(digitalRead(15)==LOW)//если кнопка нажата ...(перемещение по пунктам)
      {
  tuch++;
  if (tuch>=13){tuch=0;}
       display.setTextColor(WHITE,BLACK);
  display.setCursor(0,8); display.print("      ");display.display();
  display.setTextColor(BLACK,WHITE);
  display.setCursor(0,8); display.print("      ");display.display();
 display.setCursor(0,8);display.print(tolshina[tuch]);display.setCursor(27,8);display.print("x");
  display.setCursor(42,8);display.print(t[tuch]);display.display();
      }
    if(digitalRead(16)==LOW)//если кнопка нажата ... (счет)
      {
     display.setCursor(42,8);display.print("  ");display.display();
      t[tuch]++;
     display.setTextColor(WHITE,BLACK);
  display.setCursor(42,8); display.print("  ");display.display();
  display.setTextColor(BLACK,WHITE);
  display.setCursor(42,8); display.print("  ");display.display();
  display.display();display.setCursor(42,8);display.print(t[tuch]);display.display();
//     небольшая защита от "дребезга" контактов кнопки реализованна при помощи функции millis()
      }
        if(digitalRead(2)==LOW)//если кнопка нажата ... (итог)
        {display.clearDisplay();
      //  if ((micros()-TimOfUpd)>4000000)
      //   {

        } 

   if(digitalRead(14)==HIGH)//если кнопка нажата ...(конец смены)
     {
 savdat();
}
             
     delay(250);

  /*  LastTime = micros();  
 } */         

 }


 void savdat()
 {
  File fdat;  

 fdat = SD.open("DAT.CSV", FILE_WRITE);
  if (fdat) {
    digitalWrite(3,HIGH);
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
if (dayOfMonth < 10) {fdat.print("0");fdat.print(dayOfMonth, DEC);fdat.print("/");}
else {fdat.print(dayOfMonth, DEC);fdat.print("/");} 
if (month < 10) {fdat.print("0");fdat.print(month, DEC);fdat.print("/");}
else {fdat.print(month, DEC);fdat.print("/");}
if (year < 10) {fdat.print("0"); fdat.print(year, DEC);}
else {fdat.print(year, DEC);}
fdat.print ("   ");
if (hour < 10) {fdat.print("0");fdat.print(hour);fdat.print(":");}
else {fdat.print(hour);fdat.print(":");}  
if (minute < 10) {fdat.print("0");fdat.print(minute);fdat.print(":");}
else {fdat.print(minute);fdat.print(":");}

fdat.println ("");     
    fdat.println("---------------------------------------------");
    for(byte u=0;u<13;u++) // бежим по элементам

      {if (t[u]>0){fdat.print(tolshina[u]);
     fdat.print("x");fdat.print(t[u]);fdat.print(" ; "); } 

        }

    fdat.println(" ");fdat.println("--------------------------------------------");
    // close the file:
    fdat.close();
    Serial.println("done.");
            delay(1000);digitalWrite(3,LOW);
 } else {
    // if the file didn't open, print an error:
    Serial.println(F("error opening dat.csv"));
  }

  // re-open the file for reading:
  fdat = SD.open("dat.csv");
  if (fdat) {
    Serial.println(F("dat.csv:"));

    // read from the file until there's nothing else in it:
    while (fdat.available()) {
      Serial.write(fdat.read());
    }
    // close the file:
    fdat.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println(F("error opening dat.csv"));
  }return;}

Необходимо его оптимизировать, чтобы переменные меньше места занимали в памяти (да и сам скетч занимает много места) и заставить работать по-человечьи, а то при попытке записи на карту вылетает ошибка открытия файла (хотя файл был перед этим создан этим же скетчем).

Помогите, пожалуйста, а то все мозги уже сломал...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Haloween пишет:

Необходимо его оптимизировать, чтобы переменные меньше места занимали в памяти (да и сам скетч занимает много места) 

Сколько занимают сейчас и сколько надо?

Haloween пишет:

 заставить работать по-человечьи, а то при попытке записи на карту вылетает ошибка открытия файла (хотя файл был перед этим создан этим же скетчем).

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

 

Haloween
Offline
Зарегистрирован: 07.11.2017

Это устройство считает нажатия на кнопки и пишет результат в файл. Пересчет происходит при нажатии на кнопку"счет", а запись - по нажатию на кнопку "конец смены".

при  компиляции выходит вот что:

Скетч использует 18690 байт (60%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1764 байт (86%) динамической памяти, оставляя 284 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
 
Устройство имеет автономное питание (аккумулятор 18650), по-этому выбрана плата "PRO MINI".
b707
Онлайн
Зарегистрирован: 26.05.2017

Библиотеку дисплея надо менять - в этой предусмотрен буфер, который сжирает всю память, ищите без буфера или пишите сами.

Haloween
Offline
Зарегистрирован: 07.11.2017

Как их распознать-то? Я в С не знаток, а в названиях ничего не указано...

Может подскажете, где взять?

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

SD тоже немало жреть

DIYMan
Offline
Зарегистрирован: 23.11.2015

Сходу  по оптимизации - все строки во флеш загнать, либо макросом F, либо, что будет лучше - PROGMEM.

Haloween
Offline
Зарегистрирован: 07.11.2017

Какие именно строки? Те, где происходит вывод в серпорт и на экран?

 

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

в Serial - все, что длиннее 3-5-ти символов. Выиграяете, навскидку, порядка 100 байт оперативки.

 

DIYMan
Offline
Зарегистрирован: 23.11.2015

Haloween пишет:

Какие именно строки? Те, где происходит вывод в серпорт и на экран?

У вас  строки "DAT.CSV", "W O R K", "done.", "--------------------------------------------" не обрамлены F(), остальное, вроде, норм.

Haloween
Offline
Зарегистрирован: 07.11.2017

Какие именно строки (номера)? И как быть с ошибкой открытия файла?

DIYMan
Offline
Зарегистрирован: 23.11.2015

195, 187, 184, 176, 157, 97. Ещё можно 116 и 118. 

Haloween
Offline
Зарегистрирован: 07.11.2017

Спасибо, сделал. теперь результат вот какой:

Скетч использует 19540 байт (63%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1682 байт (82%) динамической памяти, оставляя 366 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
 
И осталась проблема ошибки открытия файла.
b707
Онлайн
Зарегистрирован: 26.05.2017

что-то мало выиграли, должны были байтов 100-150. Покажите, что получилось.

Ну и повторю - чтобы изменить ситуацию кардинально, скетч надо полностью переписывать. Библиотека Adafruit_PCD8544.h по умолчанию создает буфер размером примерно 500-600 байтов, пока вы от него не избавитесь - работать не будет. Ошибка открытия файла, скорее всего, тоже связана с недостатком памяти.

Haloween
Offline
Зарегистрирован: 07.11.2017

Получилос вот что:

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
//#include <math.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(8,7,6,5,4);

#define DS1307_I2C_ADDRESS 0x68
byte tuch=0;
byte t[13]={};
byte tolshina[13]={6,9,12,14,15,17,18,19,20,21,24,27,30};

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.write(0);
   Wire.write(decToBcd(second));    
   Wire.write(decToBcd(minute));
   Wire.write(decToBcd(hour));     
   Wire.write(decToBcd(dayOfWeek));
   Wire.write(decToBcd(dayOfMonth));
   Wire.write(decToBcd(month));
   Wire.write(decToBcd(year));
   Wire.endTransmission();
}

void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{

  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f); 
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}

void setup()     
 { 
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();

   Serial.begin(9600);
  second = 00;
  minute = 52;
  hour = 23;
  dayOfWeek = 7;
  dayOfMonth = 5;
  month = 11;
  year = 17;
 //setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);

 byte i;
  if (!SD.begin(10)) {
    Serial.println(F("initialization failed!"));
    return;
  }
  Serial.println(F("initialization done."));

 for (i=0; i<=11; i++)
  {t[i]=0;}     
   display.begin();
//  display.cp437(true);       
 display.setContrast(55);display.clearDisplay();display.fillScreen(WHITE);  
                display.display();

                display.setTextSize(1);display.setCursor(0,0);display.print(F("W O R K"));
 display.setTextSize(2);
     display.setCursor(0, 8);display.print(tolshina[0]);display.setCursor(27,8);display.print("x");
    display.display();
 //  Serial.begin(9600);

 }
 
 void loop()

{
  
 /*  if (micros() - LastTime > 280000)
  { // a = analogRead (A0);//BS=digitalRead(*/
      if(digitalRead(15)==LOW)//если кнопка нажата ...(перемещение по пунктам)
      {
  tuch++;
  if (tuch>=13){tuch=0;}
       display.setTextColor(WHITE,BLACK);
  display.setCursor(0,8); display.print(F("      "));display.display();
  display.setTextColor(BLACK,WHITE);
  display.setCursor(0,8); display.print(F("      "));display.display();
 display.setCursor(0,8);display.print(tolshina[tuch]);display.setCursor(27,8);display.print("x");
  display.setCursor(42,8);display.print(t[tuch]);display.display();
      }
    if(digitalRead(16)==LOW)//если кнопка нажата ... (счет)
      {
     display.setCursor(42,8);display.print("  ");display.display();
      t[tuch]++;
     display.setTextColor(WHITE,BLACK);
  display.setCursor(42,8); display.print("  ");display.display();
  display.setTextColor(BLACK,WHITE);
  display.setCursor(42,8); display.print("  ");display.display();
  display.display();display.setCursor(42,8);display.print(t[tuch]);display.display();
//     небольшая защита от "дребезга" контактов кнопки реализованна при помощи функции millis()
      }
        if(digitalRead(2)==LOW)//если кнопка нажата ... (итог)
        {display.clearDisplay();
      //  if ((micros()-TimOfUpd)>4000000)
      //   {

        } 

   if(digitalRead(14)==HIGH)//если кнопка нажата ...(конец смены)
     {
 savdat();
}
             
     delay(250);

  /*  LastTime = micros();  
 } */         

 }


 void savdat()
 {
  File fdat;  

 fdat = SD.open(F("DAT.CSV"), FILE_WRITE);
  if (fdat) {
    digitalWrite(3,HIGH);
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
if (dayOfMonth < 10) {fdat.print("0");fdat.print(dayOfMonth, DEC);fdat.print("/");}
else {fdat.print(dayOfMonth, DEC);fdat.print("/");} 
if (month < 10) {fdat.print("0");fdat.print(month, DEC);fdat.print("/");}
else {fdat.print(month, DEC);fdat.print("/");}
if (year < 10) {fdat.print("0"); fdat.print(year, DEC);}
else {fdat.print(year, DEC);}
fdat.print ("   ");
if (hour < 10) {fdat.print("0");fdat.print(hour);fdat.print(":");}
else {fdat.print(hour);fdat.print(":");}  
if (minute < 10) {fdat.print("0");fdat.print(minute);fdat.print(":");}
else {fdat.print(minute);fdat.print(":");}

fdat.println ("");     
    fdat.println(F("---------------------------------------------"));
    for(byte u=0;u<13;u++) // бежим по элементам

      {if (t[u]>0){fdat.print(tolshina[u]);
     fdat.print("x");fdat.print(t[u]);fdat.print(F(" ; ")); } 

        }

    fdat.println(" ");fdat.println(F("--------------------------------------------"));
    // close the file:
    fdat.close();
    Serial.println(F("done."));
            delay(1000);digitalWrite(3,LOW);
 } else {
    // if the file didn't open, print an error:
    Serial.println(F("error opening dat.csv"));
  }

  // re-open the file for reading:
  fdat = SD.open(F("dat.csv"));
  if (fdat) {
    Serial.println(F("dat.csv:"));

    // read from the file until there's nothing else in it:
    while (fdat.available()) {
      Serial.write(fdat.read());
    }
    // close the file:
    fdat.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println(F("error opening dat.csv"));
  }return;}

После компиляции сами видели, что вышло...

Как я уже говорпил, я не знаток С и переписать библиотеку вряд лои смогу.

Может подскажете, как избавиться от буфера?

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Я бы еще поэкспериментировал со vsnprintf_P(). Возможно это и не даст сильного выигрыша по RAM, но кашу в 163-173 ликвидирует.

Serial еще можно не инициализировать и 16  байт, как минимум, выиграть ))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Haloween пишет:

Может подскажете, как избавиться от буфера?

Библиотека, не использующая буфер - https://oscarliang.com/arduino-oled-display-library/

А вот здесь коллега описал как её надо подправить и запустить - http://arduino.ru/forum/apparatnye-voprosy/preodolenie-problem-s-ekranom-096-128x64-oled-lcd-i2c-ssd1306

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

sadman41 пишет:

Serial еще можно не инициализировать и 16  байт, как минимум, выиграть ))

У Serial 128 байт буфер по умолчанию, а у SD, кабы не 512 аш.  Могу ошибаться, надо читать

Haloween
Offline
Зарегистрирован: 07.11.2017

У меня и схема и корпус под экран 5110

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

опщем, на Мегу переходи. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Haloween пишет:
У меня и схема и корпус под экран 5110

Ну, так и надо было говорить. Зайдите в гугл с запросом "библиотека для 5110 без буфера" - там столько вывалится. Или просто почитайте его (5110) даташит, там собственно делать нечего и безо всякой библиотеки.

sadman41
Онлайн
Зарегистрирован: 19.10.2016

DetSimen пишет:

У Serial 128 байт буфер по умолчанию, а у SD, кабы не 512 аш.  Могу ошибаться, надо читать

Всё более запутанно в этом hardware serial:

#if !defined(SERIAL_TX_BUFFER_SIZE)
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_TX_BUFFER_SIZE 16
#else
#define SERIAL_TX_BUFFER_SIZE 64
#endif
#endif
#if !defined(SERIAL_RX_BUFFER_SIZE)
#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_RX_BUFFER_SIZE 16
#else
#define SERIAL_RX_BUFFER_SIZE 64
#endif
#endif

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

и чо там?  я вижу, если памяти больше 1 килобайта, 64 байта приемный буфер и 64 байта передающий. в сумме 128. 

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Всё правильно посчитал. Но я так понимаю, что  можно задефайнить буфер сайз и тогда Serial будет не 128 байт жрать, а поменее.  Ну, и если принимать ничего не надо, то можно RX вообще крепко порезать. На arduino.cc это обсуждалось.

Грязный хак, конечно, но если экономить на спичках надо...

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

я в таких случаях просто Serial не инициализирую и не использую. 

экранчик тем более есть, для вывода

NeProf
Offline
Зарегистрирован: 12.10.2017

добрый день форумчане. Решил не создавать новую тему , а задать вопрос в этой. В фрагменте кода (взят из скетча работы с модулем ov0706 (объектив) в связке с SD  и Ethernet) выдается ошибка. Как я не экспериментировал с библиотеками (вроде скачаны последние SD-master и SdFat-master), но ошибку устранить не могу. Натолкните, в чем здесь дело, пожалуйста

#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <SoftwareSerial.h>   

SdFat SD;
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

void setup()
{}
void loop()
{}

выдается ошибка:

NeProf
Offline
Зарегистрирован: 12.10.2017

 No such file or directory

#include <SdFatUtil.h>

                                ^

 
DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

а гугло-транлэйт чо говорит?

NeProf
Offline
Зарегистрирован: 12.10.2017

перелопатил весь гугл, но пока ответа не нашел. Видел подобный код и .... вроде работает, т.е. там другие проблемы. Возможно конфликт библиотек SD-SdFat- и еще чего то, не пойму ))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Но Вы же сами привели текст сообщения в посте №26! А на вопрос, заданный Вам в посте №27 Вы ответили (сами себе)?

NeProf пишет:
перелопатил весь гугл

Нафига лопатили? Переводчик искали, чтобы фразу "No such file or directory" перевести?

NeProf пишет:
но пока ответа не нашел.

Да, чего его искать - вот он!

Neprofi
Offline
Зарегистрирован: 31.12.2016

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, тогда я вообще не понимаю Ваших проблем. Вам прямо сказали, что нету такого файла, а Вы уже неделю не знаете что Вам делать? А какие у Вас идеи? Или и идей никаких?

Клапауций 112
Клапауций 112 аватар
Offline
Зарегистрирован: 01.03.2017

чей туфля?