Go Down

Topic: Write to EEPROM of Arduino from another Arduino over SPI? (Read 116 times) previous topic - next topic

Kilijan

Hi, I was following the tutorial on using SPI to write to an EEPROM chip, found here: https://www.arduino.cc/en/Tutorial/SPIEEPROM

However, I didn't have this chip on hand. Knowing that Arduinos have on-board EEPROM, I grabbed a nearby Nano and tried to write to it. Confusingly, it was looking like it worked - it was reading the data (1-127 from the tutorial) correctly back, but when I tried to write a custom array, it just read the original array back to me. Confused, I then plugged the Nano in directly and read the EEPROM, which told me that it was full of 255's.

Any idea as to what is going on here?

Thanks!

groundFungus

#1
Feb 17, 2020, 04:28 am Last Edit: Feb 17, 2020, 04:32 am by groundFungus
You should post the code that you tried.  Describe what the code actually does and how that differs from what you expected the code to do. 

Read the forum guidelines to see how to post code.

Did you use the EEPROM library to write to the Nano EEPROM?

spycatcher2k

When you connected your nano to your Board, did you just use the SPI interface? This does NOT write to the EEPROM on the NANO! This is possibly why it did not work, you MAY have written to the on board EEPROM of the Board you were using.
Mrs Drew
-=-
UK Based PCB Manufacturing - PM for details
I will design & code for you, but I will also charge you (PM me)
Use Google or search this site BEFORE asking!

GoForSmoke

https://www.arduino.cc/en/Tutorial/SPIEEPROM

Interfacing a Serial EEPROM Using SPI

Materials Needed:

AT25HP512 Serial EEPROM chip (or similar)
Hookup wire
Arduino Microcontroller Module

...................

Arduino Nano is NOT a Serial EEPROM chip or similar.  That's what went wrong.

If you want to write to the Arduino chip EEPROM, try
https://www.arduino.cc/en/Reference/EEPROM

1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

Kilijan

Ok, I got some SPI EEPROM chips, specifically this one:

http://ww1.microchip.com/downloads/en/DeviceDoc/25AA256-25LC256-256K-SPI-Bus-Serial-EEPROM-20001822H.pdf

Any it seemed (at first) to respond to writing from a Nano. However, I noticed that after a few loops, the serial feed started to look strange, so I re-downloaded the original tutorial code:

Code: [Select]
#define DATAOUT 11//MOSI
#define DATAIN  12//MISO
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

byte eeprom_output_data;
byte eeprom_input_data=0;
byte clr;
int address=0;
//data buffer
char buffer [128];

void fill_buffer()
{
  for (int I=0;I<128;I++)
  {
    buffer[I]=I;
  }
}

char spi_transfer(volatile char data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
  return SPDR;                    // return the received byte
}

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

  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
  // SPCR = 01010000
  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  //sample on leading edge of clk,system clock/4 rate (fastest)
  SPCR = (1<<SPE)|(1<<MSTR);
  clr=SPSR;
  clr=SPDR;
  delay(10);
  //fill buffer with data
  fill_buffer();
  //fill eeprom w/ buffer
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WREN); //write enable
  digitalWrite(SLAVESELECT,HIGH);
  delay(10);
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WRITE); //write instruction
  address=0;
  spi_transfer((char)(address>>8));   //send MSByte address first
  spi_transfer((char)(address));      //send LSByte address
  //write 128 bytes
  for (int I=0;I<128;I++)
  {
    spi_transfer(buffer[I]); //write data byte
  }
  digitalWrite(SLAVESELECT,HIGH); //release chip
  //wait for eeprom to finish writing
  delay(3000);
  Serial.write('h');
  Serial.write('i');
  Serial.write('\n');//debug
  delay(1000);
}

byte read_eeprom(int EEPROM_address)
{
  //READ EEPROM
  int data;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(READ); //transmit read opcode
  spi_transfer((char)(EEPROM_address>>8));   //send MSByte address first
  spi_transfer((char)(EEPROM_address));      //send LSByte address
  data = spi_transfer(0xFF); //get data byte
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
  return data;
}

void loop()
{
  eeprom_output_data = read_eeprom(address);
  Serial.print(eeprom_output_data,DEC);
  Serial.write('\n');
  address++;
  if (address == 128)
    address = 0;
  delay(500); //pause for readability
}


After running this, my serial output was this:

Code: [Select]
hi
255
255
255
255
255
255
127
127
72
127
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
101
99
103
107
111
115
119


Clearly, this is not correct. Is this a lack of my understanding of how the chip works? Could the program be referencing the wrong address?

Thanks for your help!

Kilijan

The problem lay in me having the chip clock tied to the wrong pin.

GoForSmoke

This SPI tutorial (not my site) includes how-to and code to make Arduino work as an SPI slave device.

http://gammon.com.au/spi

There are bootloaders that let you write to flash. If it won't change, flash is good storage. EEPROM has 10x as many writes as flash at 100K guaranteed.
1) http://gammon.com.au/blink  <-- tasking Arduino 1-2-3
2) http://gammon.com.au/serial <-- techniques howto
3) http://gammon.com.au/interrupts
Your sketch can sense ongoing process events in time.
Your sketch can make events to control it over time.

Go Up