Помогите оптимизировать код. Логирование данных

paradox3007
Offline
Зарегистрирован: 27.02.2018

Доброго времени суток.

Помогите оптимизировать скетч, до добавления функции записи на SD все работает. 

Я новичок, собирал скетч из разных источников, сам в программировании не очень. Надо что бы в файл записывалась дата, время и показания с трех датчиков.

Так все работает:

#include <Wire.h>
#include <DS1307.h>                              				// Подключаем библиотеку для работы с модулем DS3231
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 											// номер пина к которому подключен DS18B20
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DS1307 rtc(SDA, SCL);											//часовой модуль подключен к пинам Arduino: Vcc к +5V, GND к 3емле, SDA к A3, SCL к A2
char buffer[25];
char buffer1[25];
#include <OLED_I2C.h>
OLED  myOLED(A2, A3, 8); 										// Подключение дисплея, 4pin - SDA , 5pin - SCL
extern uint8_t SmallFont[]; 									// Базовый шрифт без поддержки русскийх символов.
int x = 0;
void setup()
{
  sensors.begin(); 
  myOLED.begin();
  rtc.halt(false);
}
void loop(){
// Выводим на экран показания температуры
sensors.requestTemperatures();
myOLED.clrScr(); 												// очищаем экран
myOLED.setFont(SmallFont);
myOLED.print("TEMPERATURA", CENTER, 55); 						// вывод текста 
myOLED.setFont(SmallFont);
myOLED.print(String(sensors.getTempCByIndex(0) , 1), 15, 20);   // Отображение значения температуры, с точностью до десятых
myOLED.print(String(sensors.getTempCByIndex(1) , 1), 55, 20);   // Отображение значения температуры, с точностью до десятых
myOLED.print(String(sensors.getTempCByIndex(2) , 1), 95, 20);   // Отображение значения температуры, с точностью до десятых
myOLED.print("in", 20, 30);   									// Отображение значения температуры, с точностью до десятых
myOLED.print("out", 60, 30);   									// Отображение значения температуры, с точностью до десятых
myOLED.print("st", 100, 30);   									// Отображение значения температуры, с точностью до десятых
// Получение показаний с DS1307
String stringOne = rtc.getTimeStr();
myOLED.print(stringOne.substring(0,5), 98, 0);
myOLED.print(rtc.getDateStr(), 0, 0);
myOLED.update();
delay(2000); // Пауза 2 секунды
}

Добавил запись на SD и не хватка памяти и не понял как записать данные температуры:

#include <Wire.h>
#include <DS1307.h>                             // Подключаем библиотеку для работы с модулем DS3231
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SD.h>                                 // Подключаем библиотеку для работы с SD картой
#define chipSelect 10                           // Указываем пин подключения CS вывода модуля SD
#define ONE_WIRE_BUS 2 							// номер пина к которому подключен DS18B20
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DS1307 rtc(SDA, SCL);							//часовой модуль подключен к пинам Arduino: Vcc к +5V, GND к 3емле, SDA к A3, SCL к A2
#include <OLED_I2C.h>
OLED  myOLED(A2, A3, 8); 						// Подключение дисплея, 4pin - SDA , 5pin - SCL
extern uint8_t SmallFont[]; 					// Базовый шрифт без поддержки русскийх символов.
int x = 0;
void setup()
{
  SD.begin(chipSelect);                          // Инициализируем начало работы с SD-модулем, указывая пин подключения вывода CS
  sensors.begin(); 
  myOLED.begin();
  rtc.halt(false);
}
void loop(){
  File dataFile = SD.open("log.txt", FILE_WRITE);  // Открываем файл для записи логов
  if (dataFile) {                                  // Если удалось открыть файл
    dataFile.println(logString());                 //   Записываем строку логов в файл
    dataFile.close();                              //   Закрываем файл
  } else                                           // Если не удалось открыть файл
    myOLED.print("ErrorSD", CENTER, 40);           //   Выводим сообщение об ошибке
 delay(9500);                                      // Задержка в 59 с половиной сек.
}
String logString() {                               // Функция для генерации логов
// Выводим на экран показания температуры
sensors.requestTemperatures();
myOLED.clrScr(); 									// очищаем экран
myOLED.print("TEMPERATURA", CENTER, 55); 			// вывод текста 
//myOLED.setFont(SmallFont);
myOLED.print(String(sensors.getTempCByIndex(0) , 1), 15, 20);   // Отображение значения температуры, с точностью до десятых
myOLED.print(String(sensors.getTempCByIndex(1) , 1), 55, 20);   // Отображение значения температуры, с точностью до десятых
myOLED.print(String(sensors.getTempCByIndex(2) , 1), 95, 20);   // Отображение значения температуры, с точностью до десятых
myOLED.print("in", 20, 30);   // Отображение значения температуры, с точностью до десятых
myOLED.print("out", 60, 30);   // Отображение значения температуры, с точностью до десятых
myOLED.print("st", 100, 30);   // Отображение значения температуры, с точностью до десятых

// Получение показаний с DS1307
String stringOne = rtc.getTimeStr();
myOLED.print(stringOne.substring(0,5), 98, 0);
myOLED.print(rtc.getDateStr(), 0, 0);
myOLED.update();
//
String dataString = rtc.getTimeStr(); // Помещаем дату и температуру в новую строку логов

delay(2000); // Пауза 2 секунды
}

 

paradox3007
Offline
Зарегистрирован: 27.02.2018

Вот еще один код, тут все работает, но не подключен экран. 

#include <SD.h>                                  // Подключаем библиотеку для работы с SD картой
#include <DS3231.h>                              // Подключаем библиотеку для работы с модулем DS3231
#include <OneWire.h>                             // Подключаем библиотеку для взаимодействия с устройствами, работающими на шине и по протоколу 1-Wire
#include <DallasTemperature.h>                   // Подключаем библиотеку с функциями для работы с DS18B20 (запросы, считывание и преобразование возвращаемых данных)

#define chipSelect 10                             // Указываем пин подключения CS вывода модуля SD
#define oneWireBus 2                             // Указываем пин подключения data-вывода датчика DS18B20
//#define term_power 5                             // Указываем пин подключения питания датчика DS18B20

void setup() {
  Serial.begin(9600);                            // Инициализируем вывод данных на монитор серийного порта
  SD.begin(chipSelect);                          // Инициализируем начало работы с SD-модулем, указывая пин подключения вывода CS
//  pinMode(term_power, OUTPUT);                   // Определяем пин подключения питания датчика температуры DS18B20
}

void loop() {
  File dataFile = SD.open("log.txt", FILE_WRITE);  // Открываем файл для записи логов
  if (dataFile) {                                  // Если удалось открыть файл
    dataFile.println(logString());                 //   Записываем строку логов в файл
    dataFile.close();                              //   Закрываем файл
  } else                                           // Если не удалось открыть файл
    Serial.println("Can't open file");             //   Выводим сообщение об ошибке
  delay(9500);                                      // Задержка в 59 с половиной сек.
}

String logString() {                             // Функция для генерации логов
// Получение показаний с DS18B20
  OneWire oneWire(oneWireBus);                   // Сообщаем библиотеке об устройстве, работающем по протоколу 1-Wire(DS18B20)
  DallasTemperature sensors(&oneWire);           // Связываем функции библиотеки DallasTemperature с DS18B20
  sensors.begin();                               // Запускаем библиотеку измерения температуры
//  digitalWrite(term_power, HIGH);                // Включаем питание датчика температуры DS18B20
  sensors.requestTemperatures();                 // Запрос на измерение температуры (1-й ошибочный)
  delay(500);                                    // Задержка перед поторным измерением
  sensors.requestTemperatures();                 // Запрос на измерение температуры (повторный)
  int t0 = round(float(sensors.getTempCByIndex(0)));   // Получаем значение температуры
  int t1 = round(float(sensors.getTempCByIndex(1)));   // Получаем значение температуры
  int t2 = round(float(sensors.getTempCByIndex(2)));   // Получаем значение температуры
//  digitalWrite(term_power, LOW);                 // Отключаем питание датчика температуры DS18B20
//
// Получение показаний с DS3231
  DS3231 clock;                                  // Связываем объект clock с библиотекой DS3231
  clock.begin();                                 // Инициализируем модуль RTC DS3231
  RTCDateTime DateTime;                          // Определяем переменную DateTime, как описанную структурой RTCDateTime (структура описана в библиотеке DS3231.h)
  DateTime = clock.getDateTime();                // Заполняем DateTime значениями, полученными при запросе текущего времени
//
  String dataString = leadNull(DateTime.day) + "." + leadNull(DateTime.month) + "." + String(DateTime.year) + " " + leadNull(DateTime.hour) + ":" + leadNull(DateTime.minute) + ":" + leadNull(DateTime.second) + "|" + String(round(clock.readTemperature())) + "|" + String(t0) + "|" + String(t1) + "|" + String(t2); // Помещаем дату и температуру в новую строку логов

  Serial.println(dataString);                    // Выводим строку логов на монитор серийного порта

  return(dataString);                            // Возвращаем полученные значения в место вызова функции 
}

String leadNull(int value) {                      // Функция добавления ведущего нуля
  if (value < 10)                                 //  Если значение меньше десяти
    return ("0" + String(value));                 //  Добавляем ноль в начало значения и возвращаем его
  else                                            // Иначе
    return String(value);                         //  Возвращяем значение, предварительно преобразовав его в строковый формат
}

 

ven-til
Offline
Зарегистрирован: 13.02.2018

Много памяти не хватает?

paradox3007
Offline
Зарегистрирован: 27.02.2018

Примерно так

Скетч использует 20530 байт (63%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 2124 байт (103%) динамической памяти, оставляя -76 байт для локальных переменных. Максимум: 2048 байт.
ven-til
Offline
Зарегистрирован: 13.02.2018

А первый и третий скетчи сколько занимают?

paradox3007
Offline
Зарегистрирован: 27.02.2018

Первый

Скетч использует 12238 байт (37%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1278 байт (62%) динамической памяти, оставляя 770 байт для локальных переменных. Максимум: 2048 байт.

Третий

Скетч использует 18468 байт (57%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 1109 байт (54%) динамической памяти, оставляя 939 байт для локальных переменных. Максимум: 2048 байт.

 

ven-til
Offline
Зарегистрирован: 13.02.2018

Ну судя по всему памяти должно хватить, надо просто второй скетч правильно написать. Функция logString не та, что в третьем скетче и вывод на дисплей из loop переехал в  logString зачем-то.

 

paradox3007
Offline
Зарегистрирован: 27.02.2018

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

Если можно, помогите к третьему варианту прикрутить дисплей с выводом примерно как в первом варианте. Простите если путано получается излагать мысли...

 

paradox3007
Offline
Зарегистрирован: 27.02.2018

ven-til пишет:

Функция logString не та, что в третьем скетче и вывод на дисплей из loop переехал в  logString зачем-то.

 

совершенно верно, пробовал разные варианты, пока ничего путного не выходит

ven-til
Offline
Зарегистрирован: 13.02.2018

Сперва  удалить из третьего строки 28-30

Из первого в третий копируем строки:

6-7 и 12-13 до setup

17-18 в setup

23-24 в начало loop

25-38 в loop перед delay

 

ven-til
Offline
Зарегистрирован: 13.02.2018

ещё строки из третьего 41 до setup

42-43 в setup

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

paradox3007, для вывода на экран Вы пользуетесь библиотекой, использующей экранный буфер. Сам буфер занимает 1к из имеющихся ы контроллере 2к. При этом, судя по фото, Вы выводите на экран только текст. Возьмите библиотеку без экранного буфера и все у Вас поместится.

paradox3007
Offline
Зарегистрирован: 27.02.2018

andriano пишет:

paradox3007, для вывода на экран Вы пользуетесь библиотекой, использующей экранный буфер. Сам буфер занимает 1к из имеющихся ы контроллере 2к. При этом, судя по фото, Вы выводите на экран только текст. Возьмите библиотеку без экранного буфера и все у Вас поместится.

я использую библиотеку OLED_I2C, какую библиотеку можно использовать?

ven-til
Offline
Зарегистрирован: 13.02.2018

paradox3007, допили сначала с этим, посмотри сколько получается.

paradox3007
Offline
Зарегистрирован: 27.02.2018

ven-til пишет:

paradox3007, допили сначала с этим, посмотри сколько получается.

точно так как сказал не получилось, посыпались ошибки, после устранения стало так:

Скетч использует 24350 байт (75%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 2219 байт (108%) динамической памяти, оставляя -171 байт для локальных переменных. Максимум: 2048 байт.
ven-til
Offline
Зарегистрирован: 13.02.2018

Ну вот тебе ссылка

Там есть про без буферные библиотеки.

 

paradox3007
Offline
Зарегистрирован: 27.02.2018

ven-til пишет:

Ну вот тебе ссылка

Там есть про без буферные библиотеки.

 

Спасибо. Насколько я понял только OzOled но не понял с синтаксисом 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

На всякий случай продублирую ссылку на свою библиотеку, хотя она и есть в указанной выше теме:

http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-...

paradox3007
Offline
Зарегистрирован: 27.02.2018

andriano пишет:

На всякий случай продублирую ссылку на свою библиотеку, хотя она и есть в указанной выше теме:

http://arduino.ru/forum/proekty/asoled-kompaktnaya-biblioteka-dlya-oled-displeya-128kh64-s-kirillitsei-utf-8

А не затруднит ли Вас помочь мне внедрить вашу библиотеку в скетч №3 что бы вывод был как на фото выше? 

я пока очень далет от этого, но пытаюсь разбираться на примерах

я когда нибудь обязательно научусь =)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

1. Пример использования библиотеки есть внутри.

2. Библиотека содержит очень ограниченный набор функций, так что запутаться сложно.

3. Назначение всех функций откомментировано.

 
paradox3007
Offline
Зарегистрирован: 27.02.2018

andriano пишет:

1. Пример использования библиотеки есть внутри.

2. Библиотека содержит очень ограниченный набор функций, так что запутаться сложно.

3. Назначение всех функций откомментировано.

 

подключил библиотеку, экран выводит тест командой 

LD.printString_12x16(F(" NORM TEST  "), 0, 0);

Поскажите, какой командой вывести показания с датчиков и дату/время. не смог найти, т.к. LD.printString_12x16 выводит только текст...

ven-til
Offline
Зарегистрирован: 13.02.2018

А LD.printNumber((long)n0, 0, 0); ?

Example к библиотеке можно посмотреть.

paradox3007
Offline
Зарегистрирован: 27.02.2018

andriano пишет:

1. Пример использования библиотеки есть внутри.

2. Библиотека содержит очень ограниченный набор функций, так что запутаться сложно.

3. Назначение всех функций откомментировано.

 

Доброй ночи.

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

Не могу понять как реализовать это. с выводом температуры с датчиков разобрался

ven-til
Offline
Зарегистрирован: 13.02.2018

Стопор на каком месте происходит, что именно не получается?

paradox3007
Offline
Зарегистрирован: 27.02.2018

получается фигня какая то.

LD.printString_6x8("", 0, 0);
LD.printNumber((long)DateTime.day, 0, 0, 0);
LD.printString_6x8(".", 15, 0);
LD.printNumber((long)DateTime.month, 0, 30, 0);
LD.printString_6x8(".", 40, 0);
LD.printNumber((long)DateTime.year, 0, 45, 0);

но должен же быть способ проще, что бы сразу вставлялась дата целиком и время

ven-til
Offline
Зарегистрирован: 13.02.2018

Как начсет фотки того, что пишется на экране и, что выводится в serial?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

paradox3007 пишет:

получается фигня какая то.

LD.printString_6x8("", 0, 0);
LD.printNumber((long)DateTime.day, 0, 0, 0);
LD.printString_6x8(".", 15, 0);
LD.printNumber((long)DateTime.month, 0, 30, 0);
LD.printString_6x8(".", 40, 0);
LD.printNumber((long)DateTime.year, 0, 45, 0);

но должен же быть способ проще, что бы сразу вставлялась дата целиком и время

Кто кому должен?

Лично я не помню, чтобы кому-то задолжал.

Библиотека должна уметь выводить С-строку. Все остальное - факультатив.

Вам нужно - Вы и пишите.

kalapanga
Offline
Зарегистрирован: 23.10.2016

paradox3007 пишет:

получается фигня какая то.

LD.printString_6x8("", 0, 0);
LD.printNumber((long)DateTime.day, 0, 0, 0);
LD.printString_6x8(".", 15, 0);
LD.printNumber((long)DateTime.month, 0, 30, 0);
LD.printString_6x8(".", 40, 0);
LD.printNumber((long)DateTime.year, 0, 45, 0);

но должен же быть способ проще, что бы сразу вставлялась дата целиком и время

Не знаю, чем Вас не устраивает такой способ вывода, но если Вы хотите "проще" (в кавычках потому, что внутри всё то же самое будет) и самому ничего не писать, возьмите библиотеку для часов, которая сразу возвращает дату строкой. Такие есть.

lean_74
Offline
Зарегистрирован: 22.12.2015

№54 Убавить один датчик я думаю сам дагодаешься.

paradox3007
Offline
Зарегистрирован: 27.02.2018

andriano пишет:

paradox3007 пишет:

получается фигня какая то.

LD.printString_6x8("", 0, 0);
LD.printNumber((long)DateTime.day, 0, 0, 0);
LD.printString_6x8(".", 15, 0);
LD.printNumber((long)DateTime.month, 0, 30, 0);
LD.printString_6x8(".", 40, 0);
LD.printNumber((long)DateTime.year, 0, 45, 0);

но должен же быть способ проще, что бы сразу вставлялась дата целиком и время

Кто кому должен?

Лично я не помню, чтобы кому-то задолжал.

Библиотека должна уметь выводить С-строку. Все остальное - факультатив.

Вам нужно - Вы и пишите.

Добрый день. Видимо Вы что то не так поняли, к Вам у меня только благодарность за библиотеку!

paradox3007
Offline
Зарегистрирован: 27.02.2018

kalapanga пишет:

paradox3007 пишет:

получается фигня какая то.

LD.printString_6x8("", 0, 0);
LD.printNumber((long)DateTime.day, 0, 0, 0);
LD.printString_6x8(".", 15, 0);
LD.printNumber((long)DateTime.month, 0, 30, 0);
LD.printString_6x8(".", 40, 0);
LD.printNumber((long)DateTime.year, 0, 45, 0);

но должен же быть способ проще, что бы сразу вставлялась дата целиком и время

Не знаю, чем Вас не устраивает такой способ вывода, но если Вы хотите "проще" (в кавычках потому, что внутри всё то же самое будет) и самому ничего не писать, возьмите библиотеку для часов, которая сразу возвращает дату строкой. Такие есть.

в первом скетче что размещен в этой теме есть вот такие строчки:

// Получение показаний с DS1307
String stringOne = rtc.getTimeStr();
3myOLED.print(stringOne.substring(0,5), 98, 0);
myOLED.print(rtc.getDateStr(), 0, 0);
myOLED.update();
delay(2000); // Пауза 2 секунды

Это выводит дату и время на экран так как показанно на фотов 7 посте.

Сейчас это не работает =(

но это не такая большая проблема. 

Всем спасибо за отклик.

paradox3007
Offline
Зарегистрирован: 27.02.2018

ven-til пишет:

Как начсет фотки того, что пишется на экране и, что выводится в serial?

вывод на экран

вывод в сериал порт и запись на флешку

paradox3007
Offline
Зарегистрирован: 27.02.2018

Есть правда еще вопрос, может кто подскажет.

в одном скетче вывод температуры выводится до десятых 

myOLED.print(String(sensors.getTempCByIndex(0) , 1), 15, 20);   // Отображение значения температуры, с точностью до десятых

в другом до целых

 int t0 = round(float(sensors.getTempCByIndex(0)));   // Получаем значение температуры

предполагаю что за это отвечает единица после sensors.getTempCByIndex(0) но после дабавления ее выводятся только единицы вместо температуры

вопрос, как сделать что бы температура выводилась до десятых а лучше до сотых в данном коде:

 sensors.requestTemperatures();                 // Запрос на измерение температуры (повторный)
  int t0 = round(float(sensors.getTempCByIndex(0)));   // Получаем значение температуры
  int t1 = round(float(sensors.getTempCByIndex(1)));   // Получаем значение температуры
  int t2 = round(float(sensors.getTempCByIndex(2)));   // Получаем значение температуры

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

paradox3007, у Вас round() округляет до целых. После этого десятым уже взятья неоткуда.

А выводить сотые - бессмысленно, т.к. для этого нужны датчики из совершенно другого ценового диапазона.

paradox3007
Offline
Зарегистрирован: 27.02.2018

andriano пишет:

paradox3007, у Вас round() округляет до целых. После этого десятым уже взятья неоткуда.

А выводить сотые - бессмысленно, т.к. для этого нужны датчики из совершенно другого ценового диапазона.


Спасибо, буду пробовать исключать эту переменную из кода

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Пробуйте.

Только это не переменная а функция.