Friday, April 8, 2016

YellowJacket Arduino with WiShield Wifi (Part 17)

Adding Memory to the YellowJacket Arduino —
Early attempts to transmit sensor data from YJ56 over wifi to YJ57 and then write those data to the SD Card failed to compile due to not having enough dynamic memory on the Uno to include the SD Card library code. Web pages about Arduino dynamic memory clearly stated that the 328P processor could not have its dynamic memory expanded. My notes state:
“Arduino Memory: The Atmega 328 used in the Arduino UNO use a relatively pure Harvard architecture. Programs are stored in Flash memory and data is stored in SRAM. Flash memory is used to store the program image and any initialized data. You can execute program code from flash, but you can’t modify data in flash memory from your executing code. To modify the data, it must first be copied into SRAM. Flash memory is non-volatile, so your program will still be there when the system is powered off.”
One of the bigger offenders of using valuable dynamic (flash) memory is using print() and println() statements for Serial Monitor. A simple fix is to store the text strings that are to be printed in SRAM, e.g., (Serial.println(F(“>> Listening for connections…”));, where (F(“TEXT”) will be saved as data in SRAM rather than in flash.
One good reference that discusses Arduino memory is http://arduino.stackexchange.com/questions/221/what-can-i-do-if-i-run-out-of-flash-memory-or-sram.
A quick review of various memory technologies pointed to FRAM as one that had many benefits: 1) non-volatile; 2) fast; 3) easy read and write functions; and, 4) SPI hardware interface. The Adafruit SPI FRAM breakout board (Ref: https://learn.adafruit.com/adafruit-spi-fram-breakout/overview) was installed using a header and pins on an SD Card Shield. FRAM CS pin was wired to Shield pin D6. The breakout board FRAM chip, model MB85RS64V, is 8,192 words x 8 bits (SPI) with 16-bit addressing. Fujitsu currently manufactures larger FRAM chips (MB85RS2MT) with 262,144 words ×8 bits (SPI) with 24-bit addressing.
Adafruit_FRAM_SPI Library
To get started, the Adafruit_FRAM_SPI Library was downloaded to test the FRAM memory which worked with no problems. Each byte of FRAM memory is individually addressable from address:(uint16_t byteAddress(0-8191)). Command examples include:
  • fram.writeEnable(true/false);
  • fram.write(0xaddress, (uint8_t *)”Your text”, 10);
  • value=fram.read8(byteAddress);
Hackscribble_Ferro Library
Ref: https://github.com/hackscribble/hackscribble-ferro-library
Quoting the Ref: The Hackscribble_Ferro library makes it simple to use the FRAM in an Arduino sketch, for temporary storage while the sketch is running, for long-term storage which keeps its contents even if the Arduino is powered off, or a combination of these.
Hackscribble_Ferro provides functions for writing blocks of data to the FRAM, reading them back and controlling the FRAM. It assumes that your sketch will manage the details of how it uses the available FRAM memory.
Alternatively, Hackscribble_FerroArray lets you create arrays of data which are stored in the FRAM. For each array, you choose the type of data (e.g. byteintegerfloat, etc) and how many items are in the array (so long as you don’t exceed the maximum size of the FRAM).
Hackscribble_FerroArray takes care of how the arrays are stored in the FRAM, and you use simple functions to read and write your data.
Example sketch HF_test ran 14 read/write tests successfully on the FRAM MB85RS64V.
RamDisk Library
Ref: https://github.com/greiman/RamDisk
Ref: http://forum.arduino.cc/index.php?topic=229485.0
RamDisk provides a FAT style file system on external RAM devices. The RamDisk library was written for 24-bit FRAMs (MB85RS2MT) but the MB85RS64V uses 16-bit addresses. Quite a bit of coding was required to get RamDisk operational for all the test sketches. While the 8K MB85RS64V worked as a RamDisk, the MB85RS2MT would be a much better choice for a file storage system.
To use the MB85RS64V, initially each of the RamDisk library files was modified by changing unit32_t to uint16_t. In the end, only the modified MB85RS2MT.h, MB85RS2MT.cpp, and T_MB85RS2MT.h files were saved as an MB85RS64V library which would run the example sketches with the original RamDisk library. There may be lingering address issues in the MB85RS64V library which will have to be fixed.
Most issues in the Example sketches were linked to the limited memory of the 64 kbit MB85RS64V FRAM. There are lingering issues of device memory over-runs that are not trapped and reported by the code, both with the RamDisk Library and the modified SD Library provided with the RamDisk distribution. Sketch results using 16-bit MB85RS64V library and unmodified RamDisk library:
  • RD_HelloRamDisk OK
  • RD_testFram OK
  • RD_FramPerfTest OK
  • RD_RamTestPrint OK
  • RD_RamStdioBench OK
  • RD_RamByteReadWrite OK
  • RD_RamDiskLoggerTest_a OK
  • RD_RamDiskToSdFat OK
One handy sketch, ADX_dumpFram_01, was created to examine contents of the FRAM memory. The sketch uses one or both, Adafruit FRAM Library or Ramdisk Library, to read the FRAM addresses and print the contents as HEX, DEC, and ASCii. The beginning and end memory addresses can be set or the full memory can be displayed on Serial Monitor.
/*
 * 2016-04-06
 * ADX_dumpFram_01 for Arduino UNO, IDE 1.6.5
 *
 * If startRead > 0, startRead is adjusted to the closest buf read address.
 *
 * The ADX_dumpFram sketch reads an external FRAM on SPI
 * The code was developed using an Adafruit FRAM MB85RS64V breakout board
 *
 * The sketch works with the Adafruit MB85RS64V FRAM Library
 * or the RamDisk FRAM Library modified for the
 * MB85RS64V 16 bit Version
 *
 * Design:
 * Creates 8/64 byte buffer
 * Fills buffer with data from FRAM
 * Prints data, one byte at a time as HEX, DEC, and ASC
 *
 * This sketch reads/prints individual bytes of external memory
 *  As written, it does not process 2-byte or 4-byte numbers
 *  or more complex data structures
 *
 *  The sketch does not modify FRAM memory contents
 *
 * Sketch Example Output for MB85RS64 FRAM memory:
 * framTotalBytes = 8192;
 * startRead = 7938;
 * framEndByte = 8044;
 *
Type any character to begin

  ** Initialized Adafruit SPI FRAM **

 0x1F00: 15 16 17 18 19 1A 1B 1C  d7936:  21  22  23  24  25  26  27  28  a7936: . . . . . . . . 
 0x1F08: 1D 1E 1F 20 21 22 23 24  d7944:  29  30  31  32  33  34  35  36  a7944: . . . . ! " # $ 
 0x1F10: 25 26 27 28 29 2A 2B 2C  d7952:  37  38  39  40  41  42  43  44  a7952: % & ' ( ) * + , 
 0x1F18: 2D 2E 2F 30 31 32 33 34  d7960:  45  46  47  48  49  50  51  52  a7960: - . / 0 1 2 3 4 
 0x1F20: 35 36 37 38 39 3A 3B 3C  d7968:  53  54  55  56  57  58  59  60  a7968: 5 6 7 8 9 : ; < 
 0x1F28: 3D 3E 3F 40 41 42 43 44  d7976:  61  62  63  64  65  66  67  68  a7976: = > ? @ A B C D 
 0x1F30: 45 46 47 48 49 4A 4B 4C  d7984:  69  70  71  72  73  74  75  76  a7984: E F G H I J K L 
 0x1F38: 4D 4E 4F 50 51 52 53 54  d7992:  77  78  79  80  81  82  83  84  a7992: M N O P Q R S T 
 0x1F40: 55 56 57 58 59 5A 5B 5C  d8000:  85  86  87  88  89  90  91  92  a8000: U V W X Y Z [ \ 
 0x1F48: 5D 5E 5F 60 61 62 63 64  d8008:  93  94  95  96  97  98  99 100  a8008: ] ^ _ ` a b c d 
 0x1F50: 65 66 67 68 69 6A 6B 6C  d8016: 101 102 103 104 105 106 107 108  a8016: e f g h i j k l 
 0x1F58: 6D 6E 6F 70 71 72 73 74  d8024: 109 110 111 112 113 114 115 116  a8024: m n o p q r s t 
 0x1F60: 75 76 77 78 79 7A 7B 7C  d8032: 117 118 119 120 121 122 123 124  a8032: u v w x y z { . 
 0x1F68: 7D 7E 7F 80 81 82 83 84  d8040: 125 126 127 128 129 130 131 132  a8040: . . . . . . . . 

  ** Initialized RamDisk SPI FRAM **

 0x1F00: 15 16 17 18 19 1A 1B 1C  d7936:  21  22  23  24  25  26  27  28  a7936: . . . . . . . . 
 0x1F08: 1D 1E 1F 20 21 22 23 24  d7944:  29  30  31  32  33  34  35  36  a7944: . . . . ! " # $ 
 0x1F10: 25 26 27 28 29 2A 2B 2C  d7952:  37  38  39  40  41  42  43  44  a7952: % & ' ( ) * + , 
 0x1F18: 2D 2E 2F 30 31 32 33 34  d7960:  45  46  47  48  49  50  51  52  a7960: - . / 0 1 2 3 4 
 0x1F20: 35 36 37 38 39 3A 3B 3C  d7968:  53  54  55  56  57  58  59  60  a7968: 5 6 7 8 9 : ; < 
 0x1F28: 3D 3E 3F 40 41 42 43 44  d7976:  61  62  63  64  65  66  67  68  a7976: = > ? @ A B C D 
 0x1F30: 45 46 47 48 49 4A 4B 4C  d7984:  69  70  71  72  73  74  75  76  a7984: E F G H I J K L 
 0x1F38: 4D 4E 4F 50 51 52 53 54  d7992:  77  78  79  80  81  82  83  84  a7992: M N O P Q R S T 
 0x1F40: 55 56 57 58 59 5A 5B 5C  d8000:  85  86  87  88  89  90  91  92  a8000: U V W X Y Z [ \ 
 0x1F48: 5D 5E 5F 60 61 62 63 64  d8008:  93  94  95  96  97  98  99 100  a8008: ] ^ _ ` a b c d 
 0x1F50: 65 66 67 68 69 6A 6B 6C  d8016: 101 102 103 104 105 106 107 108  a8016: e f g h i j k l 
 0x1F58: 6D 6E 6F 70 71 72 73 74  d8024: 109 110 111 112 113 114 115 116  a8024: m n o p q r s t 
 0x1F60: 75 76 77 78 79 7A 7B 7C  d8032: 117 118 119 120 121 122 123 124  a8032: u v w x y z { . 
 0x1F68: 7D 7E 7F 80 81 82 83 84  d8040: 125 126 127 128 129 130 131 132  a8040: . . . . . . . . 
 0x1F70: 85 86 87 88 89 8A 8B 8C  d8048: 133 134 135 136 137 138 139 140  a8048: . . . . . . . . 
 0x1F78: 8D 8E 8F 90 91 92 93 94  d8056: 141 142 143 144 145 146 147 148  a8056: . . . . . . . . 
Done

 *
 */


#include <RamDisk.h> // ref: https://github.com/greiman/RamDisk
#include <MB85RS64V.h> // ref: https://github.com/greiman/RamDisk
#include "SPI.h" // Arduino IDE
#include "Adafruit_FRAM_SPI.h" // ref: Adafruit.com

uint8_t buf[64];                // used by RamDisk code
uint8_t aBuf[8];                // used by Adafruit code
uint32_t framTotalBytes = 8192; // device total FRAM MB85RS64V 8192 byte memory
uint32_t framEndByte = framTotalBytes;    // Stop location chosen for total memory report
//uint32_t framEndByte = 8044;    // Stop location chosen for subset report
uint32_t startByte = 0;       // Start location for examining memory
//uint32_t startByte = 7938;      // Start location for examining subset of memory
uint32_t bufNum = 0;            // number of the current buf array 8192/64=128 buf reads
uint32_t framMemPtr;            // FRAM address pointer [0...framTotalBytes]
uint8_t value;                  // byte value read from FRAM

const uint8_t FRAM_CS = 6;          // FRAM SPI CS pin

// Option: SPI FRAM using RamDisk library
T_MB85RS64V<FRAM_CS> FRAM64V;

// Option: SPI FRAM using Adafruit library
Adafruit_FRAM_SPI adaFram = Adafruit_FRAM_SPI(FRAM_CS);  // use hardware SPI

//------------------------------------------------------------------------------
/*
 * There are many designs that could be used to cycle through and print the
 * FRAM memory. The aDumpFram design reads and prints 8 byte groups for a clean display.
 *  Reads a buffer 'aBuf[0...7]' from the FRAM[0...framTotalBytes]
 *      for [0...7] bytes from aBuf
 *        read a byte
 *          print as HEX
 *      next
 *
 *      for [0...7] bytes from aBuf
 *        read a byte
 *          print as DEC
 *      next
 *
 *      for [0...7] bytes from aBuf
 *        read a byte
 *          write as ASCII
 *      next
 *  next buf
 * done at end of framTotalBytes
 *
 */

//------------------------------------------------------------------------------


void aDumpFram() {
  // Use AdaFruit Library to
  // dump the FRAM memory to Serial Monitor

  if (!adaFram.begin()) {
    Serial.print(F("\n *** aDumpFram failed to Initialize ***\n\n"));
  }

  Serial.println(F("\n\n  ** Initialized Adafruit SPI FRAM **"));

  // do some checking and setup...
  bufNum = 0;
  uint32_t startRead = startByte;
  if (framEndByte > framTotalBytes) framEndByte = framTotalBytes; // adjust framEndByte
  if (startRead > 0) {  // starting dump from address other than 0
    bufNum = (startRead / sizeof(aBuf)) ; // calc the bufNum counter for the given startRead
    //       Serial.print("\nstartRead: "); Serial.print(startRead);
    startRead = bufNum * sizeof(aBuf); // adjust startRead to aBuf boundary
    //       Serial.print("\nNew startRead: "); Serial.print(startRead);
    //       Serial.print("\nbufNum: "); Serial.print(bufNum); Serial.print("\n");
  }

  while (startRead < framEndByte) {
    /* 1 */
    // Calc the recPtr to the 8 bytes to be read
    uint32_t recPtr = startRead; // read 8 bytes starting at this FRAM address
    /* debug
    Serial.print("\nstart:"); Serial.print (startRead);
    Serial.print(" bufNum:"); Serial.print (bufNum);
    */
    /* 3 */
    // right justify print HEX start address
    Serial.print("\n 0x");
    if (recPtr < 0x10) Serial.print('0');
    if (recPtr < 0x100) Serial.print('0');
    if (recPtr < 0x1000) Serial.print('0');
    Serial.print(recPtr, HEX);
    Serial.print(": ");

    // read 8 bytes into aBuf
    uint8_t bufPtr = 0;
    for (uint32_t framMemPtr = recPtr; framMemPtr < (recPtr + sizeof(aBuf)); framMemPtr++) { // read 8 bytes from FRAM[]
      aBuf[bufPtr] = adaFram.read8(framMemPtr); // Adafruit read8 one byte
      // write the HEX values
      value = aBuf[bufPtr]; // value of byte from aBuf[0...7]
      if (value < 0x10) Serial.print('0');
      Serial.print(value, HEX); Serial.print(" ");
      bufPtr++;
    }

    /* 4 */
    // right justify print DEC start address
    Serial.print(" d");
    if (framTotalBytes >= 100000) {
      if (recPtr < 100000) Serial.print('0');
    }
    if (framTotalBytes >= 10000) {
      if (recPtr < 10000) Serial.print('0');
    }
    if (framTotalBytes >= 1000) {
      if (recPtr < 1000) Serial.print('0');
    }
    if (framTotalBytes >= 100) {
      if (recPtr < 100) Serial.print('0');
    }
    if (recPtr < 10) Serial.print('0');
    Serial.print(recPtr, DEC);
    Serial.print(": ");

    // write the DEC values on the same line
    // process each byte of 8 byte aBuf
    for (uint8_t bufPtr = 0; bufPtr < sizeof(aBuf); bufPtr++) { // individual bytes from aBuf
      value = aBuf[bufPtr]; // value of byte from aBuf[0...7]
      if (value < 100) Serial.print(' ');
      if (value < 10) Serial.print(' ');
      Serial.print(value, DEC); Serial.print(" ");
    } // for (uint8_t bufPtr = 0; bufPtr < sizeof(aBuf); bufPtr++)

    /* 5 */
    // right justify print ASC start address
    Serial.print(" a");
    if (framTotalBytes >= 100000) {
      if (recPtr < 100000) Serial.print('0');
    }
    if (framTotalBytes >= 10000) {
      if (recPtr < 10000) Serial.print('0');
    }
    if (framTotalBytes >= 1000) {
      if (recPtr < 1000) Serial.print('0');
    }
    if (framTotalBytes >= 100) {
      if (recPtr < 100) Serial.print('0');
    }
    if (recPtr < 10) Serial.print('0');
    Serial.print(recPtr, DEC);
    Serial.print(": ");

    // write the Ascii Text values on the same line
    // process each byte of 8 in aBuf
    for (uint8_t bufPtr = 0; bufPtr < sizeof(aBuf); bufPtr++) { // individual bytes from aBuf
      value = aBuf[bufPtr]; // value of byte from aBuf[0...7]
      if ((value > 32) && (value < 124)) {
        Serial.write(value); Serial.print(" ");
      } else {
        Serial.print("."); Serial.print(" ");
      }
    } //for (uint8_t bufPtr = 0; bufPtr < sizeof(aBuf); bufPtr++)
    // increment bufNum (0...framTotalBytes/sizeof(aBuf) )
    //Serial.print("\nstart:"); Serial.print (startRead);
    //Serial.print(" bufNum:"); Serial.print (bufNum);
    bufNum++;
    startRead = startRead + sizeof(aBuf);
  } // while (startRead <= framEndByte) {
} // end aDumpFram()


//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/*
 * There are many designs that could be used to cycle through and print the
 * FRAM memory. The rDumpFram design prints 8 byte groups for a clean display.
 *  Reads a buffer 'buf[0...63]' from the FRAM[0...framTotalBytes]
 *    for [0...7] blocks (cycle 8 times)
 *      for [0...7] bytes
 *        read a byte
 *          print as HEX
 *      next
 *
 *      for [0...7] bytes
 *        read a byte
 *          print as DEC
 *      next
 *
 *      for [0...7] bytes
 *        read a byte
 *          write as ASCII
 *      next
 *    next block
 *  next buf
 * done at end of framTotalBytes
 *
 */

//------------------------------------------------------------------------------

void rDumpFram() {
  // Use RamDisk Library to
  // dump the FRAM memory to Serial Monitor

  FRAM64V.begin();

  Serial.println(F("\n\n  ** Initialized RamDisk SPI FRAM **"));

  // do some checking and setup...
  bufNum = 0;
  uint32_t startRead = startByte;
  if (framEndByte > framTotalBytes) framEndByte = framTotalBytes; // adjust framEndByte
  if (startRead > 0) {  // starting dump from address other than 0
    bufNum = (startRead / sizeof(buf)) ; // calc the bufNum counter for the given startRead
    //       Serial.print("\nstartRead: "); Serial.print(startRead);
    startRead = bufNum * sizeof(buf); // adjust startRead to buf boundary
    //       Serial.print("\nNew startRead: "); Serial.print(startRead);
    //       Serial.print("\nbufNum: "); Serial.print(bufNum); Serial.print("\n");
  }

  while (startRead < framEndByte) {
    /* 1 */
    // read 64 bytes
    FRAM64V.read(startRead, buf, sizeof(buf));
    // debug
    //Serial.print("\nbufNum: "); Serial.print(bufNum); Serial.print("\n");

    /* 2 */
    // process each of 64 bytes in buf
    //    process each [block of 8 bytes] for print width, 8 times
    //      for each block of 8 bytes in buf
    for (uint8_t iBlk = 0; iBlk < 8; iBlk++) { // block iBlk of 8 bytes from buf
      uint16_t recPtr = (bufNum * sizeof(buf)) + (iBlk * 8); // iBlk[0...7]*8

      /* 3 */
      //---------------------------------------------
      // write the HEX values
      // print iBlk start address as HEX
      Serial.print("\n 0x");
      if (recPtr < 0x10) Serial.print('0');
      if (recPtr < 0x100) Serial.print('0');
      if (recPtr < 0x1000) Serial.print('0');
      Serial.print(recPtr, HEX);
      Serial.print(": ");

      // write the HEX values
      // process each byte of 8 bytes from 8-byte block from buf to make 8-byte print record
      for (uint8_t j = 0; j < 8; j++) { // j individual bytes from block iBlk
        uint16_t bufPtr = (iBlk * 8) + j; // iBlk[0...63]*8 + j[0...7]
        value = buf[bufPtr]; // value of byte from buf[0...63]
        //        if needed, the FRAM memory address is framMemPtr
        //        uint16_t framMemPtr = (bufNum * 64) + bufPtr; // bufNum[0...128]*64 + iBlk[0...63]*8 + j[0...7]
        //        uint8_t value2 = fram.read8(framMemPtr); // Adafruit read8
        /* debug
          Serial.print("start:"); Serial.print (startRead);
          Serial.print(" bufNum:"); Serial.print (bufNum);
          Serial.print(" iBlk:"); Serial.print (iBlk);
          Serial.print(" j:"); Serial.print (j);
          Serial.print(" bufPtr:"); Serial.print (bufPtr, HEX); // buf[0...63] (0-3F)
          Serial.print(" framMemPtr:"); Serial.print (framMemPtr, HEX);
          Serial.print(" v:"); Serial.print (value, HEX);
          Serial.print(" v2:"); Serial.print (value2, HEX);
          Serial.print(""); Serial.print("");
        */
        if (value < 0x10) Serial.print('0');
        Serial.print(value, HEX); Serial.print(" ");
      } // for (uint8_t j = 0; j < 8; j++) {

      /* 4 */
      //---------------------------------------------
      // write the DEC values on the same line
      // print iBlk start address as DEC
      Serial.print(" d");
      if (framTotalBytes >= 100000) {
        if (recPtr < 100000) Serial.print('0');
      }
      if (framTotalBytes >= 10000) {
        if (recPtr < 10000) Serial.print('0');
      }
      if (framTotalBytes >= 1000) {
        if (recPtr < 1000) Serial.print('0');
      }
      if (framTotalBytes >= 100) {
        if (recPtr < 100) Serial.print('0');
      }
      if (recPtr < 10) Serial.print('0');

      Serial.print(recPtr, DEC);
      Serial.print(": ");

      // process each byte of 8 bytes from 8-byte block from buf to make 8-byte print record
      for (uint8_t k = 0; k < 8; k++) { // j individual bytes from block iBlk
        uint16_t bufPtr = (iBlk * 8) + k; // iBlk[0...63]*8 + j[0...7]
        value = buf[bufPtr]; // value of byte from buf[0...63]
        //Serial.print("  ");
        if (value < 100) Serial.print(' ');
        if (value < 10) Serial.print(' ');
        Serial.print(value, DEC); Serial.print(" ");
      } // for (uint8_t k = 0; k < 8; k++) {

      /* 5 */
      //---------------------------------------------
      // write the ASC values
      // print iBlk start address as ASC
      Serial.print(" a");
      if (framTotalBytes >= 100000) {
        if (recPtr < 100000) Serial.print('0');
      }
      if (framTotalBytes >= 10000) {
        if (recPtr < 10000) Serial.print('0');
      }
      if (framTotalBytes >= 1000) {
        if (recPtr < 1000) Serial.print('0');
      }
      if (framTotalBytes >= 100) {
        if (recPtr < 100) Serial.print('0');
      }
      if (recPtr < 10) Serial.print('0');
      Serial.print(recPtr, DEC);
      Serial.print(": ");

      // write the Text values on the same line
      // process each byte of 8 bytes from 8-byte block from buf to make 8-byte print record
      //Serial.print("  a> ");
      for (uint8_t l = 0; l < 8; l++) { // j individual bytes from block iBlk
        uint16_t bufPtr = (iBlk * 8) + l; // iBlk[0...63]*8 + j[0...7]
        value = buf[bufPtr]; // value of byte from buf[0...63]
        if ((value > 32) && (value < 124)) { // write ASC characters from 33 through 123
          Serial.write(value); Serial.print(" ");  // a space is placed between each ASC value for clarity
        } else {
          Serial.print("."); Serial.print(" "); // a dot is used for non-print ASC values
        }
      } // for (uint8_t l = 0; l < 8; l++) {

    } //for (uint8_t iBlk = 0; iBlk < 8; iBlk++) {
    // increment bufNum (0...framTotalBytes/sizeof(buf) )
    bufNum++;
    //if (startRead < framEndByte) startRead = startRead + sizeof(buf);
    startRead = startRead + sizeof(buf);
  } // while (startRead <= framTotalBytes) {
} // end rDumpFram()


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

void setup() {
  Serial.begin(115200);
  //Serial.println(F("Type any character to begin"));
  Serial.println(F("Begin ADX_dumpFram_01 >"));
  //while (!Serial.available());

  aDumpFram(); // print using Adafruit FRAM Library

  //rDumpFram(); // print using RamDisk Library

  Serial.print("\nDone\n");
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

void loop() {}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------

24LC16B EEPROM
Ref: http://www.microchip.com/wwwproducts/en/24LC16B
The Microchip 24LC16B EEPROM memory chip was also on hand for testing. The 24LC16B, also used with PICAXE, is an I2C device with 8 Blocks of 256 bytes of memory. Each Block is separately addressable as part of the slave address, and each of the 256 bytes of the Block are addressed as a starting byte address and string of bytes not to exceed the Block (page buffer) length (256 bytes). Only one 24LC16B can be used on a single I2C bus. Larger 4K-128K 24LCxx EEPROMs that use word addressing, can use up to 4 to 8 devices on a single I2C bus. Since the block size of the 24LC16B is 256 bytes, it could easily be used to read/write 8 different text/data strings of 0-255 bytes for applications that require extra dedicated memory. The FRAM, on the other hand, has contiguous 8,192 to 262,144 bytes of storage that can be accessed in one or many byte increments. The RamDisk software adds a FAT style file system using solid state memory storage.
What Was Learned?
There are several different memory options that can be used with Arduino, and software libraries have been written that can take advantage of the differing types of memory hardware, using both SPI and I2C. The Arduino 328P processor dynamic program memory can not be expanded, so using a 16-bit or 32-bit processor with larger program (flash) memory might be required. The cursory testing described above did not require high speeds, which may be a requirement for some applications and would limit what memory chips might provide the required speed.
The Arduino 328P begins to run out of I2C or SPI address pins fairly rapidly, especially when adding multiple sensors for data collection. A port expander (MCP23S17, CD74HC4067, or PCF8574) chip provides a means for increasing the number of Arduino pins for additional address ports to resolve this issue.
FRAM memory was quite versatile and relatively easy to add in code to Arduino sketches. The basic knowledge gained while testing the above memory chips provides some insight into using external memory in Arduino apps.

(Apr 8, 2016)

No comments:

Post a Comment