EEPROMの代替としてのArduino用I2C上のFRAM

オートバイのダッシュボードについては引き続き説明します。 このすばらしいデバイスには走行距離計、つまりキロメートル単位の距離計が含まれており、特性が悪いため、電源がオフの場合でもデータを保存する必要があります。 ああ、まだ何時間もあります、彼らは何とか揮発性で保存される必要があります。



もちろん、Arduinsの内部にはEEPROMがあります。 長い整数のかかとを格納するために多くのスペースは必要ありませんが、ニュアンスがあります。 EEPROMの書き込みリソースが制限されすぎています。 少なくとも数秒ごとにデータを書き込みたいです。 リソースEEPROMを使用すると、これをかなり目に見える時間で実行できます。つまり、内蔵メモリは明らかに永遠ではありません。



最初は、チップの1Kメモリのさまざまな場所のデータ構造を円で書き留めて、運命を欺いたかったのです。 ポインターもどこかに格納する必要があり、データはシーケンシャル検索に何らかのマーカーを使用するのに十分なほどランダムであると休息しました。



ポインターを格納する必要は、多くの方法でだまされる可能性があります。 たとえば、次のように:



struct MarkedSavedData { byte marker; // ,    . struct SavedData { //     } } data;
      
      







MarkedSavedData構造体は、eerpomまたはflash、または円で囲まれた何かで満たされています。 ポインターを書き込まないために、たとえば、空きレコードではdata.marker = 0x00を実行し、現在のデータではdata.marker = 0xffを占有します。 作業の過程では、もちろん、記録はポインターに従って行われ、コントローラーが起動すると、メモリ全体を検索するだけでdata.marker == 0xffの構造が検索されます。これが最後の正しいデータです。 2つのレコードが取得されるたびに、リリースされたレコードのdata.markerをリセットする必要があるかもしれません。



シリアルカウンター付きのオプションがあります。



 struct MarkedSavedData { unsugned int counter; //   . struct SavedData { //     } } data;
      
      







レコードごとに、カウンターを1つ増やし、オーバーフローを記録します。 コントローラーを起動するとき、オーバーフローの可能性を考慮して最大のカウンターを探すことはそれほど難しくありませんが、このための関数を作成し、スタック上の中間構造体をローカル変数に配置することで、スラムを節約できます。



これはすべて良いですが、これらは湿布です。



STC Metrotekの同僚は、FRAMの検索を提案しました。 これは、途方もない速度と10 14の書き込みサイクルを持つフェライトメモリです。



画像






参考になったAliexpressはそのようなモジュールを私にもたらしまし 。 ちなみに、モジュール形式のメモリは非常に高価です。 チップ自体の価格は16p / pcです。 チップのサイズは512バイトです。つまり、少々見えますが、無限のレコード数を考慮すれば十分です。



このチップの準備ができているもののトピックをグーグルで検索しても、何も見つかりませんでした。 素晴らしい猫、私は決めました、私はそれに訓練します! Wireのドック、FM24のデータシート、誰かのEEPROM / I2Cプロジェクトを同様のインターフェースで開き、FRAMのクラスをスケッチしました。



画像



Githubプロジェクト: github.com/nw-wind/FM24I2C



例はこのように添付されます。



 #include "FM24I2C.h" //   .   i2c. FM24I2C fm(0x57); void setup() { Wire.begin(); Serial.begin(9600); char str1[]="12345678901234567890"; char str2[]="qwertyuiopasdfghjklzxcvbnm"; int a1=0x00; //   FRAM int a2=0x40; //    FRAM fm.pack(a1,str1,strlen(str1)+1); //    delay(5); fm.pack(a2,str2,strlen(str2)+1); //    delay(5); char buf[80]; fm.unpack(a2,buf,strlen(str2)+1); //   Serial.println(str2); fm.unpack(a1,buf,strlen(str1)+1); //   Serial.println(str1); }
      
      





FRAMのi2cプロトコルは、EEPROMよりもはるかに簡単です。 メモリはバス上のデータ転送よりも高速に動作し、少なくとも2Kのarduino脳を一度に注ぐことができます。 私のコードの利点は、32バイトの不要なブロッキングやバイト転送さえないことです。



 class FM24I2C { private: int id; public: FM24I2C(int id_addr); ~FM24I2C(); void pack(int addr, void* data, int len); //    FRAM int unpack(int addr, void* data, int len); //   FRAM.    . //     ,    . void inline writeUnsignedLong(int addr, unsigned long data) { pack(addr, (void*)&data, sizeof(unsigned long)); } //  . unsigned long inline readUnsignedLong(int addr) { unsigned long data; return unpack(addr, (void*)&data, sizeof(unsigned long)) == sizeof(unsigned long) ? data : 0UL; } //      /,     ,   . //        . };
      
      





コードは少しだけです。



 void FM24I2C::pack(int addr, void* data, int len) { Wire.beginTransmission(id); Wire.write((byte*)&addr,2); Wire.write((byte*)data,len); // ,    unsigned int  :) Wire.endTransmission(true); } int FM24I2C::unpack(int addr, void* data, int len) { int rc; byte *p; Wire.beginTransmission(id); Wire.write((byte*)&addr,2); Wire.endTransmission(false); Wire.requestFrom(id,len); //      rc  p-data :) for (rc=0, p=(byte*)data; Wire.available() && rc < len; rc++, p++) { *p=Wire.read(); } return(rc); }
      
      





モジュールにはチップとコネクタ以外はほとんど何もないので、すでにいくつかのマイクロ回路を購入したいと思っています。 それが好きです。



All Articles