25Q32FVSIG FLASH MEMORY
At some point in an Arduino Journey you might lament the "tiny" amount of non-volatile memory (1024 bytes) found on the board. Some projects require data storage such that the data doesn't disappear when the power does!
The use of an SD-card module is possible, but I did see this little PCB on David Johnson-Davies most excellent Technoblogy site a few years ago.
The mastery of this PCB is the ability to plug straight in to a standard Arduino Uno and then be used, for example, as a data logger. For instance if you are doing long-term environmental monitoring then you could set up the project along the following lines:
/* Uses David Johnson-Davies (Technoblogy) DataFlash project to collect candle lumens via an LDR and then pump out the random candle goodness to an LED depending on the state of a button OneCircuit Sunday 6 June 16:54:19 AEST 2021 YT: https://www.youtube.com/channel/UCTm3eCrN6wk-Ozt9ymyKIIg/videos Blog:https://onecircuit.blogspot.com/ David's site: http://www.technoblogy.com/show?2JMU */ const byte analogInPin = A0; // pin for LDR const byte buttonPin = 8; // pin for button const byte outputPin = 6; // pin for LED boolean buttonPressed = false; // is the button pressed? int sensorValue = 0; // initialise sensor reading byte outputValue = 0; // initialise output // change these to suit const int sizeofbuffer = 1000; const int numberofbuffers = 40; byte readdelay = 5; byte flamedata[sizeofbuffer]; // data stored in buffer first // start of David's code #define PAGEPROG 0x02 #define READSTATUS 0x05 #define READDATA 0x03 #define WRITEENABLE 0x06 #define CHIPERASE 0x60 #define READID 0x90 const byte sck = 13; const byte miso = 12; const byte mosi = 11; const byte cs = 10; const byte power = 9; class DF { public: boolean Setup(); void BeginRead(unsigned long addr); void BeginWrite(void); uint8_t ReadByte(void); void WriteByte(uint8_t data); void EndRead(void); void EndWrite(void); private: unsigned long addr; uint8_t Read(void); void Write(uint8_t); void Busy(void); void WriteEnable(void); }; boolean DF::Setup () { uint8_t manID, devID; pinMode(power, OUTPUT); digitalWrite(power, HIGH); digitalWrite(cs, HIGH); pinMode(cs, OUTPUT); pinMode(sck, OUTPUT); pinMode(mosi, OUTPUT); pinMode(miso, INPUT); digitalWrite(sck, LOW); digitalWrite(mosi, HIGH); delay(1); digitalWrite(cs, LOW); delay(100); Write(READID); Write(0); Write(0); Write(0); manID = Read(); devID = Read(); digitalWrite(cs, HIGH); return (devID == 0x15); // Found correct device } void DF::Write (uint8_t data) { shiftOut(mosi, sck, MSBFIRST, data); } void DF::Busy () { digitalWrite(cs, 0); Write(READSTATUS); while (Read() & 1 != 0); digitalWrite(cs, 1); } void DF::WriteEnable () { digitalWrite(cs, 0); Write(WRITEENABLE); digitalWrite(cs, 1); } void DF::BeginRead (unsigned long start) { addr = start; Busy(); digitalWrite(cs, 0); Write(READDATA); Write(addr >> 16); Write(addr >> 8); Write(addr); } uint8_t DF::Read () { return shiftIn(miso, sck, MSBFIRST); } void DF::EndRead(void) { digitalWrite(cs, 1); } void DF::BeginWrite () { addr = 0; Busy(); // Erase DataFlash WriteEnable(); digitalWrite(cs, 0); Write(CHIPERASE); digitalWrite(cs, 1); Busy(); } uint8_t DF::ReadByte () { return Read(); } void DF::WriteByte (uint8_t data) { // New page if ((addr & 0xFF) == 0) { digitalWrite(cs, 1); Busy(); WriteEnable(); digitalWrite(cs, 0); Write(PAGEPROG); Write(addr >> 16); Write(addr >> 8); Write(0); } Write(data); addr++; } void DF::EndWrite (void) { digitalWrite(cs, 1); } DF DataFlash; // end of David's code void setup() { // look for the DataFlash module Serial.begin(57600); while (!Serial); if (!DataFlash.Setup()) { Serial.println("DataFlash not found"); for (;;); } // initialise pins pinMode(analogInPin, INPUT); pinMode(buttonPin, INPUT); pinMode(outputPin, OUTPUT); delay(2000); // are we collect data or output data? buttonPressed = digitalRead(buttonPin); } void loop() { // collect data if (buttonPressed) { digitalWrite(outputPin, LOW); Serial.println("Collecting and writing data:"); DataFlash.BeginWrite(); for (byte readings = 0; readings < numberofbuffers; readings++) { for (int writenum = 0; writenum < sizeofbuffer; writenum++) { sensorValue = analogRead(analogInPin); outputValue = map(sensorValue, 100, 900, 0, 230); // change to suit candle/lighting/etc if ((outputValue < 5) or (outputValue > 240)) { // clean up rough edges outputValue = 0; } flamedata[writenum] = outputValue; // write to buffer delay(readdelay); // delay between readings } // now write buffer to DataFlash module for (int writenum = 0; writenum < sizeofbuffer; writenum++) { DataFlash.WriteByte(flamedata[writenum]); } } DataFlash.EndWrite(); // done writing while (1) {}; // just wait, could flash LED? } // output data to LED if (!buttonPressed) { while (1) { DataFlash.BeginRead(0); for (byte readings = 0; readings < numberofbuffers; readings++) { for (int writenum = 0; writenum < sizeofbuffer; writenum++) { byte thisdata = DataFlash.ReadByte(); analogWrite(outputPin, thisdata); delay(readdelay); } }
delay(10);
DataFlash.EndRead();} } }delay(10);
The code seems to work fine, but some real issues emerged with the construction of David's flash module.
1. I oven baked the first one with the worst application of solder paste seen since the great solder paste disaster of 1687 in Cornwall. The program reported "DataFlash not found".
2. The first couple of soldered modules also came back "DataFlash not found".
3. Several versions of 3.3V regulator needed to be tested until I found a couple of guys that worked as advertised.
4. Quite a few of the Winbond 25Q32FVSIG chips were either faulty or I fried them in the process - a separate blog will look at these chips - are they really dead?
5. The wackiest problem? The diodes linking the flash memory to the input/output as per David's circuit stops the whole shebang from working? I've indicated this below with menacing red circles.
In a fit of rage/genius I simply removed them. The modules then worked and the universe celebrated (well, I celebrated).
Net result? Four fully working 4Mb flash memory boards that can sit on the edge of the Arduino Uno doing it's thing and record data happily, then regurgitate it as required.
Things to try?
1. Check out the Flash Chip "failures" using an EEProm adapter and appropriate tester.
2. Use bigger capacity chips! I've got some 25Q64FVSIG (8Mb) and 25Q128FVSIG (16Mb) chips on the way.
3. Design my own (larger) board. Omit diodes?