чего то делаю не так
- Войдите на сайт для отправки комментариев
Втр, 17/10/2017 - 13:16
Большая просьба помочь, не кидая камнями. Программированием не занимался никогда. Делаю счетчик для горячей и холодной воды. (ну еще семисегментный 8 рарядный индикатор показывает время и температуру)
Не работает функционал записи значений в память (для сохранения на случай пропадания питания).
Ниже код, все лишнее выбросил (про индикатор, время и температуру). Проблемный кусок про EEPROM откуда то списал не разобравшись как работает :-(
И да... счетчик Cold работает как требовалось.
#include <Bounce2.h> // библиотека обработки дребезга контактов
#include <avr/eeprom.h> // библиотека для работы с энергонезависимой памятью
int inputColdPin = 8; //назначаем вывод 8 для холодного счетчика
int inputHotPin = 7; //назначаем вывод 7 для горячего счетчика
unsigned long Cold;
unsigned long Hot;
Bounce bouncer = Bounce();
Bounce bouncer2 = Bounce();
void setup()
{
//если хотим присвоить начальные значения, активируем следующие 4 строки
//Cold=77419;
//Hot=69539;
//eeprom_write_block(&Cold, 0, 4);
//eeprom_write_block(&Hot, 5, 4);
//послезагрузки, вновь их деактивируем начальные значения будут сохранены
eeprom_read_block(&Cold, 0, 4);
eeprom_read_block(&Hot, 5, 4);
// назначенные выводы для подсчета импульсов и подключаем их (с нагрузочными резисторами) к библиотеке антидребезга
pinMode(inputColdPin, INPUT_PULLUP);
pinMode(inputHotPin, INPUT_PULLUP);
bouncer.attach(inputColdPin);
bouncer2.attach(inputHotPin);
bouncer.interval(10); // interval in ms
bouncer2.interval(10); // interval in ms
Serial.begin(9600); // инициализируем порт, скорость 9600
}
void loop()
{
if (bouncer.update() && bouncer.read() == LOW)
{
Cold=Cold+1;eeprom_write_block(&Cold, 0, 4); delay(5); //запись нового значения в память
}
if (bouncer2.update() && bouncer2.read() == LOW)
{
Hot=Hot+1;eeprom_write_block(&Hot, 5, 4); delay(5); //запись нового значения в память
}
Serial.print("Hot: "); Serial.print(Hot);Serial.print("\t");Serial.print("Cold: "); Serial.println(Cold);
}
А надо-то чо?
Добавлю: Считаю имульсы (1 на 10 литров), а на индикатор вывожу кубометры, а то разрядов не хватает.
Начальные, значения в коде - реальные, поэтому
unsignedlongВ приведенном коде, после закомментирования начальных значений, значение "Hot", после перезагрузки получается 1126318, а должно было быть 69539 С переменной "Cold" все в порядке
В коде проблем не вижу. должно работать. Попробуйте сохранять Cold в еепроме по другому адресу, например 10. Может у вас первые ячейки еепром "битые"
Попробуйте сохранять Cold в еепроме по другому адресу, например 10. Может у вас первые ячейки еепром "битые"
Это ненадолго с таким режимом записи.
2ТС: если бы вы свои Serial.print-ы воткнули сразу после считывания блока с eeprom, то всем было бы проще.
Ну Serial.print-ы воткнул в конце, что бы убедиться, счетчик считает и после сброса питания восстанавливаются именно насчитанные значения
А что с режимом записи не так? одна единичка счета на 10 литров это не особо много и часто. на 100 000 циклов это должно быть 1000 кубов (сейчас на счетчиках - 700 кубов)
Проблема не в "битых" ячейках - проверял на разных экземплярах Nano
Ну Serial.print-ы воткнул в конце, что бы убедиться, счетчик считает и после сброса питания восстанавливаются именно насчитанные значения
#include <avr/eeprom.h> // библиотека для работы с энергонезависимой памятью unsigned long Cold; unsigned long Hot; void setup() { Serial.begin(9600); // инициализируем порт, скорость 9600 //если хотим присвоить начальные значения, активируем следующие 4 строки /* Cold=77419; Hot=69539; eeprom_write_block(&Cold, 0, 4); eeprom_write_block(&Hot, 5, 4); */ //послезагрузки, вновь их деактивируем начальные значения будут сохранены eeprom_read_block(&Cold, 0, 4); eeprom_read_block(&Hot, 5, 4); Serial.print("Hot: "); Serial.print(Hot);Serial.print("\t");Serial.print("Cold: "); Serial.println(Cold); } void loop() { }Проверил
Все работает, то есть счетчики после перезагрузки питания начинают считать с того места где остановились.
НО! "Нот" - со своих непойми откуда взявшихся 1126318
Что тут посоветовать... пытайтесь локализовать проблемное место - например, втыкайте
Serial.print("Hot: ");Serial.print(Hot);туда, где у вас +1 делается.Hot: 69539 Cold: 77419
А начальные значения закоменнтировали?
Смысл был залить скетч с начальными значениями, а потом его же, но уже не давая начальных значений (брать их из EEPROM)
А начальные значения закоменнтировали?
Я даже вставил в сообщение то, что заливал, чтобы сомнений не возникло. Но это не помогло...
А что с режимом записи не так? одна единичка счета на 10 литров это не особо много и часто. на 100 000 циклов это должно быть 1000 кубов (сейчас на счетчиках - 700 кубов)
Проблема не в "битых" ячейках - проверял на разных экземплярах Nano
Вы уверены. что ваш код пишет в епром только изменяющиеся данные? Я бы на всякий случай писал функцией update(). И что 700 кубов - их этот код уже "натикал", а потом начал глючить? тогда точно битые ячейки.
Чтобы сохранить епром подольше, не пишите все время в одно место, пишите со смещением при каждой записи. Если надо - распишу алгоритм подробно. Можно продлить жизнь епром в десятки раз.
Нет этот код не натикал 700 кубов, я с Ардуиной живу последний месяц только и у меня не бассейн :-).
Запись в EEPROM стоит после изменения значения счетчика (то есть нет изменения - нет записи)
Запись со смещением - интересная мысль, но пока должно хватать того что есть.
Последовал совету b707 - перенес начальный адрес с 5 на 10: eeprom_write_block(&Hot, 10, 4);
Вроде получилось !!!
Вроде получилось !!!
тогда точно битые ячейки...
Может вы их при тестировании "поджарили"?
тогда точно битые ячейки...
Может вы их при тестировании "поджарили"?
Видимо
Был момент, когда чтобы кнопку не нажимать я счетчик в цикл поставил
А уже потом вычитал про 100 000 ограничение
А 100 000 - это на ячейку или на весь модуль?
Я сейчас снесу начальные адреса, это должно помочь?
А 100 000 - это на ячейку или на весь модуль?
Я сейчас снесу начальные адреса, это должно помочь?
на ячейку.
счетчик в цикле - это круто. Где-то читал. что при записи в цикле флеш убивается за 7 секунд, а епром за минуту.
Сдвиньте адреса записи куда-нибудь подальше, например за сотню адресов , должно помочь.
Где-то читал. что при записи в цикле флеш убивается за 7 секунд, а епром за минуту.
Сдвиньте адреса записи куда-нибудь подальше, например за сотню адресов , должно помочь.
Спасибо сдвину :-)
Я ж новичок. Всех познаний програмировании: иф, зен, гоу ту. Мне про это в институте рассказывали, лет 30 назад :-)
Ну вроде все заработало.
Вот только индикатор заметно мерцает на температуре и времени, в чем может быть дело?
Я выложу весь скетч скопом, не судите строго. Вернее судите, но не строго:
/* работающая программа Считает замыкания на землю по 2-м выводам (D7 и D8) Результат хранится в энергонезависимой памяти (на случай пропадания питания) Первоначальные значения можно внести с копьютера Запись новых значений производится при их изменении, дабы не вырабатывать циклы записи/чтения Вывод производится на 8 разрядный индикатор (на чипе MAX72XX), подключенный к выводам 10 (Load) 11(CLK) 12(DataIn) Имеются часы на базе чипа DS3231 модуль подключается к аппаратным выводам I2C Есть датчик температуры и влажности DHT11, подключенный к выводу D2 Данные счетчиков, времени и температуры выводятся последовательно с задержкой на 150 - 200 циклов программы (примерно по 4 секунды на Arduino Nano v3) */ #include <Bounce2.h> // библиотека обработки дребезга контактов #include "LedControl.h" //подключаем библиотеку работы с многоразрядным семимегментным индикатором #include <avr/eeprom.h> // библиотека для работы с энергонезависимой памятью #include <RTC.h> //подключаем библиотеку работы с часами реального времени RTC RTC time; #include <DHT_U.h> //подключаем библиотеку работы с датчиком температуры и влажности #define DHTPIN 2 // Датчик температуры подключен выводу 2 #define DHTTYPE DHT11 // указываем тип датчика, бывает еще DHT22 - более точный и с большим диапазоном включая отрицательные температуры DHT_Unified dht(DHTPIN, DHTTYPE); /* указываем к каким пинам контролера какие пины модуля подключаем. ***** These pin numbers will probably not work with your hardware ***** pin 12 is connected to the DataIn pin 11 is connected to the CLK pin 10 is connected to LOAD We have only a single MAX72XX. */ LedControl lc=LedControl(12,11,10,2); const int inputColdPin = 8; //назначаем вывод 8 для холодного счетчика const int inputHotPin = 7; //назначаем вывод 7 для горячего счетчика unsigned long Cold; unsigned long Hot; unsigned long printCold; unsigned long printHot; int NN=0; int Light = 0; int Temper; Bounce bouncer = Bounce(); Bounce bouncer2 = Bounce(); void setup() { //если хотим присвоить начальные значения, активируем следующие 4 строки //Cold=77419; //Hot=69539; //eeprom_write_block(&Cold, 20, 4); //eeprom_write_block(&Hot, 30, 4); //послезагрузки, вновь их деактивируем начальные значения будут сохранены eeprom_read_block(&Cold, 20, 4); eeprom_read_block(&Hot, 30, 4); time.begin(RTC_DS3231); //инициализация модуля RTC на базе чипа DS3231 dht.begin(); // инициализируем датчик температуры sensor_t sensor; dht.temperature().getSensor(&sensor); dht.humidity().getSensor(&sensor); lc.shutdown(0,false); //инициализируем индикатор lc.setIntensity(0,8); // устанавливаем значение яркости индикатора от 0 до 15 lc.clearDisplay(0); // очищаем дисплей // назначенные выводы для подсчета импульсов и подключаем их (с нагрузочными резисторами) к библиотеке антидребезга pinMode(inputColdPin, INPUT_PULLUP); pinMode(inputHotPin, INPUT_PULLUP); bouncer.attach(inputColdPin); bouncer2.attach(inputHotPin); bouncer.interval(10); // interval in ms bouncer2.interval(10); // interval in ms Serial.begin(9600); // инициализируем порт, скорость 9600 Serial.print("Hot: "); Serial.print(Hot); Serial.print(" Cold: "); Serial.println(Cold); } void loop() { if (bouncer.update() && bouncer.read() == LOW) { Cold=Cold+1; eeprom_write_block(&Cold, 20, 4); //запись нового значения в память Serial.print("Cold: "); Serial.println(Cold); } if (bouncer2.update() && bouncer2.read() == LOW) { Hot=Hot+1; eeprom_write_block(&Hot, 30, 4); //запись нового значения в память Serial.print("Hot: "); Serial.println(Hot); } //округляем выводимые значения printCold=okrugGl(Cold/10)*10; printHot=okrugGl(Hot/10)*10; Light=0; if ( NN==100) { sensors_event_t event; dht.temperature().getEvent(&event); Temper = event.temperature; } Filer( Temper, printCold , printHot ); } // функция округления с уменьшением разрядности int okrugGl(unsigned long x) { int Delta; unsigned long outPut; Delta=x%10; if (Delta>4) {outPut=x/10+1;} else {outPut=x/10;} return outPut; } // функция вывода на индикатор поразрядно с нулевого знакоместа // v- входное 4-х разрядное значение // n- номер начального знакоместа // l включать или нет подсветку для десятков и сотен // l2 - то же для тысяч void printNumber(int v,int n, int l, int l2) { int ones; int tens; int hundreds; int tausends; if(v > 9999) return; ones=v%10; v=v/10; tens=v%10; v=v/10; hundreds=v%10; v=v/10; tausends=v; /* Now print the number digit by digit первый аргумент отвечает за НЕотображение в указанном разряде "0" - отображать, "1" - не отображать последний аргумент в функции отвечает за отображение символа "точки" "1" - отображать, "0" - не отображать */ lc.setDigit(l2,(n+3),tausends,0); lc.setDigit(l,(n+2),hundreds,0); lc.setDigit(l,(n+1),tens,0); lc.setDigit(1,n,ones,0); //последнюю цифру не показываем } void Filer(int Temper, unsigned long printCold,unsigned long printHot ) { int l2=1; NN=NN+1; if (NN>=1 && NN<=200) //ПЕРВЫЕ 200 ЦИКЛОВ ПОКАЗЫВАЕМ СЧЕТЧИКИ { printNumber(printCold,0,Light,0); // 0 - данные по холодному счетчику сначала printNumber(printHot,4,Light,0); // 4 - данные по горячему счетчику потом lc.setChar(0,4,'-',false); // дефис между показаниями } else { lc.clearDisplay(0); if (NN>200 && NN<=350) //ВТОРЫЕ 150 ЦИКЛОВ ПОКАЗЫВАЕМ ТЕМПЕРАТУРУ { printNumber(Temper*10,3,0,l2); lc.setRow(0,3,B01100011); //знак градуса lc.setRow(0,2,B01001110); //буква "С" } else { lc.clearDisplay(0); if (NN>350&& NN<=500) //ТРЕТЬИ 150 ЦИКЛОВ ПОКАЗЫВАЕМ ВРЕМЯ { printNumber(time.minutes*10,1,0,l2); printNumber(time.Hours*10,4,0,l2); lc.setChar(0,4,'-',false); } else { lc.clearDisplay(0); NN=0; }}} }может быть в LedControl.h
проблема?
что за индикаторы кстати?
Индикатор такой:
MAX7219 LED Dot Matrix 8-Digit Digital Tube Display Control Module
https://ru.aliexpress.com/item/MAX7219-LED-Dot-Matrix-8-Digit-Digital-Tube-Display-Control-Module/32654195774.html?spm=a2g0v.10010108.1000016.1.41fcc028CGYQCk&isOrigTitle=true
По идее не должно быть делло в библиотеке. Температуру я отдаю ей так же как и значения счетчиков.
Так у Вас lc.clearDisplay(0) на каждом прогоне loop (вызове Filer) для температуры и времени. Зачем??
Чтобы сохранить епром подольше, не пишите все время в одно место, пишите со смещением при каждой записи. Если надо - распишу алгоритм подробно. Можно продлить жизнь епром в десятки раз.
интересно , распишите, как Вы это делаете.
Я делал испыталку на вкл/выкл, и каждый факт срабатывания надо было хранить. А тестов в одном запуске 40000 раз.
Потому храню в ячейке с аддр 0 номер запуска (int), а текущий адрес для записи результатов тестов каналов (4*unsigned int) в запуске вычисляю каждый раз, как :
текущий_адрес=базовый_адрес+количество_запусков*длина_записи(+смещение_канала)
если результат больше 1023, то текущий_адрес=базовый_адрес
Так у Вас lc.clearDisplay(0) на каждом прогоне loop (вызове Filer) для температуры и времени. Зачем??
Если не чистить каша получается.
Но Вы правы. Поставил очистку на конкретные номера заходов на филер и все получилось :-)
Вот, получилось
Всем ОГРОМНОЕ спасибо.