По ходу настройки подсистемы стабилизации квадрокоптера закономерно возникла задача организации быстрого журнала событий, другими словами лога. Для составления полной картины происходящего внутри контроллера требуется вести лог исходных и фильтрованных показаний датчиков, а также переменных PID и прочих промежуточных величин. Таким образом, на каждом такте работы алгоритма, каждые 20мс, в лог будет записываться пять-шесть вещественных величин, что соответствует 20 - 24 байтам.
Самые простые варианты, которые пришли в голову первыми - это вести лог на встроенной или внешней flash-памяти, либо на ОЗУ микроконтроллера. В случае flash-памяти мы имеем огромное по своим размерам хранилище (например встроенная flash-память в mbed составляет 512кб), но весьма медленную скорость записи. Так, мои тесты на mbed показали, что процедура записи четырех байт с открыванием и закрыванием файла занимает около 80мс.
Запись в RAM безумно быстрая, но размер её весьма ограничен. Например, в mbed и Arduino UNO мы имеем всего 32кб RAM. При этом взять я могу далеко не все эти килобайты, ведь память расходуется на хранение других переменных программы. Дай бог удастся использовать 16кб, а это всего около 13 секунд при логировании шести вещественных чисел. Как вариант, можно прицепить к микроконтроллеру внешнюю DRAM память, подобные решения можно найти и для mbed, и для Arduino. Но я пошел немного по-другому пути, по пути инноваций :).
Ramtron FRAM
Во время поиска подходящего хранилища для лога я наткнулся на FRAM память. FRAM расшифровывается как Ferroelectric RAM и представляет собой очень быструю энергонезависимую память. Время хранения данных на FRAM составляет около 10 лет. Память выдерживает до 100 триллионов циклов перезаписи, а скорость записи/чтения ограничивается по-сути только скоростью интерфейса шины. Единственным производителем такой памяти на данный момент является компания Ramtron.
Существуют модификации чипов FRAM с параллельным интерфейсом, а также с распространенными I2C и SPI. Также есть микросхемы со встроенными дополнительными функциями, типа часов и календаря. Изначально я хотел приобрести чип FM25V10 объемом 128кб, но поскольку его не оказалось в наличии, для экспериментов пришлось взять FM25V02, который имеет более скромные 32кб. Кстати, к недостаткам FRAM относят высокую стоимость. Однако FM25V02 обошлась мне в 150р, что соизмеримо со стоимостью аналогичных SRAM микросхем.
Поскольку DIP корпус в наше время постепенно уходит в прошлое, чипы от ramtron практически все имеют корпус SOIC. В связи с этим, пришлось изготовить небольшую плату, которую можно бы было затем легко подключить к mbed.

FM25V02 снабжена SPI интерфейсом с максимальной скоростью 40МГц. Имеется поддержка SPI Mode 0 и 3. Для питания чипа потребуется 3.3в. Распиновка микросхемы представлена на рисунке, она аналогичная многим подобным устройствам памяти с поддержкой SPI.
Подключение к mbed происходит по следующей схеме:
FM25V02 | mbed | Описание |
S | 8 | Выбор |
Q | 6 - MISO | SPI выход |
W | 40 - VOUT | +3.3в |
VSS | 1 - GND | Земля |
D | 5 - MOSI | SPI вход |
C | 7 - SCK | Синхронизация |
HOLD | 40 - VOUT | +3.3в |
VDD | 40 - VOUT | +3.3в |
Небольшая программа для записи и чтения из FRAМ для mbed представлена ниже.
FRAM чтение/запись для mbed
#include "mbed.h"
Serial pc(USBTX, USBRX);
SPI spi(p5,p6,p7);
DigitalOut spi_cs(p8);
#define READ 0x03
#define WRITE 0x02
#define WRITE_ENABLED 0x06
int main() {
int address = 0;
char data[] = "Hello world!";
// write
spi_cs = 0;
spi.write(WRITE_ENABLED);
spi_cs = 1;
spi_cs = 0;
spi.write(WRITE);
spi.write(address >> 8);
spi.write(address & 0xFF);
for( int i=0; i<14; i++ )
spi.write(data[i]);
spi_cs = 1;
// read
spi_cs = 0;
spi.write(READ);
spi.write(address >> 8);
spi.write(address & 0xFF);
for( int i=0; i<14; i++ )
pc.putc(spi.write(0x0));
spi_cs = 1;
}
По моим замерам, запись в FRAM шести вещественных чисел заняла около 200мкс, что вполне позволяет использовать данное устройство в качестве хранилища для лога. Конечно, образец FM25V02 имеет всего 32кб и придется подключить в SPI шине несколько таких микросхем, либо их более толстых товарищей FM25V10, с объемом памяти 128кб. Но в целом, задачу по организации лога можно считать решенной, и помогла её решить "интересная" память FRAM.