Логи
С интерфейсом калибровки завершили, теперь будем прикручивать логи. Для чего нам логи? Во-первых просто чтоб было. Во-вторых мониторинг - оно всегда полезно, посмотреть как меняется pH в аквариуме в течение суток, как реагирует на дозирование, проветривание комнаты и всякое такое.
Для хранения логов у нас на плате стоит отдельный чип EEPROM 64 килобайт (=65536 байт). Прикинем какой длины лог туда влезет. Для хранения величин pH с точностью до сотых (скажем от pH = 0.00 до 14.00) требуется 2 байта. До тысячных - тоже два байта. Получается, что в чип памяти влезет 65536 / 2 = 32768 измерений pH.
Но вообще-то просто просто писать данные в лог смысла нет, нужна привязка ко времени. Здесь в голову приходят два решения:
1) Записываем время старта логгирования и дальше пишем, скажем, с частотой 1 измерение в минуту. А дальше, программа рисующая график, будет знать, что измерение номер 60 - час прошел, номер 70 - час и 10 минут... Оно бы все хорошо, но где гарантии, что не будет пропусков измерений (например отключали прибор на время, процессор перезагрузился не вовремя - хотя такого с этими процессорами не бывает, но все же). Не нравится мне этот метод.
2) Для каждого измерения параллельно записываем время (и дату) измерения. Плюсы - правильный график можно будет нарисовать даже если были пропуски в измерениях и даже если измерения были через разные промежутки времени. Минусы - требуется лишняя память. Во сколько байт можно утрамбовать год+месяц+число+час+минуты? Вообще-то в шесть. Многовато. Тогда делаем такой финт - пишем не текущую дату, а время в минутах прошедшее с некоей стартовой точки, дата которой запоминается. Тогда все влезает в два байта. В итоге в наш чип влезет 32768 / 2 = 16384 измерений pH. Если делать 1 измерение в минуту, то хватит на 11 с лишним дней непрерывной записи. Нам оно выше крыши.
Итак, имеем возможность раз в минуту непрерывно писать в лог в течение 11 дней.
А что делать, если логгер работает дольше (включили и не выключаем)? Если дольше, то будем перезаписывать самые старые данные - в контроллере всегда будут данные за последние 11 дней (а более старое, если надо, автоматом скидывается на комп и плюсуется к предыдущим данным).
А как программа узнает по цепочке данных где у нас старые, а где новые данные? Маркируем старшим битом в логе времени (у меня сейчас нет цели сделать смысл сказанного понятным - я просто показываю некоторую нетривиальность и увлекательность процесса). Дальше по смене бита находим границу между старыми и новыми данными. А как искать эту смену бита в 16 тысячах измерений в общем-то не быстром чипе? Перебором упаримся, поэтому реализуем алгоритм бинарного поиска, скорость которого мало зависит от размера массива...
Короче - это все не сложно и уже реализовано. Осталось только прикрутить к интерфейсу (пока не сделал) чтобы оно было прозрачно для пользователя, без всего того мудрежа, о котором писал выше. Но для отладки, для собственных нужд, чтоб не тупить если будут ошибки в моем коде, написал инструмент для просмотра дампа памяти чипа, чтоб глазами видеть правильно ли туда все что надо пишется, вот на это весь день и угрохал. Выглядит он так, в окончательной публичной версии программы наверное уберу, чтоб не смущать простых пользователей.