Проблемы записи EEPROM в UNO

pav2000
Offline
Зарегистрирован: 15.12.2014

Есть плата UNO. Необходимо записать структуру в eeprom (структура Eeprom). Бьюсь уже неделю. Пробовал различными способами, везде наблюдаю схожие проблемы. Проблемы три:

1. Вызов функции записи (Hour()) работает только в цикле loop, в других местах запись приводит к сбросу контроллера в момент записи. Мне надо писать каждый час (сейчас для отладки сделано раз в минуту).

2. Пишется только первая переменная структуры, все остальные не менеются.

3. Первые две переменные (Eeprom.GlobalEnergyP и Eeprom.GlobalEnergyG) принимают бредовые знаения.

Сам скейтч (при компиляии занимает 28042 и 1432 байт соответственно). Функция записи 0 (AllResetEeprom())  работает корректно

001#if defined(ARDUINO) && ARDUINO >= 100
002  #include "Arduino.h"
003#else
004  #include "WProgram.h"
005#endif
006 
007#define DEMO                   // Признак демонстрации
008#define READVCC_CALIBRATION_CONST 1103782L // Калибровка встроенного АЦП (встроенный ИОН) по умолчанию 1126400 дальше измеряем питание и смотрим на дисплей
009#define NUM_SCREEN                4        // Число экранов
010#define CALIBRATION_CONST_220     147.13   // Калибровка датчика напряжения 220 В
011#define CALIBRATION_CONST_220_I   10.03    // Калибровка датчика тока 220 A
012#define EE_SAVED_ADDRESS   0
013 
014 
015 
016// Дополнительные библиотеки
017#include <OneWire.h>           // OneWire библиотека
018#include <EEPROM.h>            // Запись во флеш
019#include <leOS2.h>             // Шедуллер задач
020#include "U8glib.h"            // Экран ЖКИ 128х64 по SPI
021#include "rusFont.h"           // Ресурс дополнительных фонтов
022#include "BitMap.h"        // Ресурс картинки для вывода на дисплей
023#include "emonLib.h"
024#include <avr/pgmspace.h>      // библиотека для использования  PROGMEM и F  - строковые константы в rom
025// ----------------------------------------------------------------------  
026 
027byte fStart = 0;                            // Какой текущий экран вывода 0-стартовый
028volatile int count=0;                       // Счетчик вемени для записи в eeprom
029     
030const char ver[] = "Ver. leOS2 0.61 130315";// Текущая верстия
031const byte statusLed  = 13;                 // Нога куда прицеплено реле потока (если замкнуто то поток есть) - светодиод и реле к ТП 1-2
032const byte sensorKey =12;                   // Нога куда прицеплена кнопка
033const byte Relay2 =6;                       // Нога куда прицеплено второе реле (пока не используется)
034const int  TimeMeasurement=9850;            // Длительность цикла измерения мсек  !! неточно дискретность 16 мксек
035const int  TimeInterview=120;               // Длительность цикла опроса кнопок мсек
036const unsigned int  TimeChart=59500;        // Длительность цикла рисования графика не более 65000 (unsigned int)
037const unsigned long  TimeHour=59500;        // Длительность цикла час - для записи в ЕЕПРОМ
038const int  ONE_WIRE_BUS = 10;               // Нога на которой весят датчики температуры
039const int  TEMPERATURE_PRECISION =12;       // разрешение датчика темературы в битах 9-12 бит
040const float calibrationFactor = 0.435;      // Калибровочный коэфициент датчика потока 2-0.439 3-431
041const float heat_capacity=4.191;            // Теплоемкость теплоносителя (вода 4.191)
042  
043volatile unsigned long oldTime=0;           // переменная для расчета interval
044volatile long interval;                     // реальный интервал измерения (чуть больше TimeMeasurement особенность leOS2)
045volatile long ChartInterval;                // реальный интервал вывода графика (чуть больше TimeChart особенность leOS2)
046volatile unsigned long ChartOldTime=0;      // переменная для расчета ChartInterval
047char buf[12];                               // буфер для вывода чисел на экран
048byte oldKey=0;                              // Предыдущее знаение клавиши
049byte flagKey=1;                             // Флаг нажатия клавиши
050 
051// Электросчетчик -----------------------------
052const int eConst=1000;                       // Число импульсов на киловат/час
053volatile unsigned long eCount=0;             // Счетчик импульсов от электросчетчика
054volatile float ePower=0;                     // Пиковая мощность за TimeMeasurement
055volatile float eEnergy=0;                    // Потребленная энергия
056byte pChart[60];                             // Данные графика потеблемой мощности (датчики)
057byte ChartCOP[60];                           // Данные графика COP
058volatile float pPower=0;                     // Пиковая мощность за TimeMeasurement
059volatile float pEnergy=0;                    // Потребленная энергия
060 
061// Первый канал ---------------------------
062const byte sensorInterrupt1 = 0;             // Первый датчик потока адрес прерывания
063const byte sensorPin1       = 2;             // Первый датчик потока ножка на которую вешается датчик
064//const long totalLitresAdr1=0;                // Адрес объема в литрах  во флеше
065const float errOut1=0.05;                    // Ошибка первого датчика - вычитается из показаний 0.05
066const float errIn1=0.09;                     // Ошибка второго датчика - вычитается из показаний 0.17
067unsigned char ThermOut1[8] = {0x28,0xFF,0x37,0x7F,0x4A,0x04,0x00,0xCF};  // ТП обратка адрес датчика DS18B20 28FF377F4A0400CF закругленный конец
068byte ThermIn1 [8] = {0x28,0xBC,0x6B,0x3D,0x06,0x00,0x00,0x01};  // ТП подача адрес датчика DS18B20 28BC6B3D06000001 прямой конец  синий кембрик
069volatile unsigned int pulseCount1=0;         // Счетчик импульсов первого датчика
070volatile float flowRate1=0.0;                // Поток литров в минуту измеряется раз в минуту
071volatile float totalLitres1=0.0;             // Общий объем прошедшей житкости в литрах Пишется во флеш каждый час
072volatile float totalPower1=0.0;              // Общий объем тепла
073volatile unsigned int count1 = 0;            // Число импульсов от датчика полученное за интервал измерения
074volatile float HZ1=0.0;                      // Частота          
075volatile float P1=0.0;                       // Мощность за секунду
076volatile float tOut1,tIn1;                   // текущие температуры
077byte Chart1[60];                             // Данные первого графика (ТП)
078 
079// Второй канал ---------------------------
080const byte sensorInterrupt2 = 1;             // Второй датчик потока адрес прерывания
081const byte sensorPin2       = 3;             // Второй датчик потока ножка на которую вешается датчик
082//const long totalLitresAdr2=0+6;              // Адрес объема в литрах  во флеше
083const float errOut2=0.00;                    // Ошибка первого датчика - вычитается из показаний
084const float errIn2=0.00;                     // Ошибка второго датчика - вычитается из показаний
085byte ThermOut2 [8]= {0x28,0xFF,0x37,0x7F,0x4A,0x04,0x00,0xCF};  // ТП обратка адрес датчика DS18B20 28FF377F4A0400CF закругленный конец
086byte ThermIn2 [8] = {0x28,0xBC,0x6B,0x3D,0x06,0x00,0x00,0x01};  // ТП подача адрес датчика DS18B20 28BC6B3D06000001 прямой конец
087volatile unsigned int pulseCount2=0;         // Счетчик импульсов первого датчика
088volatile float flowRate2=0.0;                // Поток литров в минуту измеряется раз в минуту
089volatile float totalLitres2=0.0;             // Общий объем прошедшей житкости в литрах Пишется во флеш каждый час
090volatile float totalPower2=0.0;              // Общий объем тепла
091volatile unsigned int count2 = 0;            // Число импульсов от датчика полученное за интервал измерения
092volatile float HZ2=0.0;                      // Частота          
093volatile float P2=0.0;                       // Мощность за секунду
094volatile float tOut2,tIn2;                   // текущие температуры
095byte Chart2[60];                             // Данные второго графика (ГК)
096 
097// Структура для записи в EEPROM
098volatile struct my_EEPROM
099{
100unsigned long GlobalEnergyP;                          //  Потребленная энергия с момента старта ТН - не сбрасывается
101unsigned long GlobalEnergyG;                          //  Выработанная энергия с момента старта ТН - не сбрасывается
102unsigned long YearEnergyP;                            //  Потребленная энергия с начала сезона отопления ТН - сбрасывается
103unsigned long YearEnergyG;                            //  Выработанная энергия с начала сезона отопления ТН - сбрасывается
104unsigned long GlobalHour;                             //  Мото часы общие с момента старта ТН - не сбрасывается
105unsigned long YearHour;                               //  Мото часы общие с начала сезона отопления ТН - сбрасывается
106} Eeprom;
107const uint32_t AdrrEeprom=0;             // Адрес записи стуктуры во флеш
108volatile unsigned long EnergyP=0,EnergyG=0;  // промежуточные переменные
109volatile unsigned long TimeEeprom=0;
110//long int EE_SAVED_ADDRESS EEMEM=0;
111int32_t EEMEM SAVED_ADDRESS;
112 
113// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ БИБЛИОТЕК
114U8GLIB_ST7920_128X64 u8g(4, 9, 8, U8G_PIN_NONE);   // Дисплей SPI E = 4, RW = 9, RS = 8
115leOS2 myOS;                                        // многозадачность
116OneWire ds(ONE_WIRE_BUS);                          // поддержка температурных датчиков
117EnergyMonitor emon1;                               // Мониторинг электросети
118 
119void setup(void) {
120  u8g.setFont(my5x7rus);
121  u8g.setRot180();                   //Перевернул экран
122  pinMode(statusLed, OUTPUT);        // Индикация потока светодиод и реле
123  digitalWrite(statusLed, HIGH); 
124  pinMode(sensorPin1, INPUT);        //  Подключение датчика потока 1
125  digitalWrite(sensorPin1, HIGH);
126  pinMode(sensorPin2, INPUT);        //  Подключение датчика потока 2
127  digitalWrite(sensorPin2, HIGH);
128  pinMode(sensorKey, INPUT);         //  Включена кнопка
129  digitalWrite(sensorKey, HIGH);
130  pinMode(5, INPUT);                 //  Электросчетчик
131  digitalWrite(5, HIGH);
132  
133  // Установка начальных переменных
134  interval=TimeMeasurement;
135  ChartInterval=TimeChart; 
136  attachInterrupt(sensorInterrupt1, pulseCounter1, CHANGE);  // Прерывания
137  attachInterrupt(sensorInterrupt2, pulseCounter2, CHANGE);
138   
139  myOS.begin();
140  myOS.addTask(measurement,myOS.convertMs(TimeMeasurement));
141  myOS.addTask(Chart,myOS.convertMs(TimeChart));
142 // myOS.addTask(Hour,myOS.convertMs(TimeHour));
143      
144// Программирование 1 таймера на подсчет событий на D5 (туда заводится электросчетчик)
145  TCCR1A = 0;   // reset Timer 1
146  TCCR1B = 0;
147  TCNT1 = 0; 
148  // start Timer 1 External clock source on T1 pin (D5). Clock on rising edge.
149  TCCR1B =  bit (CS10) | bit (CS11) | bit (CS12);
150   
151  emon1.voltage(0,CALIBRATION_CONST_220,1.7);  // Инициализация датчика напряжения 220
152  emon1.current(1, CALIBRATION_CONST_220_I);   // Инициализация датчика тока 220
153   
154  // Чтение счетчиков из флеша
155 AllResetEeprom();
156  readEeprom();
157      }
158// --------------------------------------------- LOOP ------------------------------------  
159void loop(void) {
160  float t;
161 
162    // Старт преобразования датчиков
163    StartDS1820(ThermOut1);
164    StartDS1820(ThermIn1);
165    StartDS1820(ThermOut2);
166    StartDS1820(ThermIn2);
167   
168    u8g.firstPage();
169     do {
170       // Общая часть для каждого экрана (для экономии длины кода) - заголовок экрана
171       if (fStart!=0)
172        {
173          u8g.drawBox(0,0,128,9);  // Закрашиваем прямоугольник белым
174          u8g.setColorIndex(0);    // Черные чернила, Белый  фон
175          u8g.setPrintPos(1, 7);
176          u8g.print(int(fStart));
177          u8g.drawLine(118, 0, 118, 8);  // Индикатор потока на экран и на реле
178          u8g.setPrintPos(121, 7);
179          if ((flowRate1>0)&&(flowRate2>0)) {digitalWrite(statusLed, HIGH);u8g.print(F("+"));}// Светодиод и реле показывает что поток есть реле идет к ТН (1-2)
180          else {digitalWrite(statusLed, LOW); u8g.print(F("-"));}
181          u8g.drawLine(98, 0, 98, 8);  // Индикатор потока на экран и на реле
182          u8g.setPrintPos(100, 7);
183          u8g.print(dtostrf(count,3,0,buf)); // Вывод напряжения в стоке состояния
184      // u8g.print(dtostrf(emon1.Vrms,3,0,buf)); // Вывод напряжения в стоке состояния
185          u8g.setPrintPos(8, 7);   // Далее сразу можно печатать заголовок
186        }
187       switch (fStart)
188        {
189        case 0: ScreenStart(); break;
190        case 1: Screen1(); break;
191        case 2: Screen2(); break;
192        case 3: Screen3(); break;
193        case 4: Screen4(); break;
194        default:Screen1();
195        }
196          
197       } while( u8g.nextPage() );
198        
199       if (fStart==0)
200         { delay(3000); myOS.addTask(scanKey,myOS.convertMs(TimeInterview)); } // Клавиатура активируется, начинается сканирование
201         
202       if (count>=1) { Hour();  count=0;  Eeprom.GlobalEnergyP++;}
203              
204        delay(500);
205        emon1.calcVI(20,4000); 
206        t=getTempDS1820(ThermOut1);
207        if (t>-30&&t<80) tOut1=t-errOut1;   // Иногда считывает глюки
208        t=getTempDS1820(ThermIn1);
209        if (t>-30&&t<70) tIn1=t-errIn1;     // Иногда считывает глюки
210        t=getTempDS1820(ThermOut2);
211        if (t>-30&&t<30) tOut2=t-errOut2;   // Иногда считывает глюки
212        t=getTempDS1820(ThermIn2);
213        if (t>-30&&t<30) tIn2=t-errIn2;     // Иногда считывает глюки
214     
215        }
216// Стартовый экран --------------------------------------
217void ScreenStart()
218{
219 u8g.setColorIndex(1);
220 u8g.drawXBM(0, 0, 56, 56, u8g_logo_bits);
221// u8g.drawXBM(0, 0, 51, 51, aLogo);
222 u8g.setPrintPos(73, 10);
223 u8g.print(F("Контроль"));
224 u8g.setPrintPos(70, 20);
225 u8g.print(F("Теплового"));
226 u8g.setPrintPos(78, 30);
227 u8g.print(F("Насоса"));
228 u8g.setPrintPos(66, 40);
229 u8g.print(F("Arduino UNO"));
230 u8g.setPrintPos(1, 63); 
231 u8g.print(ver);
232}
233 
234// Отображение типа 1 -------------------------------------
235void Screen1()
236{
237  byte x1,y1,i;
238  u8g.print(F("Теплые Полы"));
239  
240  u8g.setColorIndex(1);    // белые чернила, черный фон
241  u8g.setPrintPos(0, 16);
242  u8g.print(F("Поток:         Част:"));
243  u8g.setPrintPos(32, 16);
244  u8g.print(dtostrf(flowRate1*60.0/1000.0,4, 3, buf));
245  u8g.setPrintPos(95, 16);
246  u8g.print(HZ1);
247   
248  u8g.drawXBM(58, 10, 9, 7, cub);
249  u8g.drawXBM(120, 10, 8, 7, Hz);
250   
251  u8g.drawLine(0, 18, 127, 18);
252   
253  u8g.drawXBM(0, 20, 21, 25, T123); // Термометр и значки
254   
255  x1=8; y1=26;
256  u8g.setPrintPos(x1+14, y1); // Подача
257  u8g.print(dtostrf(tOut1,4, 2, buf));
258  u8g.drawXBM(x1+45, y1-6, 9, 7, C0);
259   
260  u8g.setPrintPos(x1+14, y1+9); // Обратка
261  u8g.print(dtostrf(tIn1,4, 2, buf));
262  u8g.drawXBM(x1+45, y1-6+9, 9, 7, C0);
263  
264  if (tOut1-tIn1<0) u8g.setPrintPos(x1+13, y1+9+9); // Разность температур
265  else  u8g.setPrintPos(x1+14+6, y1+9+9);
266  u8g.print(dtostrf(tOut1-tIn1,4, 2, buf));
267  u8g.drawXBM(x1+45, y1-6+9+9, 9, 7, C0);
268   
269  u8g.drawLine(63, 18, 63, 63);
270  
271  u8g.setFont(u8g_font_courB10);
272  u8g.setPrintPos(107, 30);
273  u8g.print(F("kW"));
274  u8g.setPrintPos(70, 30);
275  u8g.print(dtostrf(P1,3, 1, buf));
276  u8g.setFont(my5x7rus);
277   
278  u8g.drawLine(0, 46, 63, 46);
279       
280  u8g.setPrintPos(0, 54);
281  u8g.print(F("V:"));
282  u8g.setPrintPos(12, 54);
283  u8g.print(dtostrf(totalLitres1/60/1000,11, 3, buf));
284  u8g.setPrintPos(0, 63);
285  u8g.print(F("G:"));
286  u8g.setPrintPos(12, 63);
287  u8g.print(dtostrf(totalPower1,11, 3, buf));
288   
289  // График
290  // for(i=0;i<60;i++) u8g.drawPixel(65+i,63-Chart1[i]);     // Точки
291  for(i=0;i<60;i++) u8g.drawLine(65+i,64,65+i,64-Chart1[i]); // Линия 0 не выводится
292    
293}
294// Отображение типа 2 -------------------------------------
295void Screen2()
296{
297  byte x1,y1,i;
298  u8g.print(F("Гео контур"));
299   
300  u8g.setColorIndex(1);    // белые чернила, черный фон
301  u8g.setPrintPos(0, 16);
302  u8g.print(F("Поток:         Част:"));
303  u8g.setPrintPos(32, 16);
304  u8g.print(dtostrf(flowRate2*60.0/1000.0,4, 3, buf));
305  u8g.setPrintPos(95, 16);
306  u8g.print(HZ2);
307   
308  u8g.drawXBM(58, 10, 9, 7, cub);
309  u8g.drawXBM(120, 10, 8, 7, Hz);
310   
311  u8g.drawLine(0, 18, 127, 18);
312   
313  u8g.drawXBM(0, 20, 21, 25, T123); // Термометр и значки
314   
315  x1=8; y1=26;
316  u8g.setPrintPos(x1+14, y1); // Подача
317  u8g.print(dtostrf(tOut2,4, 2, buf));
318  u8g.drawXBM(x1+45, y1-6, 9, 7, C0);
319   
320  u8g.setPrintPos(x1+14, y1+9); // Обратка
321  u8g.print(dtostrf(tIn2,4, 2, buf));
322  u8g.drawXBM(x1+45, y1-6+9, 9, 7, C0);
323  
324  if (tOut2-tIn2<0) u8g.setPrintPos(x1+13, y1+9+9); // Разность температур
325  else  u8g.setPrintPos(x1+14+6, y1+9+9);
326  u8g.print(dtostrf(tOut2-tIn2,4, 2, buf));
327  u8g.drawXBM(x1+45, y1-6+9+9, 9, 7, C0);
328   
329  u8g.drawLine(63, 18, 63, 63);
330  
331  u8g.setFont(u8g_font_courB10);
332  u8g.setPrintPos(107, 30);
333  u8g.print(F("kW"));
334  u8g.setPrintPos(70, 30);
335  u8g.print(dtostrf(P2,3, 1, buf));
336  u8g.setFont(my5x7rus);
337   
338  u8g.drawLine(0, 46, 63, 46);
339       
340  u8g.setPrintPos(0, 54);
341  u8g.print(F("V:"));
342  u8g.setPrintPos(12, 54);
343  u8g.print(dtostrf(totalLitres2/60/1000,11, 3, buf));
344  u8g.setPrintPos(0, 63);
345  u8g.print(F("G:"));
346  u8g.setPrintPos(12, 63);
347  u8g.print(dtostrf(totalPower2,11, 3, buf));
348   
349   // График
350  // for(i=0;i<60;i++) u8g.drawPixel(65+i,63-Chart2[i]);
351  for(i=0;i<60;i++) u8g.drawLine(65+i,64,65+i,64-Chart2[i]); // 0 не выводится
352    
353}
354 
355// Отображение типа 3  Напряжение Ток-------------------------------------
356void Screen3()
357{
358  int i;
359  u8g.print(F("Напряжение&Ток"));
360  u8g.setColorIndex(1);    // белые чернила, черный фон
361   
362  u8g.setPrintPos(0, 16);
363  u8g.print(F("V rms:"));
364  u8g.setPrintPos(31, 16);
365  u8g.print(dtostrf(emon1.Vrms,4,1,buf));
366 // u8g.setPrintPos(66, 16);
367  u8g.setPrintPos(0, 24);
368  u8g.print(F("I rms:"));
369  u8g.setPrintPos(31, 24);
370//  u8g.setPrintPos(105, 16);
371  u8g.print(dtostrf(emon1.Irms,4,1,buf));
372   
373  u8g.setPrintPos(65, 16);
374  u8g.print(F("Pow_f:"));
375  u8g.setPrintPos(102, 16);
376  u8g.print(dtostrf(emon1.powerFactor,3,2,buf));
377   
378  u8g.setPrintPos(0, 34);
379  u8g.print(F("PW кВт:"));
380  u8g.setPrintPos(39,34);
381  #ifdef  DEMO    // Демка
382    u8g.print(dtostrf(pPower,4, 2, buf));
383  #else
384    u8g.print(dtostrf(emon1.realPower/1000.0,4, 2, buf));
385   #endif
386//  u8g.print(dtostrf(emon1.realPower/1000.0,4, 2, buf));
387//   u8g.print(dtostrf(pPower,4, 2, buf));
388   
389  u8g.setPrintPos(75, 26);
390  u8g.print(F("COP:"));
391  u8g.setPrintPos(98, 26);
392  if (emon1.realPower>500)  u8g.print(dtostrf(P1/(emon1.realPower/1000),3,2,buf));
393  else u8g.print(dtostrf(0.0,3,2,buf));
394    
395  u8g.drawLine(63, 18, 63, 63);
396  u8g.drawLine(0, 26, 63, 26);
397  u8g.drawLine(64, 18, 127, 18);
398   
399  //  for(i=0;i<=6;i++) u8g.drawPixel(62,64-i*4);  // Шкала мощность
400  for(i=0;i<=5;i++)
401  { u8g.drawPixel(64,64-i*7);   // Шкала СОР
402    u8g.drawPixel(65,64-i*7);
403  }
404  
405 for(i=0;i<60;i++) // График
406    {
407     u8g.drawLine(i,64,i,64-pChart[i]);  
408     u8g.drawLine(67+i,64,67+i,64-ChartCOP[i]);
409    }
410}
411 
412// Отображение типа 4  Счетчики -------------------------------------
413void Screen4()
414{
415  u8g.print(F("Счетчики."));
416  u8g.setColorIndex(1);    // белые чернила, черный фон
417   
418  u8g.drawLine(28, 9, 28, 63);
419  u8g.drawLine(79, 9, 79, 63);
420   
421  u8g.setPrintPos(0, 16);
422  u8g.print(F("        За сезон   Общий"));
423    
424  u8g.setPrintPos(0, 24);
425  u8g.print(F("P кВт"));
426  u8g.setPrintPos(31, 24);
427  u8g.print(long(Eeprom.YearEnergyP));
428  u8g.setPrintPos(82, 24);
429  u8g.print(long(Eeprom.GlobalEnergyP));
430  
431  u8g.setPrintPos(0, 32);
432  u8g.print(F("G кВт"));
433  u8g.setPrintPos(31, 32);
434  u8g.print(long(Eeprom.YearEnergyG));
435  u8g.setPrintPos(82, 32);
436  u8g.print(long(Eeprom.GlobalEnergyG));
437   
438  u8g.setPrintPos(0, 40);
439  u8g.print(F("COP"));
440  u8g.setPrintPos(31, 40);
441  u8g.print(dtostrf((float)Eeprom.YearEnergyG/(float)Eeprom.YearEnergyP,4,2, buf));
442  u8g.setPrintPos(82, 40);
443  u8g.print(dtostrf((float)Eeprom.GlobalEnergyG/(float)Eeprom.GlobalEnergyP,4,2, buf));
444 
445  u8g.setPrintPos(0, 48);
446  u8g.print(F("Часы"));
447  u8g.setPrintPos(31, 48);
448  u8g.print(int(Eeprom.YearHour));
449  u8g.setPrintPos(82, 48);
450  u8g.print(int(Eeprom.GlobalHour));
451 
452}
453// Прерывание подсчет импульсов от первого канала
454void pulseCounter1() {   pulseCount1++; }
455// Прерывание подсчет импульсов от второго канала
456void pulseCounter2() {   pulseCount2++; }
457 
458// Цикл измерения интервал задается -----------------------------------
459void measurement()
460{
461  cli();  // Запретить прерывания TimeMeasurement
462 count1=pulseCount1;  pulseCount1 = 0;
463 count2=pulseCount2;  pulseCount2 = 0;
464 sei();  // разрешить прерывания
465  
466 interval=millis()-oldTime; // Точное определение интервала ----------------------------
467 oldTime= interval+oldTime; 
468 if (interval<=0) interval=TimeMeasurement; // Через 50 дней millis() сбросится по этому после этого первая итерация расчетная
469 
470 #ifdef  DEMO    // Демка
471     count1=random(190,240);
472     count2=random(160,200);
473     TCNT1=random(5,9);
474     emon1.realPower=random(1700,2700);
475   #endif
476 
477 // Первый канал
478 HZ1=(count1*1000.0)/interval/2; // делить на 2 - это т.к. прерывания работает на оба фронта импульса CHANGE
479 flowRate1 = HZ1/calibrationFactor; // рассчитать поток в литрах за минуту
480 totalLitres1 = totalLitres1 + flowRate1*(interval/1000.0);
481 P1=(flowRate1/60) // литры/килограммы в секунду
482                   *heat_capacity*(tOut1-tIn1);
483 totalPower1 = totalPower1 + P1*(interval/1000.0)/3600;
484  
485 // Второй канал
486 HZ2=(count2*1000.0)/interval/2; // делить на 2 - это т.к. прерывания работает на оба фронта импульса CHANGE
487 flowRate2 = HZ2/calibrationFactor; // рассчитать поток в литрах за минуту
488 totalLitres2 = totalLitres2 + flowRate2*(interval/1000.0);
489 P2=(flowRate2/60) // литры/килограммы в секунду
490                   *heat_capacity*(tOut2-tIn2);
491 totalPower2 = totalPower2 + P2*(interval/1000.0)/3600;
492  
493 // Электросчетчик
494 eCount=eCount+TCNT1; // Общий счетчик
495 ePower=(float)TCNT1*3600.0/(float)eConst/(interval/1000.0); // Пиковый счетчик
496 eEnergy=(float)eCount/(float)eConst;
497 TCNT1 = 0;
498  
499 // Датчик напряжения и тока
500 pPower=emon1.realPower/1000.0;
501 pEnergy=pEnergy+emon1.realPower*(3600.0*interval/1000.0);
502   
503 }
504 
505// Сканирование клавиш ------------------------------------------
506void scanKey()
507{
508byte key; 
509key=digitalRead(sensorKey);
510if ((key==1)&&(oldKey==1)&&(flagKey==1)) {fStart++;flagKey=0;}  // Клавиша нажита
511if ((key==0)&&(oldKey==1)) flagKey=1;                           // Начало (по заднему фронту) ожидания нового нажатия
512oldKey=key;
513if (fStart > NUM_SCREEN) fStart=1;
514}
515 
516// Подготовка массива точек для графиков ----------------------------------------
517void Chart()
518{
519 int i;
520  count++;
521 ChartInterval=millis()-ChartOldTime; // Точное определение интервала показа графика----------------------------
522 ChartOldTime= ChartInterval+ChartOldTime; 
523 if (ChartInterval<=0) ChartInterval=TimeMeasurement; // Через 50 дней millis() сбросится по этому после этого первая итерация расчетная
524  // Сдвиг графиков и запись новых данных
525  for(i=0;i<60;i++)
526     
527      Chart1[i]=Chart1[i+1];
528      Chart2[i]=Chart2[i+1];
529      pChart[i]=pChart[i+1];
530      ChartCOP[i]=ChartCOP[i+1];
531     }
532    Chart1[59]=P1*2.5;
533    Chart2[59]=P2*2.5;
534    pChart[59]=9*emon1.realPower/1000;
535    if (emon1.realPower>500) ChartCOP[59]=(P1/(emon1.realPower/1000))*7.0; else ChartCOP[59]=0;
536}
537// Вызывается раз в час используется для сохранения показаний счетчиков в еепром------------------------------
538void Hour()
539{
540unsigned long dP,dG,dT;
541//  Электричество
542 dP= pEnergy-EnergyP; // Прирост за час
543 EnergyP=pEnergy;      // запоминание для нового цикла
544 Eeprom.GlobalEnergyP =Eeprom.GlobalEnergyP+dP;
545 Eeprom.YearEnergyP=Eeprom.YearEnergyP+dP;
546  
547 // Тепло
548 dG= totalPower1-EnergyG; // Прирост за час
549 EnergyG=totalPower1;      // запоминание для нового цикла
550 Eeprom.GlobalEnergyG =Eeprom.GlobalEnergyG+dG;
551 Eeprom.YearEnergyG=Eeprom.YearEnergyG+dG;
552  
553 // Мото часы
554 dT=millis()-TimeEeprom;
555 if (dT<=0) dT=0;
556 TimeEeprom=millis();
557 Eeprom.GlobalHour=Eeprom.GlobalHour+TimeEeprom/1000/60/60;
558 Eeprom.YearHour=Eeprom.YearHour+TimeEeprom/1000/60/60;
559//Eeprom.YearHour=Eeprom.YearHour+TimeEeprom;
560 
561 // Запись во флеш
562writeEeprom();
563
564 
565// Старт преобразования одного датчика -----------------------------------------------
566void StartDS1820(byte *addr)
567{
568   ds.reset();
569   ds.select(addr);
570   ds.write(0x44,0); 
571}
572// Чтение температуры одного датчика -----------------------------------------------
573float getTempDS1820(unsigned char *addr)
574{
575    byte i;
576    byte type_s;
577    byte present = 0;
578    byte data[12];
579    // Запрос уже послан ранее StartDS1820
580    present = ds.reset();
581    ds.select(addr);
582    ds.write(0xBE); // Команда на чтение регистра температуры
583    for ( i = 0; i < 9; i++) { data[i] = ds.read();}
584    int16_t raw = (data[1] << 8) | data[0];
585    if (type_s) {
586     raw = raw << 3; // 9 bit resolution default
587     if (data[7] == 0x10) {
588      // "count remain" gives full 12 bit resolution
589      raw = (raw & 0xFFF0) + 12 - data[6];
590    }
591  } else {
592    byte cfg = (data[4] & 0x60);
593    // at lower res, the low bits are undefined, so let's zero them
594    if (cfg == 0x00) raw = raw & ~7;      // 9 bit resolution, 93.75 ms
595    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
596    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
597    //// default is 12 bit resolution, 750 ms conversion time
598  }
599  return (float)raw / 16.0;      
600}
601 
602// Чтение внутреннего датчика температуры ---------------------------------------
603double GetTemp(void)
604{
605  unsigned int wADC;
606  double t;
607  ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
608  ADCSRA |= _BV(ADEN); 
609  delay(20);          
610  ADCSRA |= _BV(ADSC); 
611  while (bit_is_set(ADCSRA,ADSC));
612  wADC = ADCW;
613  t = (wADC - 324.31 ) / 1.22;
614  return (t);
615}
616 
617//----------------------------EEPROM FUNCTION--------------------------------------------------
618 
619void writeEeprom()
620{
621//  byte *x = (byte *)&Eeprom;
622//  for(int i = 0; i < 6*4; i++) EEPROM.write(i, x[i]);
623   
624// eeprom_write_dword(0,32);
625// eeprom_write_dword(4,33);
626 
627 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS),  *(uint32_t *)&Eeprom.GlobalEnergyP);
628 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+4),  *(uint32_t *)&Eeprom.GlobalEnergyG);
629 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+8),  *(uint32_t *)&Eeprom.YearEnergyP);
630 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+12), *(uint32_t *)&Eeprom.YearEnergyG);
631 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+16), *(uint32_t *)&Eeprom.GlobalHour);
632 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+18), *(uint32_t *)&Eeprom.YearHour);
633 
634 
635/*long a;
636 a=Eeprom.GlobalEnergyP;
637 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS), a);
638 a=Eeprom.GlobalEnergyG;
639 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+4),a);
640 a=Eeprom.YearEnergyP;
641 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+8),a);
642 a=Eeprom.YearEnergyG;
643 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+12),a);
644 a=Eeprom.GlobalHour;
645 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+16),a);
646 a=Eeprom.YearHour;
647 eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS+18),a);
648*/
649}
650// Полный сброс делается только один раз
651void AllResetEeprom()
652{
653 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS, 0);
654 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+4, 0);
655 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+8, 0);
656 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+12, 0);
657 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+16, 0);
658 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+18, 0);
659}
660// Сброс только последнего сезона
661void YearResetEeprom()
662{
663 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS, Eeprom.GlobalEnergyP);
664 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+4, Eeprom.GlobalEnergyG);
665 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+8, 0);
666 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+12, 0);
667 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+16, Eeprom.GlobalHour);
668 eeprom_write_dword((uint32_t *)EE_SAVED_ADDRESS+18, 0);
669}
670 
671//read
672void readEeprom()
673{
674 Eeprom.GlobalEnergyP=eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS);                      
675 Eeprom.GlobalEnergyG=eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+4);                       
676 Eeprom.YearEnergyP  =eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+8);                         
677 Eeprom.YearEnergyG  =eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+12);                        
678 Eeprom.GlobalHour   =eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+16);                         
679 Eeprom.YearHour     =eeprom_read_dword((const uint32_t *)EE_SAVED_ADDRESS+18);      
680}

 

 

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

void eeprom_write_dword (uint32_t *__p, uint32_t __value);

Я не спец, но второй параметр "обычный" а не указатель. А у Вас там чёрт ногу сломит, и разименование и указатель всё в одном флаконе.

Причём далее у Вас идет YearResetEeprom там используется просто значение как и должно быть...

pav2000
Offline
Зарегистрирован: 15.12.2014

Пробовал и такой код (он закоментированн), так сказать явно

long a;
a=Eeprom.GlobalEnergyP;
eeprom_write_dword((uint32_t *)(EE_SAVED_ADDRESS), a);

Результат аналогичный

Нашел свой косяк и исправил третью проблему. Первые две остались

 

pav2000
Offline
Зарегистрирован: 15.12.2014

Воощем разобрался самостоятельно.

Было много моих ошибок в коде. Но главное что я нарыл -

Работа с eeprom не должна производится в обработчиках прерываний (любых). Я использую LEos 2  а она использует вачдог таймер (пытался на нее повесить запись раз в час). При вызове процедур работы eeprom из loop все стало работать. Да это не удобно но по другому никак. Да и в момент работы надо запрещать прерывания.

Сейчас все работает.