Проблемы записи EEPROM в UNO
- Войдите на сайт для отправки комментариев
Сб, 14/03/2015 - 08:49
Есть плата UNO. Необходимо записать структуру в eeprom (структура Eeprom). Бьюсь уже неделю. Пробовал различными способами, везде наблюдаю схожие проблемы. Проблемы три:
1. Вызов функции записи (Hour()) работает только в цикле loop, в других местах запись приводит к сбросу контроллера в момент записи. Мне надо писать каждый час (сейчас для отладки сделано раз в минуту).
2. Пишется только первая переменная структуры, все остальные не менеются.
3. Первые две переменные (Eeprom.GlobalEnergyP и Eeprom.GlobalEnergyG) принимают бредовые знаения.
Сам скейтч (при компиляии занимает 28042 и 1432 байт соответственно). Функция записи 0 (AllResetEeprom()) работает корректно
#if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif #define DEMO // Признак демонстрации #define READVCC_CALIBRATION_CONST 1103782L // Калибровка встроенного АЦП (встроенный ИОН) по умолчанию 1126400 дальше измеряем питание и смотрим на дисплей #define NUM_SCREEN 4 // Число экранов #define CALIBRATION_CONST_220 147.13 // Калибровка датчика напряжения 220 В #define CALIBRATION_CONST_220_I 10.03 // Калибровка датчика тока 220 A #define EE_SAVED_ADDRESS 0 // Дополнительные библиотеки #include <OneWire.h> // OneWire библиотека #include <EEPROM.h> // Запись во флеш #include <leOS2.h> // Шедуллер задач #include "U8glib.h" // Экран ЖКИ 128х64 по SPI #include "rusFont.h" // Ресурс дополнительных фонтов #include "BitMap.h" // Ресурс картинки для вывода на дисплей #include "emonLib.h" #include <avr/pgmspace.h> // библиотека для использования PROGMEM и F - строковые константы в rom // ---------------------------------------------------------------------- byte fStart = 0; // Какой текущий экран вывода 0-стартовый volatile int count=0; // Счетчик вемени для записи в eeprom const char ver[] = "Ver. leOS2 0.61 130315";// Текущая верстия const byte statusLed = 13; // Нога куда прицеплено реле потока (если замкнуто то поток есть) - светодиод и реле к ТП 1-2 const byte sensorKey =12; // Нога куда прицеплена кнопка const byte Relay2 =6; // Нога куда прицеплено второе реле (пока не используется) const int TimeMeasurement=9850; // Длительность цикла измерения мсек !! неточно дискретность 16 мксек const int TimeInterview=120; // Длительность цикла опроса кнопок мсек const unsigned int TimeChart=59500; // Длительность цикла рисования графика не более 65000 (unsigned int) const unsigned long TimeHour=59500; // Длительность цикла час - для записи в ЕЕПРОМ const int ONE_WIRE_BUS = 10; // Нога на которой весят датчики температуры const int TEMPERATURE_PRECISION =12; // разрешение датчика темературы в битах 9-12 бит const float calibrationFactor = 0.435; // Калибровочный коэфициент датчика потока 2-0.439 3-431 const float heat_capacity=4.191; // Теплоемкость теплоносителя (вода 4.191) volatile unsigned long oldTime=0; // переменная для расчета interval volatile long interval; // реальный интервал измерения (чуть больше TimeMeasurement особенность leOS2) volatile long ChartInterval; // реальный интервал вывода графика (чуть больше TimeChart особенность leOS2) volatile unsigned long ChartOldTime=0; // переменная для расчета ChartInterval char buf[12]; // буфер для вывода чисел на экран byte oldKey=0; // Предыдущее знаение клавиши byte flagKey=1; // Флаг нажатия клавиши // Электросчетчик ----------------------------- const int eConst=1000; // Число импульсов на киловат/час volatile unsigned long eCount=0; // Счетчик импульсов от электросчетчика volatile float ePower=0; // Пиковая мощность за TimeMeasurement volatile float eEnergy=0; // Потребленная энергия byte pChart[60]; // Данные графика потеблемой мощности (датчики) byte ChartCOP[60]; // Данные графика COP volatile float pPower=0; // Пиковая мощность за TimeMeasurement volatile float pEnergy=0; // Потребленная энергия // Первый канал --------------------------- const byte sensorInterrupt1 = 0; // Первый датчик потока адрес прерывания const byte sensorPin1 = 2; // Первый датчик потока ножка на которую вешается датчик //const long totalLitresAdr1=0; // Адрес объема в литрах во флеше const float errOut1=0.05; // Ошибка первого датчика - вычитается из показаний 0.05 const float errIn1=0.09; // Ошибка второго датчика - вычитается из показаний 0.17 unsigned char ThermOut1[8] = {0x28,0xFF,0x37,0x7F,0x4A,0x04,0x00,0xCF}; // ТП обратка адрес датчика DS18B20 28FF377F4A0400CF закругленный конец byte ThermIn1 [8] = {0x28,0xBC,0x6B,0x3D,0x06,0x00,0x00,0x01}; // ТП подача адрес датчика DS18B20 28BC6B3D06000001 прямой конец синий кембрик volatile unsigned int pulseCount1=0; // Счетчик импульсов первого датчика volatile float flowRate1=0.0; // Поток литров в минуту измеряется раз в минуту volatile float totalLitres1=0.0; // Общий объем прошедшей житкости в литрах Пишется во флеш каждый час volatile float totalPower1=0.0; // Общий объем тепла volatile unsigned int count1 = 0; // Число импульсов от датчика полученное за интервал измерения volatile float HZ1=0.0; // Частота volatile float P1=0.0; // Мощность за секунду volatile float tOut1,tIn1; // текущие температуры byte Chart1[60]; // Данные первого графика (ТП) // Второй канал --------------------------- const byte sensorInterrupt2 = 1; // Второй датчик потока адрес прерывания const byte sensorPin2 = 3; // Второй датчик потока ножка на которую вешается датчик //const long totalLitresAdr2=0+6; // Адрес объема в литрах во флеше const float errOut2=0.00; // Ошибка первого датчика - вычитается из показаний const float errIn2=0.00; // Ошибка второго датчика - вычитается из показаний byte ThermOut2 [8]= {0x28,0xFF,0x37,0x7F,0x4A,0x04,0x00,0xCF}; // ТП обратка адрес датчика DS18B20 28FF377F4A0400CF закругленный конец byte ThermIn2 [8] = {0x28,0xBC,0x6B,0x3D,0x06,0x00,0x00,0x01}; // ТП подача адрес датчика DS18B20 28BC6B3D06000001 прямой конец volatile unsigned int pulseCount2=0; // Счетчик импульсов первого датчика volatile float flowRate2=0.0; // Поток литров в минуту измеряется раз в минуту volatile float totalLitres2=0.0; // Общий объем прошедшей житкости в литрах Пишется во флеш каждый час volatile float totalPower2=0.0; // Общий объем тепла volatile unsigned int count2 = 0; // Число импульсов от датчика полученное за интервал измерения volatile float HZ2=0.0; // Частота volatile float P2=0.0; // Мощность за секунду volatile float tOut2,tIn2; // текущие температуры byte Chart2[60]; // Данные второго графика (ГК) // Структура для записи в EEPROM volatile struct my_EEPROM { unsigned long GlobalEnergyP; // Потребленная энергия с момента старта ТН - не сбрасывается unsigned long GlobalEnergyG; // Выработанная энергия с момента старта ТН - не сбрасывается unsigned long YearEnergyP; // Потребленная энергия с начала сезона отопления ТН - сбрасывается unsigned long YearEnergyG; // Выработанная энергия с начала сезона отопления ТН - сбрасывается unsigned long GlobalHour; // Мото часы общие с момента старта ТН - не сбрасывается unsigned long YearHour; // Мото часы общие с начала сезона отопления ТН - сбрасывается } Eeprom; const uint32_t AdrrEeprom=0; // Адрес записи стуктуры во флеш volatile unsigned long EnergyP=0,EnergyG=0; // промежуточные переменные volatile unsigned long TimeEeprom=0; //long int EE_SAVED_ADDRESS EEMEM=0; int32_t EEMEM SAVED_ADDRESS; // ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ БИБЛИОТЕК U8GLIB_ST7920_128X64 u8g(4, 9, 8, U8G_PIN_NONE); // Дисплей SPI E = 4, RW = 9, RS = 8 leOS2 myOS; // многозадачность OneWire ds(ONE_WIRE_BUS); // поддержка температурных датчиков EnergyMonitor emon1; // Мониторинг электросети void setup(void) { u8g.setFont(my5x7rus); u8g.setRot180(); //Перевернул экран pinMode(statusLed, OUTPUT); // Индикация потока светодиод и реле digitalWrite(statusLed, HIGH); pinMode(sensorPin1, INPUT); // Подключение датчика потока 1 digitalWrite(sensorPin1, HIGH); pinMode(sensorPin2, INPUT); // Подключение датчика потока 2 digitalWrite(sensorPin2, HIGH); pinMode(sensorKey, INPUT); // Включена кнопка digitalWrite(sensorKey, HIGH); pinMode(5, INPUT); // Электросчетчик digitalWrite(5, HIGH); // Установка начальных переменных interval=TimeMeasurement; ChartInterval=TimeChart; attachInterrupt(sensorInterrupt1, pulseCounter1, CHANGE); // Прерывания attachInterrupt(sensorInterrupt2, pulseCounter2, CHANGE); myOS.begin(); myOS.addTask(measurement,myOS.convertMs(TimeMeasurement)); myOS.addTask(Chart,myOS.convertMs(TimeChart)); // myOS.addTask(Hour,myOS.convertMs(TimeHour)); // Программирование 1 таймера на подсчет событий на D5 (туда заводится электросчетчик) TCCR1A = 0; // reset Timer 1 TCCR1B = 0; TCNT1 = 0; // start Timer 1 External clock source on T1 pin (D5). Clock on rising edge. TCCR1B = bit (CS10) | bit (CS11) | bit (CS12); emon1.voltage(0,CALIBRATION_CONST_220,1.7); // Инициализация датчика напряжения 220 emon1.current(1, CALIBRATION_CONST_220_I); // Инициализация датчика тока 220 // Чтение счетчиков из флеша AllResetEeprom(); readEeprom(); } // --------------------------------------------- LOOP ------------------------------------ void loop(void) { float t; // Старт преобразования датчиков StartDS1820(ThermOut1); StartDS1820(ThermIn1); StartDS1820(ThermOut2); StartDS1820(ThermIn2); u8g.firstPage(); do { // Общая часть для каждого экрана (для экономии длины кода) - заголовок экрана if (fStart!=0) { u8g.drawBox(0,0,128,9); // Закрашиваем прямоугольник белым u8g.setColorIndex(0); // Черные чернила, Белый фон u8g.setPrintPos(1, 7); u8g.print(int(fStart)); u8g.drawLine(118, 0, 118, 8); // Индикатор потока на экран и на реле u8g.setPrintPos(121, 7); if ((flowRate1>0)&&(flowRate2>0)) {digitalWrite(statusLed, HIGH);u8g.print(F("+"));}// Светодиод и реле показывает что поток есть реле идет к ТН (1-2) else {digitalWrite(statusLed, LOW); u8g.print(F("-"));} u8g.drawLine(98, 0, 98, 8); // Индикатор потока на экран и на реле u8g.setPrintPos(100, 7); u8g.print(dtostrf(count,3,0,buf)); // Вывод напряжения в стоке состояния // u8g.print(dtostrf(emon1.Vrms,3,0,buf)); // Вывод напряжения в стоке состояния u8g.setPrintPos(8, 7); // Далее сразу можно печатать заголовок } switch (fStart) { case 0: ScreenStart(); break; case 1: Screen1(); break; case 2: Screen2(); break; case 3: Screen3(); break; case 4: Screen4(); break; default:Screen1(); } } while( u8g.nextPage() ); if (fStart==0) { delay(3000); myOS.addTask(scanKey,myOS.convertMs(TimeInterview)); } // Клавиатура активируется, начинается сканирование if (count>=1) { Hour(); count=0; Eeprom.GlobalEnergyP++;} delay(500); emon1.calcVI(20,4000); t=getTempDS1820(ThermOut1); if (t>-30&&t<80) tOut1=t-errOut1; // Иногда считывает глюки t=getTempDS1820(ThermIn1); if (t>-30&&t<70) tIn1=t-errIn1; // Иногда считывает глюки t=getTempDS1820(ThermOut2); if (t>-30&&t<30) tOut2=t-errOut2; // Иногда считывает глюки t=getTempDS1820(ThermIn2); if (t>-30&&t<30) tIn2=t-errIn2; // Иногда считывает глюки } // Стартовый экран -------------------------------------- void ScreenStart() { u8g.setColorIndex(1); u8g.drawXBM(0, 0, 56, 56, u8g_logo_bits); // u8g.drawXBM(0, 0, 51, 51, aLogo); u8g.setPrintPos(73, 10); u8g.print(F("Контроль")); u8g.setPrintPos(70, 20); u8g.print(F("Теплового")); u8g.setPrintPos(78, 30); u8g.print(F("Насоса")); u8g.setPrintPos(66, 40); u8g.print(F("Arduino UNO")); u8g.setPrintPos(1, 63); u8g.print(ver); } // Отображение типа 1 ------------------------------------- void Screen1() { byte x1,y1,i; u8g.print(F("Теплые Полы")); u8g.setColorIndex(1); // белые чернила, черный фон u8g.setPrintPos(0, 16); u8g.print(F("Поток: Част:")); u8g.setPrintPos(32, 16); u8g.print(dtostrf(flowRate1*60.0/1000.0,4, 3, buf)); u8g.setPrintPos(95, 16); u8g.print(HZ1); u8g.drawXBM(58, 10, 9, 7, cub); u8g.drawXBM(120, 10, 8, 7, Hz); u8g.drawLine(0, 18, 127, 18); u8g.drawXBM(0, 20, 21, 25, T123); // Термометр и значки x1=8; y1=26; u8g.setPrintPos(x1+14, y1); // Подача u8g.print(dtostrf(tOut1,4, 2, buf)); u8g.drawXBM(x1+45, y1-6, 9, 7, C0); u8g.setPrintPos(x1+14, y1+9); // Обратка u8g.print(dtostrf(tIn1,4, 2, buf)); u8g.drawXBM(x1+45, y1-6+9, 9, 7, C0); if (tOut1-tIn1<0) u8g.setPrintPos(x1+13, y1+9+9); // Разность температур else u8g.setPrintPos(x1+14+6, y1+9+9); u8g.print(dtostrf(tOut1-tIn1,4, 2, buf)); u8g.drawXBM(x1+45, y1-6+9+9, 9, 7, C0); u8g.drawLine(63, 18, 63, 63); u8g.setFont(u8g_font_courB10); u8g.setPrintPos(107, 30); u8g.print(F("kW")); u8g.setPrintPos(70, 30); u8g.print(dtostrf(P1,3, 1, buf)); u8g.setFont(my5x7rus); u8g.drawLine(0, 46, 63, 46); u8g.setPrintPos(0, 54); u8g.print(F("V:")); u8g.setPrintPos(12, 54); u8g.print(dtostrf(totalLitres1/60/1000,11, 3, buf)); u8g.setPrintPos(0, 63); u8g.print(F("G:")); u8g.setPrintPos(12, 63); u8g.print(dtostrf(totalPower1,11, 3, buf)); // График // for(i=0;i<60;i++) u8g.drawPixel(65+i,63-Chart1[i]); // Точки for(i=0;i<60;i++) u8g.drawLine(65+i,64,65+i,64-Chart1[i]); // Линия 0 не выводится } // Отображение типа 2 ------------------------------------- void Screen2() { byte x1,y1,i; u8g.print(F("Гео контур")); u8g.setColorIndex(1); // белые чернила, черный фон u8g.setPrintPos(0, 16); u8g.print(F("Поток: Част:")); u8g.setPrintPos(32, 16); u8g.print(dtostrf(flowRate2*60.0/1000.0,4, 3, buf)); u8g.setPrintPos(95, 16); u8g.print(HZ2); u8g.drawXBM(58, 10, 9, 7, cub); u8g.drawXBM(120, 10, 8, 7, Hz); u8g.drawLine(0, 18, 127, 18); u8g.drawXBM(0, 20, 21, 25, T123); // Термометр и значки x1=8; y1=26; u8g.setPrintPos(x1+14, y1); // Подача u8g.print(dtostrf(tOut2,4, 2, buf)); u8g.drawXBM(x1+45, y1-6, 9, 7, C0); u8g.setPrintPos(x1+14, y1+9); // Обратка u8g.print(dtostrf(tIn2,4, 2, buf)); u8g.drawXBM(x1+45, y1-6+9, 9, 7, C0); if (tOut2-tIn2<0) u8g.setPrintPos(x1+13, y1+9+9); // Разность температур else u8g.setPrintPos(x1+14+6, y1+9+9); u8g.print(dtostrf(tOut2-tIn2,4, 2, buf)); u8g.drawXBM(x1+45, y1-6+9+9, 9, 7, C0); u8g.drawLine(63, 18, 63, 63); u8g.setFont(u8g_font_courB10); u8g.setPrintPos(107, 30); u8g.print(F("kW")); u8g.setPrintPos(70, 30); u8g.print(dtostrf(P2,3, 1, buf)); u8g.setFont(my5x7rus); u8g.drawLine(0, 46, 63, 46); u8g.setPrintPos(0, 54); u8g.print(F("V:")); u8g.setPrintPos(12, 54); u8g.print(dtostrf(totalLitres2/60/1000,11, 3, buf)); u8g.setPrintPos(0, 63); u8g.print(F("G:")); u8g.setPrintPos(12, 63); u8g.print(dtostrf(totalPower2,11, 3, buf)); // График // for(i=0;i<60;i++) u8g.drawPixel(65+i,63-Chart2[i]); for(i=0;i<60;i++) u8g.drawLine(65+i,64,65+i,64-Chart2[i]); // 0 не выводится } // Отображение типа 3 Напряжение Ток------------------------------------- void Screen3() { int i; u8g.print(F("Напряжение&Ток")); u8g.setColorIndex(1); // белые чернила, черный фон u8g.setPrintPos(0, 16); u8g.print(F("V rms:")); u8g.setPrintPos(31, 16); u8g.print(dtostrf(emon1.Vrms,4,1,buf)); // u8g.setPrintPos(66, 16); u8g.setPrintPos(0, 24); u8g.print(F("I rms:")); u8g.setPrintPos(31, 24); // u8g.setPrintPos(105, 16); u8g.print(dtostrf(emon1.Irms,4,1,buf)); u8g.setPrintPos(65, 16); u8g.print(F("Pow_f:")); u8g.setPrintPos(102, 16); u8g.print(dtostrf(emon1.powerFactor,3,2,buf)); u8g.setPrintPos(0, 34); u8g.print(F("PW кВт:")); u8g.setPrintPos(39,34); #ifdef DEMO // Демка u8g.print(dtostrf(pPower,4, 2, buf)); #else u8g.print(dtostrf(emon1.realPower/1000.0,4, 2, buf)); #endif // u8g.print(dtostrf(emon1.realPower/1000.0,4, 2, buf)); // u8g.print(dtostrf(pPower,4, 2, buf)); u8g.setPrintPos(75, 26); u8g.print(F("COP:")); u8g.setPrintPos(98, 26); if (emon1.realPower>500) u8g.print(dtostrf(P1/(emon1.realPower/1000),3,2,buf)); else u8g.print(dtostrf(0.0,3,2,buf)); u8g.drawLine(63, 18, 63, 63); u8g.drawLine(0, 26, 63, 26); u8g.drawLine(64, 18, 127, 18); // for(i=0;i<=6;i++) u8g.drawPixel(62,64-i*4); // Шкала мощность for(i=0;i<=5;i++) { u8g.drawPixel(64,64-i*7); // Шкала СОР u8g.drawPixel(65,64-i*7); } for(i=0;i<60;i++) // График { u8g.drawLine(i,64,i,64-pChart[i]); u8g.drawLine(67+i,64,67+i,64-ChartCOP[i]); } } // Отображение типа 4 Счетчики ------------------------------------- void Screen4() { u8g.print(F("Счетчики.")); u8g.setColorIndex(1); // белые чернила, черный фон u8g.drawLine(28, 9, 28, 63); u8g.drawLine(79, 9, 79, 63); u8g.setPrintPos(0, 16); u8g.print(F(" За сезон Общий")); u8g.setPrintPos(0, 24); u8g.print(F("P кВт")); u8g.setPrintPos(31, 24); u8g.print(long(Eeprom.YearEnergyP)); u8g.setPrintPos(82, 24); u8g.print(long(Eeprom.GlobalEnergyP)); u8g.setPrintPos(0, 32); u8g.print(F("G кВт")); u8g.setPrintPos(31, 32); u8g.print(long(Eeprom.YearEnergyG)); u8g.setPrintPos(82, 32); u8g.print(long(Eeprom.GlobalEnergyG)); u8g.setPrintPos(0, 40); u8g.print(F("COP")); u8g.setPrintPos(31, 40); u8g.print(dtostrf((float)Eeprom.YearEnergyG/(float)Eeprom.YearEnergyP,4,2, buf)); u8g.setPrintPos(82, 40); u8g.print(dtostrf((float)Eeprom.GlobalEnergyG/(float)Eeprom.GlobalEnergyP,4,2, buf)); u8g.setPrintPos(0, 48); u8g.print(F("Часы")); u8g.setPrintPos(31, 48); u8g.print(int(Eeprom.YearHour)); u8g.setPrintPos(82, 48); u8g.print(int(Eeprom.GlobalHour)); } // Прерывание подсчет импульсов от первого канала void pulseCounter1() { pulseCount1++; } // Прерывание подсчет импульсов от второго канала void pulseCounter2() { pulseCount2++; } // Цикл измерения интервал задается ----------------------------------- void measurement() { cli(); // Запретить прерывания TimeMeasurement count1=pulseCount1; pulseCount1 = 0; count2=pulseCount2; pulseCount2 = 0; sei(); // разрешить прерывания interval=millis()-oldTime; // Точное определение интервала ---------------------------- oldTime= interval+oldTime; if (interval<=0) interval=TimeMeasurement; // Через 50 дней millis() сбросится по этому после этого первая итерация расчетная #ifdef DEMO // Демка count1=random(190,240); count2=random(160,200); TCNT1=random(5,9); emon1.realPower=random(1700,2700); #endif // Первый канал HZ1=(count1*1000.0)/interval/2; // делить на 2 - это т.к. прерывания работает на оба фронта импульса CHANGE flowRate1 = HZ1/calibrationFactor; // рассчитать поток в литрах за минуту totalLitres1 = totalLitres1 + flowRate1*(interval/1000.0); P1=(flowRate1/60) // литры/килограммы в секунду *heat_capacity*(tOut1-tIn1); totalPower1 = totalPower1 + P1*(interval/1000.0)/3600; // Второй канал HZ2=(count2*1000.0)/interval/2; // делить на 2 - это т.к. прерывания работает на оба фронта импульса CHANGE flowRate2 = HZ2/calibrationFactor; // рассчитать поток в литрах за минуту totalLitres2 = totalLitres2 + flowRate2*(interval/1000.0); P2=(flowRate2/60) // литры/килограммы в секунду *heat_capacity*(tOut2-tIn2); totalPower2 = totalPower2 + P2*(interval/1000.0)/3600; // Электросчетчик eCount=eCount+TCNT1; // Общий счетчик ePower=(float)TCNT1*3600.0/(float)eConst/(interval/1000.0); // Пиковый счетчик eEnergy=(float)eCount/(float)eConst; TCNT1 = 0; // Датчик напряжения и тока pPower=emon1.realPower/1000.0; pEnergy=pEnergy+emon1.realPower*(3600.0*interval/1000.0); } // Сканирование клавиш ------------------------------------------ void scanKey() { byte key; key=digitalRead(sensorKey); if ((key==1)&&(oldKey==1)&&(flagKey==1)) {fStart++;flagKey=0;} // Клавиша нажита if ((key==0)&&(oldKey==1)) flagKey=1; // Начало (по заднему фронту) ожидания нового нажатия oldKey=key; if (fStart > NUM_SCREEN) fStart=1; } // Подготовка массива точек для графиков ---------------------------------------- void Chart() { int i; count++; ChartInterval=millis()-ChartOldTime; // Точное определение интервала показа графика---------------------------- ChartOldTime= ChartInterval+ChartOldTime; if (ChartInterval<=0) ChartInterval=TimeMeasurement; // Через 50 дней millis() сбросится по этому после этого первая итерация расчетная // Сдвиг графиков и запись новых данных for(i=0;i<60;i++) { Chart1[i]=Chart1[i+1]; Chart2[i]=Chart2[i+1]; pChart[i]=pChart[i+1]; ChartCOP[i]=ChartCOP[i+1]; } Chart1[59]=P1*2.5; Chart2[59]=P2*2.5; pChart[59]=9*emon1.realPower/1000; if (emon1.realPower>500) ChartCOP[59]=(P1/(emon1.realPower/1000))*7.0; else ChartCOP[59]=0; } // Вызывается раз в час используется для сохранения показаний счетчиков в еепром------------------------------ void Hour() { unsigned long dP,dG,dT; // Электричество dP= pEnergy-EnergyP; // Прирост за час EnergyP=pEnergy; // запоминание для нового цикла Eeprom.GlobalEnergyP =Eeprom.GlobalEnergyP+dP; Eeprom.YearEnergyP=Eeprom.YearEnergyP+dP; // Тепло dG= totalPower1-EnergyG; // Прирост за час EnergyG=totalPower1; // запоминание для нового цикла Eeprom.GlobalEnergyG =Eeprom.GlobalEnergyG+dG; Eeprom.YearEnergyG=Eeprom.YearEnergyG+dG; // Мото часы dT=millis()-TimeEeprom; if (dT<=0) dT=0; TimeEeprom=millis(); Eeprom.GlobalHour=Eeprom.GlobalHour+TimeEeprom/1000/60/60; Eeprom.YearHour=Eeprom.YearHour+TimeEeprom/1000/60/60; //Eeprom.YearHour=Eeprom.YearHour+TimeEeprom; // Запись во флеш writeEeprom(); } // Старт преобразования одного датчика ----------------------------------------------- void StartDS1820(byte *addr) { ds.reset(); ds.select(addr); ds.write(0x44,0); } // Чтение температуры одного датчика ----------------------------------------------- float getTempDS1820(unsigned char *addr) { byte i; byte type_s; byte present = 0; byte data[12]; // Запрос уже послан ранее StartDS1820 present = ds.reset(); ds.select(addr); ds.write(0xBE); // Команда на чтение регистра температуры for ( i = 0; i < 9; i++) { data[i] = ds.read();} int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; // 9 bit resolution default if (data[7] == 0x10) { // "count remain" gives full 12 bit resolution raw = (raw & 0xFFF0) + 12 - data[6]; } } else { byte cfg = (data[4] & 0x60); // at lower res, the low bits are undefined, so let's zero them if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms //// default is 12 bit resolution, 750 ms conversion time } return (float)raw / 16.0; } // Чтение внутреннего датчика температуры --------------------------------------- double GetTemp(void) { unsigned int wADC; double t; ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3)); ADCSRA |= _BV(ADEN); delay(20); ADCSRA |= _BV(ADSC); while (bit_is_set(ADCSRA,ADSC)); wADC = ADCW; t = (wADC - 324.31 ) / 1.22; return (t); } //----------------------------EEPROM FUNCTION-------------------------------------------------- void writeEeprom() { // byte *x = (byte *)&Eeprom; // for(int i = 0; i < 6*4; i++) EEPROM.write(i, x[i]); // eeprom_write_dword(0,32); // eeprom_write_dword(4,33); eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS), *(uint32_t *)&Eeprom.GlobalEnergyP); eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+4), *(uint32_t *)&Eeprom.GlobalEnergyG); eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+8), *(uint32_t *)&Eeprom.YearEnergyP); eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+12), *(uint32_t *)&Eeprom.YearEnergyG); eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+16), *(uint32_t *)&Eeprom.GlobalHour); eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+18), *(uint32_t *)&Eeprom.YearHour); /*long a; a=Eeprom.GlobalEnergyP; eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS), a); a=Eeprom.GlobalEnergyG; eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+4),a); a=Eeprom.YearEnergyP; eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+8),a); a=Eeprom.YearEnergyG; eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+12),a); a=Eeprom.GlobalHour; eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+16),a); a=Eeprom.YearHour; eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+18),a); */ } // Полный сброс делается только один раз void AllResetEeprom() { eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS, 0); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+4, 0); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+8, 0); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+12, 0); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+16, 0); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+18, 0); } // Сброс только последнего сезона void YearResetEeprom() { eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS, Eeprom.GlobalEnergyP); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+4, Eeprom.GlobalEnergyG); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+8, 0); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+12, 0); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+16, Eeprom.GlobalHour); eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+18, 0); } //read void readEeprom() { Eeprom.GlobalEnergyP=eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS); Eeprom.GlobalEnergyG=eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+4); Eeprom.YearEnergyP =eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+8); Eeprom.YearEnergyG =eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+12); Eeprom.GlobalHour =eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+16); Eeprom.YearHour =eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+18); }
void eeprom_write_dword (uint32_t *__p, uint32_t __value);
Я не спец, но второй параметр "обычный" а не указатель. А у Вас там чёрт ногу сломит, и разименование и указатель всё в одном флаконе.
Причём далее у Вас идет YearResetEeprom там используется просто значение как и должно быть...
Пробовал и такой код (он закоментированн), так сказать явно
long a;
a=Eeprom.GlobalEnergyP;
eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS), a);
Результат аналогичный
Нашел свой косяк и исправил третью проблему. Первые две остались
Воощем разобрался самостоятельно.
Было много моих ошибок в коде. Но главное что я нарыл -
Работа с eeprom не должна производится в обработчиках прерываний (любых). Я использую LEos 2 а она использует вачдог таймер (пытался на нее повесить запись раз в час). При вызове процедур работы eeprom из loop все стало работать. Да это не удобно но по другому никак. Да и в момент работы надо запрещать прерывания.
Сейчас все работает.