Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

cs5460 with atmega8515

Status
Not open for further replies.

dhruv_electro

Advanced Member level 4
Joined
Dec 17, 2010
Messages
118
Helped
9
Reputation
18
Reaction score
8
Trophy points
1,298
Location
India
Activity points
2,378
here I am posting discussion with a friend about cs5460 so other can find it useful

donnib said:
dhruv_electro said:
donnib said:
Hi,
I read that you have implemented an simple energy meter using CS5460. I am trying to do the same but will be using an ATmega328 and i need some code to Configuration, Start measurement and Calibration. Could you send the final code to me ? I saw an example in this thread https://www.edaboard.com/threads/197704/

thx
donnib

Hi donnib.

The code i have given there is the final code and yes it is for ATmega8515. You can convert it acording to your mcu. I have code for:

Code:
void SPI_MasterInit(void);                               //for initialisation the spi
void SPI_MasterTransmit(unsigned char cData);  // spi transmition
unsigned char SPI_MasterReceive(void);           // for spi reception
void spi_reinitilise(void);                                // for reinitilise the cs5460 (read datasheet and see code)
unsigned long int SPI_Read_data(char cData);  //read data from address given from cs5460
void spi_data_write(char command,unsigned long int x); //write data at given address (24bit data)
you can copy detail code from that thred.

now if you wanted to read Voltage channel rms value than type this

Code:
EN_CS1();                                //enable cs5460 
x=SPI_Read_data(0x18);
DS_CS1();                               //disable cs5460
where 0x18 is address for reading data from voltage channel rms reg.

for calibration you can give calibration command like this

Code:
EN_CS2();
SPI_MasterTransmit(0xDA);
DS_CS2();
where 0xDA is calibration command for gain reg. see datasheet for other calibration. I have done ac offset and dc offset calibration.

for start of conversion you can do this:

Code:
EN_CS2();
SPI_MasterTransmit(0xE8;);
DS_CS2();
Hope you will find this useful.

Yes this is indeed pretty helpful. thank you VERY much for replyiing back. I just need to figure out how to convert this to an ATmega328 or TI MSP430. At the moment i only have the MSP430 because my Arduino Uno with the ATMega328 has just been ordered. I guess i need to initialize the SPI properly and set the clock correct, yes ?

Let pressume i have set up correct SPI. How do i start ?

Code:
int main(void)
{
//initialize SPI
SPI_MasterInit();

//start conversion
EN_CS2();
SPI_MasterTransmit(0xE8;);
DS_CS2();

//read V_RMS
EN_CS1();                                //enable cs5460 
x=SPI_Read_data(0x18);
DS_CS1();                               //disable cs5460
}

Would the above do it ?

Couple of more questions :

1. Calibration : How does that work in practice ? You just read the "Last voltage value" without load and if it gives let's say 210V then you know the offset is 220V-210V 10V ? What about the current because you do not know the value without load ? Sorry for asking such simple quesitons :(

2. What pins do i need to use ? Is SDO, SDI, CS, SCLK enough or i need the RESET pin as well ?

3. I would like to get all the enrgy used P during the use for some load so i can show it in a nice graph vs. time. Would one poll the "Last power value" and accumulate that or ? Any ideas are welcome ?

4. Did you do some wireless transmission from your microcontroller of the data or what did you do with your data delivered by the CS5460 ? My intention is to build some home monitoring meters for each wallet so i can monitor the power ussage in our house.

Thanks again for your very useful message.

br.
donnib

Yes you have done the right way of start of conversion command in your main function.

But before start you have to do following step:

1. read a byte or a flag stored in your eeprom after power up, which indicate that calibration is done on your device or not?
2. If that flag says yes then you skip 3 to 6 step and goto step 7.
3. If that flag says no then you have to do calibration.
4. For calibration process please read an application note given by cirrus logic "Calibrating the cs5460a".
5. after calibration is done please read the calibration values for the DC/AC offset reg & Gain Reg.
6. Store this value in your eeprom or your flash.
7. Now after each power up you have to write this values in thier respective reg.
8. Now give start of conv command.
9. Start reading :wink:

I think now you can find answer to your que no 1.

yes for this kind of configuration the pin SDO,SDI,SCK and CS is enough. You can give pulled up high on Reset pin. (ans for que. 2)

Ans for que 3.: Your hardware must have lots of memory space (external memmory)for this and you must have used some "RTC" for this. You scan your reading in real time and you can store its vaue in your memory. You can use this reading leater for your Energy Vs Time graph. (Or you can use a PC interface with your MCU, which receive reading and your GUI will make direct real time graph).


Ans for que 4: Yes we have transmitted data over Zigbee module (microchip MRF24J40A) to remote PC. There we have maintained a real time System. But we dont use power or energy data. We just used current data. (our application was limited to some machine.)
 

I have read the Calibrating the cs5460a from Cirrus but i am still in doubt what to connect to IIN+ and IIN- and VIN+ anv VIN- when i would like to do calibration. What do you connect to these inputs when doing calibration ? I don't think it's clear from the datasheet.

Couple of questions about your code.

Please explain what is happening in the following cases of your code :

I pressume this is to start an Offset calibration correct ?
Code:
EN_CS2();
SPI_MasterTransmit(0xD9); //11011001
DS_CS2();

What are you trying to read here ? The offset ?
Code:
EN_CS2();
x=SPI_Read_data(0x06); 
spi_data_write(0x06,x);
DS_CS2();
What about here ? 0x02 is the Ign current gain ?
Code:
EN_CS2();
x=SPI_Read_data(0x02);
spi_data_write(0x02,x);
DS_CS2();
Here ? I thougt it was the Calibration control but it does not seem so.
Code:
EN_CS2();
SPI_MasterTransmit(0xDD);
DS_CS2();
Here ?
Code:
EN_CS2();
x=SPI_Read_data(0x22);
spi_data_write(0x22,x);
DS_CS2();

EN_CS2();
x=SPI_Read_data(0x20);
spi_data_write(0x20,x);
DS_CS2();
Now you are doing gain calibration ?
Code:
EN_CS2();
SPI_MasterTransmit(0xDA);
DS_CS2();

Here ?
Code:
EN_CS2();
x=SPI_Read_data(0x08;);
spi_data_write(0x08,x);
DS_CS2();

EN_CS2();
x=SPI_Read_data(0x04);
spi_data_write(0x04,x);
DS_CS2();
 

Dear Donnib,

Please follow this link for your calibration problem https://cirrus.com/en/pubs/appNote/an227rev1.pdf

After that i dont think you have to copy paste my code. you will able to designe your code.

If you see my code carefully, in my code
in SPI_Read_data: SPDR = cData;
and in SPI_data_write: SPDR=command | 0x40;

so if you want to read Voltage channel DC offset reg from cs5460 you will call like:
x=SPI_Read_data(0x06);

and according to datasheet if you want to write some value in Voltage channel DC offset reg you have to give command like
spi_data_write(0x46,x); //where x is some data
see https://www.cirrus.com/en/pubs/proDatasheet/CS5460A_F5.pdf page no 41

but i have make my code like that you dont have to change address of the reg. so you can also try this:
spi_data_write(0x06,x); //where x is some data

this will also write x into Voltage channel dc offset reg.

Dont follow my code it is just for one special application. for calibration your code will be diffrent from mine. You can use my routine in your code. but the sequence of command will be diffrent for you application. In my application there are 5 cs5460, and I have to calibrate each channel in each chip with one source of voltage. so i have done some testing and then i came to one conclusion that:
1. Do DC calibration and wait for 5 sec, now read the DC calibration reg. (IDCoff: 0x02 & VDCoff: 0x06) store into your eeprom or flash you can use this data for next power up
2. Do AC calibration and wait for 12sec, again read the AC calibration reg, (IACoff 0x20 & VACoff: 0x22) and strore it
3. Do Gain calibration and wait for 8sec., again read Gain calibration reg, (Ign 0x04 & Vgn: 0x08) and store it
 

Hi

I want to interface cs5460 with msp430f5529.I initialise the spi of the controller and try to read the default value of the controller but every time i got 0 . Please help me to solve this problem.

/******************************************************************************************************************/

#include <msp430f5529.h>

unsigned char MST_Data,SLV_Data;
unsigned long int total_data=0;
unsigned char temp;
unsigned long int SPI_DATA=0;
/***************************************************************************/
#define RST BIT0
//CS5460A register addresses
#define CS5460A_REG_CONFIG 0x00
#define CS5460A_REG_AIN1_OFFSET 0x02
#define CS5460A_REG_AIN1_GAIN 0x04
#define CS5460A_REG_AIN2_OFFSET 0x06
#define CS5460A_REG_AIN2_GAIN 0x08
#define CS5460A_REG_CYCLE 0x0A
#define CS5460A_REG_PULSE 0x0C
#define CS5460A_REG_CURRENT 0x0E
#define CS5460A_REG_VOLT 0x10
#define CS5460A_REG_POWER 0x12
#define CS5460A_REG_ENERGY 0x14
#define CS5460A_REG_IRMS 0x16
#define CS5460A_REG_VRMS 0x18
#define CS5460A_REG_TBC 0x1A
#define CS5460A_REG_STATUS 0x1E
#define CS5460A_REG_IACOFFSET 0x22
#define CS5460A_REG_VACOFFSET 0x24
#define CS5460A_REG_MASK 0x34
#define CS5460A_REG_CONTROL 0x38
//CS5460A commands
#define CONVERT_CONTINOUS 0xE8
#define CONVERT_ONCE 0xE0
#define CS5460A_SYNC0 0xFE
#define CS5460A_SYNC1 0xFF
#define POWER_UP_HALT 0xA0
#define CAL_AIN1_DC_GAIN 0xCA
#define CAL_AIN1_DC_OFFSET 0xC9
#define CAL_AIN2_DC_GAIN 0xD2
#define CAL_AIN2_DC_OFFSET 0xD1
#define CS5460A_WRITE 0x40
#define CS5460A_READ 0x3E
#define CAL_IV_DC_OFFSET 0xD9

//config data
#define CLOCK_DIVIDER 0x00000001 //VHPF & IHPF ENABLED 0x00000001
#define AIN1_GAIN_10 0x00000000
#define AIN1_GAIN_50 0x00010000
#define SOFT_RESET 0x00000080
#define MASK_NO_INTERRUPTS 0x00800020
#define STATUS_CLR_CRDY 0x00100000
#define STATUS_CLR_DRDY 0x00800000
#define STATUS_TOTAL_REG 0x00800020
#define STATUS_CLR_ALL 0x00FFFFFF
#define CONTROL_DEFAULT 0x00000008 // 0x00000000
#define CURRENT_GAIN_DEFAULT 0x00100000 //org
#define VOLT_GAIN_DEFAULT 0x00100000
#define COMPUTATION_CYCLE 0x00000FA0 //7D0 = 2000 //1000cnt-0x3E8 //400cnt -0x190 //200cnt-0xC8//100cnt-0x64//12ms-15//org
#define TIME_BASE 0x00800000
// #define CONFIG_REG_TOTAL 0x00010001
#define CONFIG_REG_TOTAL 0x00000081
#define CONFIG_OFF_TOTAL 0x001E0000
#define CURRENT_GAIN_SET 0x00012200


/************************************************************************/
void delay(unsigned int ms)
{
unsigned int i;
for(i=0;i<ms;i++)
{
__delay_cycles(1000);
}

}

void spi_init(void)
{
// P1OUT |= 0x02;

P4DIR |= BIT6; //for the use of the cs
P4OUT |= BIT6;
P4OUT &=~BIT6; //make cs low for both read and write cycle
P3SEL |= BIT3+BIT4; // P3.3,4 option select
P2SEL |= BIT7; // P2.7 option select
UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL0 |= UCMST+UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI master
UCA0CTL1 |= +UCCKPH ;

UCA0CTL1 |= UCSSEL_2;//+UCCKPL; // SMCLK
UCA0BR0 = 0x02; // /2
UCA0BR1 = 0; //
UCA0MCTL = 0; // No modulation
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
}
void spi_write(unsigned char reg_add,unsigned long int data)
{
unsigned char data1,data2,data3;

data1=(data &0xff);
data2=(data>>8)&0xff;
data3=(data>>16)&0xff;


__delay_cycles(100);
// while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
// UCA0TXBUF = 0x40; //this is used to indicate for the write operation
__delay_cycles(100);
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = (reg_add |0x40);

while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = data3;

while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = data2;

while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = data1;


}
void spi_wr_byte(unsigned char reg_add)
{

__delay_cycles(100);

while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = reg_add;
__delay_cycles(100);


}


unsigned long int spi_read(unsigned char data)
{
unsigned char total_data1,total_data2,total_data3;
total_data=0;


while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = data;




/*******************************************************/

// while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = 0xff;
/*******************************************************/

while (!(UCA0IFG&UCRXIFG)); // USCI_A0 TX buffer ready?
total_data1=UCA0RXBUF ;
__delay_cycles(4);

/*******************************************************/

// while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF =0xff;
/*******************************************************/

while (!(UCA0IFG&UCRXIFG)); // USCI_A0 TX buffer ready?
total_data2=UCA0RXBUF ;
__delay_cycles(4);

/*******************************************************/

// while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = 0xff;
/*******************************************************/

while (!(UCA0IFG&UCRXIFG)); // USCI_A0 TX buffer ready?
total_data3=UCA0RXBUF ;
__delay_cycles(4);


/*************************************************************/
total_data=total_data1;
total_data=total_data<<8;
total_data |=total_data2;
total_data=total_data<<8;
total_data |=total_data3;
/*************************************************************/
return(total_data);

}
/*************************************************************/
unsigned long int measure_voltage(void)
{


SPI_DATA = spi_read(CS5460A_REG_CONTROL);
return(SPI_DATA);
}

void voltage_check(void)
{
unsigned long int voltage;
__delay_cycles(1000); //its the 0.2 sec delay
voltage = measure_voltage();
voltage = (voltage & 0x00FFFF00);
voltage = (voltage/29); //this is the volatge value must send on the uart


}
void spi_reinitialise(void)
{
spi_wr_byte(CS5460A_SYNC1); // ADC cs 5460 serial port initilization.
spi_wr_byte(CS5460A_SYNC1); // ADC cs 5460 serial port initilization.
spi_wr_byte(CS5460A_SYNC1); // ADC cs 5460 serial port initilization.
spi_wr_byte(CS5460A_SYNC0); // ADC cs 5460 serial port initilization.


}
/**************************************************************************/
void main(void)
{
unsigned long int dummy;
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer
delay(1000);
spi_init();
P2DIR=0xff;
P2OUT |=RST;//make rst


delay(1000);
delay(1000);
delay(1000);
delay(1000);

/************************************************************/

spi_reinitialise(); //send the sequence to open the serial terminal
spi_write(CS5460A_REG_CONFIG,CONFIG_REG_TOTAL);//(CLOCK_DIVIDER|AIN1_GAIN_50)); // adc cs5460 configuration register Fosc/1
spi_reinitialise();
delay(500);
// spi_wr_byte(0xD9);
delay(500);
dummy=spi_read(CS5460A_REG_CONFIG); //want to read this
dummy=1;
delay(500);

/* spi_write(CS5460A_REG_AIN1_OFFSET,CONFIG_OFF_TOTAL); // OFFSET SETTING
spi_write(CS5460A_REG_AIN2_GAIN,CURRENT_GAIN_SET); //GAIN SETTINGS
spi_write(CS5460A_REG_MASK,MASK_NO_INTERRUPTS); // Clear all flags and interrupts in MASK REGISTER.
spi_write(CS5460A_REG_STATUS,STATUS_TOTAL_REG); // Clear all flags/STATUS and interrupts in STATUS REGISTER.
spi_write(CS5460A_REG_CONTROL ,CONTROL_DEFAULT); // control default | SYNC BIT = 1

spi_wr_byte(0xE8); //continues sampling
spi_reinitialise(); //The serial port is resynchronized to byte boundaries by sending three or more consecutive SYNC1 commands
//followed by a SYNC0 command
*/

delay(1000);
delay(1000);
delay(1000);
delay(1000);


/**********************************************************/

while(1)
{

delay(1);
dummy= spi_read(CS5460A_REG_STATUS);
__delay_cycles(1000);
__delay_cycles(1000);


}



}
 

I have interfaced CS5460 with 89v51rd2 and i am getting the rms and instantaneous values and have displayed it on my lcd. I have done the offset and gain calibration too.
Now the problem is that my rms value which i am getting is always the double of instantaneous value.
So now when differential voltage applied is 0mv i am getting 0000 as the reading.
Then when i reach 125 mv the instantaneous voltage beocomes ~4200000 counts but rms goes to 8388608 counts that is full scale. Again when voltage is increased above 125mv the rms reading increases from zero and again when voltage reaches 250mv the rms reading reads 8388607 ie full scale.
On the other hand instantaneous gives proper linearity ie
1) zero counts on 0 mv
2) ~ 4200000 counts on 125 mv ie mid range
3) 8388607 max counts on max voltage ie 250mv.
i need the same linearity with rms values too.

please help
 

Hi mihir,

I have used CS5460A (may be u r also using that instead of CS5460). We had faced same kind of problem using this IC. But as for that much resolution with such cheap rates, may still use it. Now I just wanted to ask the sequence of your calibration. Link for your ref is here:

https://www.cirrus.com/en/pubs/appNote/an227rev1.pdf

This may be help.
 

Hi mihir,

I have used CS5460A (may be u r also using that instead of CS5460). We had faced same kind of problem using this IC. But as for that much resolution with such cheap rates, may still use it. Now I just wanted to ask the sequence of your calibration. Link for your ref is here:

https://www.cirrus.com/en/pubs/appNote/an227rev1.pdf

This may be help.
Dear dhruv please attach the schemetic for interfacing cs5460A with avr microcontroller.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top