Reading data from Flow sensor with EEPROM

Hello Guys,

I am at the beginner level of Arduino and working on a project to measure the flow rate from the flow sensor.

The flow sensor came with a data sheet for Model 840205 (attached). I could read analog voltage of flow and temperature using a basic analog read program from example. But to make this into some meaning full data, we need to use data that is stored in EEPROM of the flow sensor.

can someone please help me to write a program to do so.

840205_206 Specification Rev B.pdf (324 KB)

The EEPROM manufacturers data book will include further details on how to read data out of the ROM.

Hello,

This was my first question on Arduino form and I have posted it in forum only.

The datasheet attached is all that was given by the manufacturer.

I'll try again

The EEPROM manufacturers data book

But to make this into some meaning full data, we need to use data that is stored in EEPROM of the flow sensor.
can someone please help me to write a program to do so.

It appears that the flow sensor uses an SPI eeprom.
Table 6.2 shows the pin connections.
Table 6.4 shows the address map.

This tutorial shows how to work with an SPI eeprom. It will give you some ideas.

Hello Cattledog,

I have been following this SPI EEPROM example and modified the code as I don't want to write anything in my EEPROM. Below are the connections I have made and my program.

Sensor Pin------Arduino pin
1------------A0
2-----------A1
3--------- 5V
4-----------Gnd
5---------11
6----------13
7----------10
8--------12
9----------5V
10--------Gnd

************ CODE *************
#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<8;I++)
{
buffer*=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);*
  • Serial.print('h');*
  • Serial.print('i');*
  • Serial.print('\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,HEX);*
  • Serial.print('\n');*
  • address++;*
  • if (address == 8)*
  • address = 0;*
  • delay(500); //pause for readability*
    }
    the output of this code is 78 (HEX). looks like i am doing something wrong here but not sure what.
    can you please help further.

Please edit your post to place your code with the code tags as described in Item 7 of How to Use this Forum.

Without them, the forum software distorts the posted code.

Here is corrected code

#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<8;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);
  Serial.print('h');
  Serial.print('i');
  Serial.print('\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,HEX);
  Serial.print('\n');
  address++;
  if (address == 8)
    address = 0;
  delay(500); //pause for readability
}

the output of this code is 78 (HEX).

78 repeated eight times, or just 78?

it keeps on printing 78 on serial every 0.5 seconds. i guess its because of loop.

Your code looks reasonable to me.

Can you see any sort of identification on the eeprom chip on the board? The specific manufacture and chip id might help determine any specific settings required.

I would suggest that you try different spi modes and speeds. You are using mode 0 at clk/4 (4MHz). While is is generically common, the specific eeprom may require something else. I'd try the different modes first, because an eeprom chip doesn't work at 4MHz would be unusual.

Hello,

Can you please tell me exactly where I need to make changes. I will try to get EEPROM datasheet also

Thanks

Can you please tell me exactly where I need to make changes

You will set the values in the SPCR (SPI Control Register) There are 4 possible modes set by bits 3 and 2. CPOL (clock polarity) and CPHA(clock phase).

There is a summary of the SPCR resister here
http://avrbeginners.net/architecture/spi/spi.html

Google search for "avr spcr spi control register" will get you more.

What Arduino are you using?

I will try to get EEPROM datasheet also

Good idea.

Hello cattledog,

I have gone through the link you have shared, and modified my code a little bit. I found the EEPROM installed on circuit it is AT25020AN and in its datasheet, it says clock speed 20MHZ. (attached datasheet).

I modified SPCR = (1<<SPE)|(1<<MSTR) to ------------->SPCR = (1<<SPE)|(1<<MSTR)|(SPR1)|(SPR1);

still, the output is 78 once and repeat after 0.5 seconds.

Code*******************

#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<8;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)|(SPR1)|(SPR1);
  clr=SPSR;
  clr=SPDR;
  delay(10);
  Serial.print('h');
  Serial.print('i');
  Serial.print('\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,HEX);
  Serial.print('\n');
  address++;
  if (address == 8)
    address = 0;
  delay(500); //pause for readability
}

AT25010B-20B-40B.pdf (784 KB)

I modified SPCR = (1<<SPE)|(1<<MSTR) to ------------->SPCR = (1<<SPE)|(1<<MSTR)|(SPR1)|(SPR1);

This syntax makes no sense to me. What do you want the SPCR register to look like when setup as you want?

I will take a look at the data sheet you attached.

Hello,

I corrected the syntax and got different results as below:

correct syntax------ SPCR = (1<<SPE)|(1<<MSTR)|(0<<CPOL)|(1<<CPHA)|(1<<SPR1)|(0<<SPR0);

Input Output
(0<<CPOL)|(0<<CPHA) 78
(0<<CPOL)|(1<<CPHA) FF
(1<<CPOL)|(0<<CPHA) BC
(1<<CPOL)|(1<<CPHA) 78

I will explain my project again below:
I have an airflow sensor that I want to use for airflow measurement using Arduino. This sensor comes with factory-set calibration which is stored in EEPROM.

In order to get the correct flow rate, I need to read calibration data and use it for flow rate calculations.

From what I read in the data sheet, the eeprom will work in mode 0 or mode 3 at 4Mhz. I would therefore set SPCR as you originally had it

 SPCR = (1<<SPE)|(1<<MSTR);

The problem that I see is that the tutorial was based on a larger eeprom than is on your device. There is only an 8 bit address (one byte), and not a 16 bit (2 byte) address.

Try to modify the read function to reflect that

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

Helle Cattledog,

I modified the code as per your suggestion and now i am getting below data output in Dec.

120
121
123
124
125
126
127

and it repeats

In reference to the the EEPROM Data Map of the Flow Sensor, (attachment in the first post) its not clear what you are seeing.

The sequential values certainly would appear to be wrong, but I don't see what is incorrect about the reading routine. However, I'm not very experienced with SPI.

I would suggest that you print address 0 through 15 to see if you can make more sense of the return values. It will be easier to deal with the values in HEX so please print them out in HEX.

I have cleaned up the code a bit, and made it consistent with all the values being typed as byte and removing the unused material.

#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 address=0;

byte spi_transfer(byte 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);
  delay(10);
  Serial.print('h');
  Serial.print('i');
  Serial.print('\n');//debug
  delay(1000);
}

byte read_eeprom(byte EEPROM_address)
{
  //READ EEPROM
  byte data;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(READ); //transmit read opcode
  spi_transfer(EEPROM_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(address);
  Serial.print('\t');
  Serial.print(eeprom_output_data,HEX);
  Serial.print('\n');
  address++;
  if (address == 16)
    address = 0;
  delay(500); //pause for readability
}

Can anyone please help further to understand this data or improve the data. i really need to do this.