23A256 SPI RAM with Arduino Mega

Hi all,

I need to use the 23A256 RAM with my Arduino Mega using SPI interface.
Attached please find the schematic which I implemented. I used appropriate resistor-based voltage dividers to make sure I apply appropriate (1.5-1.9V) supply voltage to 23A256 RAM.
I downloaded the library (spiRAM3a.zip) from Arduino Playground - SpiRAM

However, when I run the "Test" example of the library I get the attached error, and when I run the "Example" example of the library I get no results at all.

Now I wonder whether I made the schematic wrong, or there is something wrong with the library.

In the examples I just changed the SS_PIN from 10 to 53, as pin 53 is the slave select pin of Mega.
There is a variable named "A5" in "Test" example, which was unclear for me.

I would highly appreciate if anyone can help.

Below please find the codes of both examples.

// Test example
#include <SPI.h>
#include <SpiRAM.h>

#define SS_PIN 53 //this was 10 in original example code

byte clock = 0;
SpiRAM spiRam(0, SS_PIN);

void setup() {
  digitalWrite(A5, HIGH);
  Serial.begin(115200); 
  delay(1000);              // wait for a second
  Serial.println("Version 1");  
}

// The RAM, initially having random contents, will fail the test. If A5 is 
// pulled to ground, the correct value will be written before test, and the
// RAM location written to, will pass the test. Keeping A5 low for the full 
// cycle from 0 to 7FFF will make the test completely happy. Until the next
// next power cycle.
void loop() {
  unsigned int address = 0;
  unsigned int i;
  unsigned int maxRam = 32768;
  byte wValue, rValue;
  for (i=0; i < maxRam; i++) {
    wValue = (byte) (i & 0xFF);
    if (digitalRead(A5) == LOW) {
      spiRam.write_byte(i, wValue);
    }
    rValue = (byte)spiRam.read_byte(i);
    if (wValue != rValue) {
      Serial.print("RAM error at ");
      Serial.print(i, HEX);
      Serial.print(" should be ");
      Serial.print(wValue, HEX);
      Serial.print(" is ");
      Serial.println(rValue, HEX);
    } else {
      Serial.println(i, HEX);
    }
  }
}
//Example example
#include <SPI.h>
#include <SpiRAM.h>

#define SS_PIN 53 //this was 10 in original example code

byte clock = 0;
SpiRAM SpiRam(0, SS_PIN);

void setup()   {                
  Serial.begin(9600);
}

void loop()                    
{
  char data_to_chip[17] = "Testing 90123456";
  char data_from_chip[17] = "                ";
  int i = 0;

  // Write some data to RAM
  SpiRam.write_stream(0, data_to_chip, 16);
  delay(100);

  // Read it back to a different buffer
  SpiRam.read_stream(0, data_from_chip, 16);

  // Write it to the serial port
  for (i = 0; i < 16; i++) {
    Serial.print(data_from_chip[i]);
  }
  Serial.print("\n");
  delay(1000);                  // wait for a second
}

gevorgparsyan:
Hi all,

I need to use the 23A256 RAM with my Arduino Mega using SPI interface.
Attached please find the schematic which I implemented. I used appropriate resistor-based voltage dividers to make sure I apply appropriate (1.5-1.9V) supply voltage to 23A256 RAM.
I downloaded the library (spiRAM3a.zip) from Arduino Playground - HomePage

However, when I run the "Test" example of the library I get the attached error, and when I run the "Example" example of the library I get no results at all.

Now I wonder whether I made the schematic wrong, or there is something wrong with the library.

In the examples I just changed the SS_PIN from 10 to 53, as pin 53 is the slave select pin of Mega.
There is a variable named "A5" in "Test" example, which was unclear for me.

I would highly appreciate if anyone can help.

Below please find the codes of both examples.

// Test example

#include <SPI.h>
#include <SpiRAM.h>

#define SS_PIN 53 //this was 10 in original example code

byte clock = 0;
SpiRAM spiRam(0, SS_PIN);

void setup() {
 digitalWrite(A5, HIGH);
 Serial.begin(115200);
 delay(1000);              // wait for a second
 Serial.println("Version 1");  
}

// The RAM, initially having random contents, will fail the test. If A5 is
// pulled to ground, the correct value will be written before test, and the
// RAM location written to, will pass the test. Keeping A5 low for the full
// cycle from 0 to 7FFF will make the test completely happy. Until the next
// next power cycle.
void loop() {
 unsigned int address = 0;
 unsigned int i;
 unsigned int maxRam = 32768;
 byte wValue, rValue;
 for (i=0; i < maxRam; i++) {
   wValue = (byte) (i & 0xFF);
   if (digitalRead(A5) == LOW) {
     spiRam.write_byte(i, wValue);
   }
   rValue = (byte)spiRam.read_byte(i);
   if (wValue != rValue) {
     Serial.print("RAM error at ");
     Serial.print(i, HEX);
     Serial.print(" should be ");
     Serial.print(wValue, HEX);
     Serial.print(" is ");
     Serial.println(rValue, HEX);
   } else {
     Serial.println(i, HEX);
   }
 }
}





//Example example
#include <SPI.h>
#include <SpiRAM.h>

#define SS_PIN 53 //this was 10 in original example code

byte clock = 0;
SpiRAM SpiRam(0, SS_PIN);

void setup()   {                
 Serial.begin(9600);
}

void loop()                    
{
 char data_to_chip[17] = "Testing 90123456";
 char data_from_chip[17] = "                ";
 int i = 0;

// Write some data to RAM
 SpiRam.write_stream(0, data_to_chip, 16);
 delay(100);

// Read it back to a different buffer
 SpiRam.read_stream(0, data_from_chip, 16);

// Write it to the serial port
 for (i = 0; i < 16; i++) {
   Serial.print(data_from_chip[i]);
 }
 Serial.print("\n");
 delay(1000);                  // wait for a second
}

I question the use of a resistor divider for your power supply, It might work, if the .1uF cap can even out the random voltage spikes.

But, It will never work. the Mega running on 5V is expecting logic HIGH levels to be 60% of VCC or 3v at a minimum. This means the high level output from your 23A512 (1.5v to 1.9v) will never be seen by the Mega as a high.

You are going to have to add active voltage level translation something like one of these Maxim Level converters

Chuck.

That amazingly convoluted resistor network you have on VCC cannot work IMO.

Essentially you have (we'll ignore the 300k, not sure why that is there)

5v - 470 - 3k3 - VCC - 2k2 - GND

Have another look at resistor dividers. I'll let you do the math but there's no way you have 5v on VCC.

And as Chuck said, the 3v MISO will not likely show as a high on a 5v AVR. (Actually Vih is 70% of VCC, so there is no chance)

Thank you guys for explanation.

Now I'm considering using another RAM like 23K256 (3.6V supply) or 23LC512 (5.5V supply). I guess with both of them I won't need to amplify the signal for MISO, am I correct?
Would the same library work with 23K256 and 23LC512 ?

Thanks.

23K256 (3.6V supply)

Do you plan to actually use a 3v6 supply?

5 x .7 = 3.5v, that is the minimum voltage guaranteed to be read as a high, if your chip is running at 3v6 it should be OK, but if you are using 3v3 it's not.

Why not just use the 5v chip? That will need no extra circuitry at all.

I don't know about the library.

gevorgparsyan:
Thank you guys for explanation.

Now I'm considering using another RAM like 23K256 (3.6V supply) or 23LC512 (5.5V supply). I guess with both of them I won't need to amplify the signal for MISO, am I correct?
Would the same library work with 23K256 and 23LC512 ?

Thanks.

The 23A,23K,23LC are the same chip functionally, Just their operation voltage is different. So, the library will work just fine.

If you are using a 5v processor why do you want to use a lower voltage memory? It is just added complexity.

The only time I use a mixed system is when I cannot get a 5V version. I am currently working on a system with

ESP-12F(3.3v), 23LCV1024(2.5V .. 5V),W25Q64F(3.3v),SDCard(3.3V), Arduino MEGA(5v).

Both processors will have access to the peripherals. So I chose 3.3v. This means I have to Down convert the MEGA's (MOSI,SCK,CS), Up convert the device (MISO). The ESP-12F can directly access them at their native 3.3. I had to add Tristate buffers between the two controllers and the peripherals with hardware handshaking. I implemented an active low SPIFREE signal using I2C level translation circuits connected to interrupt pins (Mega( < - > )ESP-12F.

This is a complex system with race situation considerations. It is a headache, I would not do it if I did not need it.

Chuck.

Hey guys.

I could manage to have signal level converter. So now my signals have correct levels at each side (23A256 and Arduino Mega).
However now when I'm running the example I get a weird result (see attached picture).

#include <SPI.h>
#include <SpiRAM.h>

#define SS_PIN 53 //this was 10 in original example code

byte clock = 0;
SpiRAM SpiRam(0, SS_PIN);

void setup()   {                
  Serial.begin(9600);
}

void loop()                    
{
  char data_to_chip[17] = "Testing 90123456";
  char data_from_chip[17] = "                ";
  int i = 0;

  // Write some data to RAM
  SpiRam.write_stream(0, data_to_chip, 16);
  delay(100);

  // Read it back to a different buffer
  SpiRam.read_stream(0, data_from_chip, 16);

  // Write it to the serial port
  for (i = 0; i < 16; i++) {
    Serial.print(data_from_chip[i]);
  }
  Serial.print("\n");
  delay(1000);                  // wait for a second
}

Can anyone tell, what is wrong there?

Thanks.

result.png

gevorgparsyan:
Hey guys.

I could manage to have signal level converter. So now my signals have correct levels at each side (23A256 and Arduino Mega).
However now when I'm running the example I get a weird result (see attached picture).

#include <SPI.h>

#include <SpiRAM.h>

#define SS_PIN 53 //this was 10 in original example code

byte clock = 0;
SpiRAM SpiRam(0, SS_PIN);

void setup()   {                
 Serial.begin(9600);
}

void loop()                    
{
 char data_to_chip[17] = "Testing 90123456";
 char data_from_chip[17] = "                ";
 int i = 0;

// Write some data to RAM
 SpiRam.write_stream(0, data_to_chip, 16);
 delay(100);

// Read it back to a different buffer
 SpiRam.read_stream(0, data_from_chip, 16);

// Write it to the serial port
 for (i = 0; i < 16; i++) {
   Serial.print(data_from_chip[i]);
 }
 Serial.print("\n");
 delay(1000);                  // wait for a second
}




Can anyone tell, what is wrong there?

Thanks.

I have no idea how SPIRam.h work, so, I can't tell you what went wrong.
But here is simple code to communicate with the ram.

/* circuit.

Arduino   -   Ram
MISO        SO
MOSI        SI
SCK          CLK
SS            CS

*/

#include <SPI.h>

void setup(){
Serial.begin(9600);
SPI.begin();
pinMode(SS,OUTPUT);  
digitalWrite(SS,HIGH); // de-select SPI RAM

SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));

// I am going to configure the memory for sequential access, no page boundaries 
// this step usually only needs to be done once, or if you have changed it.
digitalWrite(SS,LOW);
SPI.transfer(0x01); // Write mode register Command
SPI.transfer(0x40); // Sequential mode
digitalWrite(SS,HIGH);

SPI.endTransaction();


randomSeed(analogRead(0));  // try to get some random noise to init the pseudoRandom generator.

}

void writeBlock(uint16_t addr, const char msg[]){
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));

//now I am going to write a block of text
digitalWrite(SS,LOW);

SPI.transfer(0x02); // Write Command
SPI.transfer16(addr); // address where to store the data
uint16_t i=0;
while(buf[i]){ // while the character at bu[i] is not zero do,
 SPI.transfer(buf[i++]);  // send the byte at buf[i], then increment the value of i by one.
 }
SPI.transfer(0); // put a byte of zero at then end of the string of text to mark the end.

digitalWrite(SS,HIGH); // de-select the chip
SPI.endTransaction(); // release the SPI bus so that others may use it.
}

void readBlock(uint16_t addr, char msg[], uint16_t maxLen){

SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));

//now I am going to read a block of text, that is terminated by a '\0'
digitalWrite(SS,LOW);

SPI.transfer(0x03); // Read Command
SPI.transfer16(addr); // address where to store the data
uint16_t i=0;
bool done = !(i<maxLen); // is the output buffer full?
uint8_t dummy;
while(!done]){  
 buf[i++] = SPI.transfer(dummy);  // have to send a byte to get a byte, read does not care what is send.
 done = !(i<maxLen)||(buf[i-1]=='\0'); // terminate if buffer is full or a null is encountered.
 }
if(maxLen>0) buf[i-1]='\0';  // the last byte must be zero, if the buffer was full
 // I will overwrite the last received charater with a zero to make the end of the string.

digitalWrite(SS,HIGH); // de-select the chip
SPI.endTransaction(); // release the SPI bus so that others may use it.
}


void loop(){
uint16_t adr = random(0,0xFFFF); //adr is the starting point for the message, it may/can roll over the
// top 0xFFFF, back to the bottom 0x0000.

char msgBuf[300];

sprintf(msgBuf,"tick=%ld at adrs=%04X\nNow is the time for all good men to come the the aid of their fellow country men. This can be accomplished by the use of force in the governing of the populace.",millis(),adr);

writeBlock(adr,msgBuf);

sprintf(msgBuf," dummy data to prove the read actually worked, if the read failed, this will be send to Serial.")

readBlock(adr,msgBuf,300);

Serial.print(msgBuf);
Delay(5000);
}

This code should work, I don't have easy access to a UNO with a 23LC512 to try it on, also there might be simple syntax errors, I haven't tried compiling it.

Chuck.

Hi Chuck,

Thanks for the code.

  1. When I tried to compile the code I received several errors related to declaration of "buf" in read and write functions.
    I declared it in both functions like this: char buf[300]; // is this correct? If not please guide me how to do.
    P.S. There were also some minor syntax errors, which I fixed.

  2. I couldn't find where SS is defined. I thought it might be defined in SPI.h, but couldn't find anything. Could you please clarify?

  3. When I run the code, I receive the following message "dummy data to prove the read actually worked, if the read failed, this will be send to Serial"
    I guess I receive this because the read operation fails. And I'm not sure if the write operation works or not. I think this might be related to SS. Because I didn't assign the appropriate pin to it.

Could you please give me your comments to above points.

Thanks in advance.

Gevorg

gevorgparsyan:
Hi Chuck,

Thanks for the code.

  1. When I tried to compile the code I received several errors related to declaration of "buf" in read and write functions.
    I declared it in both functions like this: char buf[300]; // is this correct? If not please guide me how to do.
    P.S. There were also some minor syntax errors, which I fixed.

  2. I couldn't find where SS is defined. I thought it might be defined in SPI.h, but couldn't find anything. Could you please clarify?

  3. When I run the code, I receive the following message "dummy data to prove the read actually worked, if the read failed, this will be send to Serial"
    I guess I receive this because the read operation fails. And I'm not sure if the write operation works or not. I think this might be related to SS. Because I didn't assign the appropriate pin to it.

Could you please give me your comments to above points.

Thanks in advance.

Gevorg

Gevorg,
Attached is a correct version, it compiles, but it is untested.

The major corrections were to change buf[] to msg[] in the Read and Write function.

See if it works.

Chuck.

spiram1.ino (2.91 KB)

Hi Chuck,

I could compile and run the code. Attached please find the result.
I wonder why do I get those weird symbols, instead of a regular text.

And I had also another question, which is still unclear for me. Where is the SS defined (which pin)?
And if I have 2 RAMs, how can I define the other SS pin for the second RAM?

Regards,

Gevorg

Result.png

gevorgparsyan:
Hi Chuck,

I could compile and run the code. Attached please find the result.
I wonder why do I get those weird symbols, instead of a regular text.

And I had also another question, which is still unclear for me. Where is the SS defined (which pin)?
And if I have 2 RAMs, how can I define the other SS pin for the second RAM?

Regards,

Gevorg

the 'weird' symbols are just 0xFF.

Post a current schematic of your connections.

If you are using a Mega :
50: MISO
51: MOSI
52: SCK
53: SS

UNO:
10: SS
11: MOSI
12: MISO
13: SCK

Any other pin can be used for the CS line of the second RAM.

Only ONE of the CS (or SS) pins can be LOW at a time. That is what signals the RAM chip to listen to the SPI bus.

If you are receiving 255, I do not think your RAM is working. Either it is wired incorrectly, or it has failed.

Chuck.

I wonder why do I get those weird symbols, instead of a regular text.

That particular symbol is 0xFF, so as Chuck said your RAM is not working or your connections are bad, or (most likely I think) you are not handling the CS signal correctly.

Hi guys,

Attached please find the schematic. Could you please look at it, I might miss something.
The 470, 300k and the 12k, 6.8k resistor pairs are just voltage dividers.
The 23A256 needs about 1.8V supply, that's why I added the 470, 300k pair to reduce the 5V down to 1.8V.
As we already understood, the MISO signal coming from 23A256 is 1.8V as well, that's why I added the signal level converter to increase the 1.8V to 5V.
The signal level converter needs to be "supplied" by two voltage sources (low voltage - LV, and high voltage - HV). It has an input named LV1, where my 1.8V applies, and has an output, where I get the 5V. The LV supply must be equal to the LV1 input, that's why I added the 12k, 6.8k resistor pairs to get 1.8V (out of 5V) for supply.
I tested the converter separately and it works fine.

Any ideas what can cause a problem?

Thanks,

Gevorg

gevorgparsyan:
Hi guys,

Attached please find the schematic. Could you please look at it, I might miss something.
The 470, 300k and the 12k, 6.8k resistor pairs are just voltage dividers.
The 23A256 needs about 1.8V supply, that's why I added the 470, 300k pair to reduce the 5V down to 1.8V.
As we already understood, the MISO signal coming from 23A256 is 1.8V as well, that's why I added the signal level converter to increase the 1.8V to 5V.
The signal level converter needs to be "supplied" by two voltage sources (low voltage - LV, and high voltage - HV). It has an input named LV1, where my 1.8V applies, and has an output, where I get the 5V. The LV supply must be equal to the LV1 input, that's why I added the 12k, 6.8k resistor pairs to get 1.8V (out of 5V) for supply.
I tested the converter separately and it works fine.

Any ideas what can cause a problem?

Thanks,

Gevorg

Using a resistor divider for the Power source is the Failure point.

The load on your Power Supply is not STATIC, It is dynamic. I expect if you were to connect an oscilloscope to pin8 you would see voltages from your 2.2v down to below 1v. It is never going to be reliable.

The IC is spec'd to require 10mA during normal usage. I ran you circuit with a 10mA load a pin8,
the voltage drops down to 0.230V FAIL.

I wash my hands, I'm out.

Chuck.

Hi Chuck,

Could you recommend other type SPI RAMs which have a completed library?

Best regards,

Using a resistor divider for the Power source is the Failure point.

To quote from my post #2

That amazingly convoluted resistor network you have on VCC cannot work IMO.

Essentially you have (we'll ignore the 300k, not sure why that is there)

5v - 470 - 3k3 - VCC - 2k2 - GND

Have another look at resistor dividers. I'll let you do the math but there's no way you have 5v on VCC.

that was ignored, as indeed were my other comments.

I'm out as well.