Arduino Nano+SD+LCD+RTC
- Войдите на сайт для отправки комментариев
Задача.
Снимать данные с четырех датчиков - два аналога, два DS18B20, небольшая математика, вывести значения на экран, при наличии SD карты записать датчики и результат математики на карту памяти.
Алгоритм
1. Если нет карты памяти, то только вывод на экран, математика по условию 1.
2. Если карта памяти есть, то на ней ищется файл для условия математики.
2.1 Если файла условия нет - создается имя для файла, в который будут записываться данные - неизменные буквы и число. Число берется из двух ячеек памяти с прибавлением единицы и записью в эти же ячейки. Т.е. при страте каждый раз создается новый файл с уникальным номером по порядку. В этот файл записывается условие, по которому работает математика. Далее математика по условию 1, вывод на экран, запись в файл данных.
2.2 Если карта памяти есть, есть файл условия, но в нем ничего нет - то аналогично 2.1
2.3 Если карта памяти есть, есть файл условия, в нем написано условие 1 - то 2.1
2.4. Если карта памяти есть, есть файл условия,в нем условие 2 - то 2.1 с математикой по условию 2.
Как бы алгоритм понятен, надеюсь.
Железо
Nano. LCD20x4 подключен по I2C к выводам А4 и А5. Датчики DS квыводам D9 и D8 по 1-Wire. Аналоговые к А0 и А1, опорное напряжение внутреннее. SD карта через SPI. выводы D10, D11, D12, D13.
Все это замечательно работает, до тех пор пока я не подключил модуль DS1307, так же к выводам А4 и А5. Мне нужно знать время снятия данных.
И вот тут начинается глюк. Библиотека <iarduino_RTC.h>
Если в коде присутствуют сточки iarduino_RTC time(RTC_DS1307) и time.begin() то все работает хорошо, данные пишутся на карту. Едва я пытаюсь отправить время в серийный порт Serial.println(time.gettime("d-m-Y H:i:s")) или на экран lcd.print(time.gettime("d-m-Y H:i:s")) Данные на карту перестают записываться.
Описания переменных, подключенные библиотеки и вычисления я оставил за кадром.
Код
iarduino_RTC time(RTC_DS1307); void setup(){ Serial.begin(9600); time.begin(); pinMode(2, OUTPUT); // для светодиода digitalWrite(2, LOW); // гасим его lcd.init(); lcd.backlight(); // Включаем подсветку дисплея lcd.setCursor(1, 1); //lcd.print(time.gettime("d-m-Y H:i:s")); delay(3000); lcd.clear(); // Карта памяти if (!SD.begin(10)) { //наличие SD-карты, вывод SC (SS) карты на 10 цифровом lcd.setCursor(5, 0); lcd.print("No SD-card "); lcd.setCursor(8, 1); rec="134a"; lcd.print(rec); // по-умолчанию без карты работаем с 134-м lcd.setCursor(0, 3); lcd.print(ver); delay(4000); lcd.clear(); return; } else { SDK=1; // если карта есть byte lowByte = EEPROM.read(addr1); // считываем из памяти контроллера число byte highByte = EEPROM.read(addr1 + 1); // из двух ячеек unsigned short int nmfile=lowByte + (highByte << 8); // которое потом будет именем файла nmfile++; // прибавляем единицу EEPROM.write(addr1,low(nmfile)); // и записывем новое имя EEPROM.write(addr1+1,high(nmfile)); // в две ячейки z="psi" + String(nmfile) + ".txt"; // Создаем имя файла из psi, номера и .txt Freon = SD.open("freon.txt",FILE_READ); while (Freon.available() && (pos <= Freon.position())) { int i=(Freon.read()); //шерстим карту памяти по всем позициям F+=i; // все записываем в F pos++; delay (3); } Freon.close(); } if(F=="52485599"){ rec=407; rec+="c"; } if(F=="49515297"||F==""){ rec=134; rec+="a"; } ISP = SD.open(z, FILE_WRITE); // Откроем новый файл ISP.println(rec); // пишем название фреона в него ISP.close(); // закрываем файл lcd.setCursor(5, 0); lcd.print(" SD-card "); lcd.setCursor(8, 1); lcd.print(rec); lcd.setCursor(7, 2); lcd.print(z); lcd.setCursor(0, 3); lcd.print(ver); delay(4000); lcd.clear(); } void loop(){ //Serial.println(time.gettime("d-m-Y, H:i:s")); digitalWrite(2, HIGH); // зажгем светодиод на время записи ISP = SD.open(z, FILE_WRITE); //Откроем файл ISP.println(record); ISP.close(); // закрываем файл // delay(200); } digitalWrite(2, LOW); //гасим сетодиод }
т.е. данные собираются в переменную record и из нее пишутся фв файл на карточке.
Где может сидеть глюк?
При таком количестве "тяжелых" библиотек у вас, скорее всего, проблемы с памятью. Сколько остается памяти при компиляции скетча?
Первое, что нужно сделать - загнать все строковые константы во флеш, обернув их макросом F().
При таком количестве "тяжелых" библиотек у вас, скорее всего, проблемы с памятью. Сколько остается памяти при компиляции скетча?
Без RTC 76% память и 69% глобальные переменные. Если добавить часы и вывод на экран времени - то память съедается на 85%. Не, я могу для эксперимента убрать вычисления и посмотреть - в этом проблема или нет
Первое, что нужно сделать - загнать все строковые константы во флеш, обернув их макросом F().
У меня строковая константа всего одна - я при старте вывожу на экран номер версии и ее дату. Это, конечно, баловство - но пока мне это нужно.
И еще пять строковых переменных.
Первое, что нужно сделать - загнать все строковые константы во флеш, обернув их макросом F().
У меня строковая константа всего одна - я при старте вывожу на экран номер версии и ее дату. Это, конечно, баловство - но пока мне это нужно.
И еще пять строковых переменных.
"52485599" - это не переменная, это строковая КОНСТАНТА. Если вы этого не понимаете - ваша проблема, но обернуть всё в F() - нужно.
Если бы я все понимал - я бы сюда не пришел.
По делу. Убрал часть кода, освободив память. Компилятор не ругается. Но данные так и не пишутся на карту.
Предположив, что 1307 и экран пересекаются по I2C, переподключил LCD на цифроые выходы, с соответствующей библиотекой. Такая же ерунда. При выводе времени на экран данные на карту не пишутся. Как это может быть связано... Надо будет пробовать другие библиотеки для 1307.
Повторю то, что уже было сказано другими: вероятнее всего, у Вас проблемы с памятью.
Причем, с памятью оперативной, а не программной, чего Вы, судя по всему не понимаете.
Когда приводите цифры, приводите их для оперативной, а не программной памяти. И для начала избавьтесь от всех переменных типа String - пусть даже в ущерб алгоритму (например, не вычислять новое имя файла, а писать в один и тот же файл.)
А как мне увидеть сколько в ОЗУ занято? От строковых я временно могу избавиться, а вот насовсем - врядли. Вывод значений на экран без них не обходится, но это другая тема.
А как мне увидеть сколько в ОЗУ занято? От строковых я временно могу избавиться, а вот насовсем - врядли. Вывод значений на экран без них не обходится, но это другая тема.
1. При компиляции скетча для AVR пишется в конце выдачи компилятора. Но это только глобальные переменные.
2. Чтобы посмотреть в процессе выполнения, ЕвгенийП писал, какжется, в теме "Этюды для начинающих".
Помни, что один буфер SD отжирает 512 байт, это 25% всей памяти Дуни. Да сериал - 128. И скоко там от 2 килобайт останется? Куды чо пхать-то?
Ну в общем все получилось. Удалось сократить количество стороковых переменных, некоторые переменные удалось использовать два раза по ходу программы и просто оптимизирровать код - все это подействовало. При компиляции на недостаоток памяти не ругается, данные на карту пишет... Но запаса нет. Если придется что-то добавлять - придется переползать на следующую платформу.