Go Down

Topic: Arduino Yun / SPI Problem / Power Measuring CS5463  (Read 10562 times) previous topic - next topic

Blizzart

Hey Guys,
I'm pretty new to the arduino world and I'm currently facing a communication Problem between the Arduino Yun and the CS5463 Measuring IC (Datasheet)

For testing and debugging purposes I am NOT connecting anything to line Voltage and only working with "save low voltage"!
The Arduino Power Outputs (5V VCC and GND) are powering the CS5463 and I connected the pins of the ICSP header to the corresponding SPI pins on the CS5463. (--> schematic below)

Right now I have nothing connected to the VIN and IIN pins, but I am planning on using a 50Hz sinus wave signal with Vrms=700mV coming from a function generator after reducing the the Voltage with two simple resistors. (the CS5463 can measure up to 250mV peak which should be about 170mV RMS).

I do have an Oscilloscope, stable power supply, function generator but I don't have a logic analyzer (but I want to buying on).

I was planning on using the signal provided by the function generator for both Voltage and Current Measuring for the first testing. Later I will carry on to a shunt Resistor for the Current.

I'm having trouble to read and write the registers in order to get the Voltage and Current measurements, that's why i went back to simply write some configurations in the config register and trying to read the data to verify the operation.
I would really appreciate your help and am very grateful for any advice.
If I missed any crucial information about my test setup just let my know and I will try to provide them as quickly as possible.

Thanks a lot!
Felix

Here is my shematic:


Here is my Code:
Code: [Select]

 /*
 CS5463 Single Phase Power Measuring IC

 Circuit:
 CS5463 attached to pins 8, 9, 12, 13:

 
 /*
// CS5463 Register Addresses
// B7 B6 B5 B4 B3 B2 B1 B0
// 0 W/R RA4 RA3 RA2 RA1 RA0 0
// W=1 R=0
Read Write Address
 Config  = 0x0     0x40 0b00000  ; // Configuration
 IDCoff  = 0x2     0x42 0b00001  ; // Current DC Offset
 Ign         = 0x4     0x44 0b00010  ; // Current Gain
 VDCoff      = 0x6     0x46 0b00011  ; // Voltage DC Offset
 Vgn         = 0x8     0x48 0b00100  ; // Voltage Gain
 CycleCount  = 0xA     0x4A 0b00101  ; // Number of A/D conversions used in one computation cycle (N)).
 PulseRateE  = 0xC     0x4C 0b00110  ; // Sets the E1, E2 and E3 energy-to-frequency output pulse rate.
 I           = 0xE     0x4E 0b00111  ; // Instantaneous Current
 V           = 0x10   0x50 0b01000  ; // Instantaneous Voltage
 P           = 0x12   0x52 0b01001  ; // Instantaneous Power
 PActive     = 0x14   0x54 0b01010  ; // Active (Real) Power
 IRMS        = 0x16   0x56 0b01011  ; // RMS Current
 VRMS        = 0x18   0x58 0b01100  ; // RMS Voltage
 Epsilon     = 0x1A   0x5A 0b01101  ; // Ratio of line frequency to output word rate (OWR)
 Poff        = 0x1C   0x5C 0b01110  ; // Power Offset
 Status      = 0x1E   0x5E 0b01111  ; // Status
 IACoff      = 0x20   0x60 0b10000  ; // Current AC (RMS) Offset
 VACoff      = 0x22   0x62 0b10001  ; // Voltage AC (RMS) Offset
 Mode        = 0x24   0x64 0b10010  ; // Operation Mode
 T           = 0x26   0x66 0b10011  ; // Temperature
 QAVG        = 0x28   0x68 0b10100  ; // Average Reactive Power
 Q           = 0x2A   0x6A 0b10101  ; // Instantaneous Reactive Power
 IPeak       = 0x2C   0x6C 0b10110  ; // Peak Current
 VPeak       = 0x2E   0x6E 0b10111  ; // Peak Voltage
 QTrig       = 0x30   0x70 0b11000  ; // Reactive Power calculated from Power Triangle
 PF          = 0x32   0x72 0b11001  ; // Power Factor
 Mask        = 0x34   0x74 0b11010  ; // Interrupt Mask
 S           = 0x36   0x76 0b11011  ; // Apparent Power
 Ctrl        = 0x38   0x78 0b11100  ; // Control
 PH          = 0x3A   0x7A 0b11101  ; // Harmonic Active Power
 PFA         = 0x3C   0x7C 0b11110  ; // Fundamental Active Power
 QF          = 0x3E   0x7E 0b11111  ; // Fundamental Reactive Power / Page


 created 15. September 2015
 
 
 */

// the CS5463 communicates using SPI, so include the library:
#include <SPI.h>



const int CS = 8; // Assign the Chip Select signal to pin 8
const int RESET = 13; // Assign Reset to pin 13

byte H_ByteC;          //High Byte
byte M_ByteC;          //Middle Byte
byte L_ByteC;          //Low Byte

byte Read  = 0B0000000;
byte Write = 0B0100000;
int junk;

void setup() {  

  pinMode(CS, OUTPUT); //initalize the chip select pin;
  pinMode(RESET, OUTPUT); //initalize the RESET pin;

  digitalWrite(CS, HIGH);
  digitalWrite(RESET, HIGH);
  
  delay (100);
  
  
 //Create a serial connection to display the data on the terminal.  
  Serial.begin(9600);
  
  //start the SPI library;
  SPI.begin();
  
    SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(8);

digitalWrite(RESET, LOW);
 delay (100);
 digitalWrite(RESET, HIGH);
delay (100);


digitalWrite(CS, LOW); //Chip select to low to initialise comms with CS5463

//Set Config register
 
SPI.transfer(0x40);
SPI.transfer(0x34);  //3 bytes of data to set 24bits of config register        
   SPI.transfer(0xC);    
   SPI.transfer(0x34);
    
digitalWrite(CS, HIGH);  //Chip select to low to disable comms with CS5463  
}


void loop()
{
digitalWrite(CS, LOW);
SPI.transfer(Read);
SPI.transfer(0x0);             //Read the Instantaneous Power Register                                
H_ByteC = SPI.transfer(0xFF);   //Reads high byte and writes sync1                                      
M_ByteC = SPI.transfer(0xFF);   //Reads middle byte and writes sync1                                    
L_ByteC = SPI.transfer(0xFF);   //Reads low byte and writes sync1                                  
digitalWrite(CS, HIGH);

delay (100);
  

Serial.print("Config: ");
Serial.println(H_ByteC,BIN);
Serial.println(M_ByteC,BIN);
Serial.println(L_ByteC),BIN ;
delay (100);

}



sonnyyu

The URL of Code?

Correct diagram:



...
The Arduino Power Outputs (5V VCC and GND) are powering the CS5463.
...
Deadly wrong!

Missing SPI isolation!

If I were you, cease the project immediately!






-dev

Could you list *all* the connections.  There are separate analog and digital power/ground pins on this device.

Do you have a schematic?

What crystal are you using?

Are you using a SSOP-24 breakout board, or are you using the Eval board?

Do you have an oscilloscope?

Do you have a logic analyzer?

Have you connected anything to VIN or IIN?  This is the safety concern, as there is no electrical isolation in the chip.

You can develop your software with "safe" inputs to VIN and IIN (i.e., true isolated low-voltage/current inputs instead of mains), and then switch to conditioned mains inputs for the final system.  You'd still have to use isolation from the Arduino to something else, like a PC, unless you're using wireless ethernet.  However, you'd always have to disconnect the device from mains to reprogram the Arduino.

Most projects will isolate the CS5463 SPI pins from the Arduino pins: ADuM1200 and Si8441 come to mind.  That would allow you to reprogram the Arduino without disconnecting from the CS5463 from mains, and safely connect the Arduino Serial to your PC for debugging.

You could also use a voltage and current transformer to isolate VIN and IIN from mains, with some distortion in the readings.

There are many safety concerns here, with deadly results.  We don't know your background or who may be guiding your work, hence our questions.

Cheers,
/dev

sonnyyu

...
There are many safety concerns here, with deadly results.  We don't know your background or who may be guiding your work, hence our questions.
...
very nice!




sonnyyu

Plan B:

Get Single Phase Din Rail Energy Meter with RS485 Modbus RTU



US $18.00  / Piece

A lot of them uses CS5463  inside.

Yun/Yun shield  + USB-RS485  adaptor connect with Energy Meter.

You made IOT ( Internet of Things)  Energy Meter.




Blizzart

Thanks a lot for your replies so far!



I soldered the CS5463 to a breakout board and connected everything on a breadboard.
I do know that line voltage is dangerous, that is exactly why I was planning on testing the whole setup with "save low voltage", sorry for not mentioning that.

Here is my shematic:



I do have an Oscilloscope, but I don't have a logic analyzer, I am happy to buy one if you could give me a recommendation.
Right now I have nothing connected to the VIN and IIN pins, but I am planning on using a 50Hz sinus wave signal with Vrms=700mV coming from a function generator after reducing the the Voltage with two simple resistors. (the CS5463 can measure up to 250mV peak which should be about 170mV RMS). EDIT: found a typo in my shematic, its a 4.096MHz oscillator

I was planning on using the signal for both Voltage and Current Measuring for the first testing. Later I will carry on to a shunt Resistor for the Current.

I do know about the requirement for galvanic isolation when i go one step further and do actual Line Voltage and Power measurements but for now I need to verify that the CS5463 with its SPI connection is working and I can receive the correct Values .


Right now I am trying to understand how the register read functions are working and how i can write to the Config register.
Hopefully this will help my to correct my mistakes in the read routine for the calculated measuring values.

Thanks again for your help!
Felix


-dev

Quote
I was planning on testing the whole setup with "safe low voltage"
We're all relieved to hear that!

Is the MODE pin connected?

Regarding the software, I don't think you're reading the "Instantaneous Power" register with this code:

Code: [Select]
SPI.transfer(Read);
SPI.transfer(0x0);            //Read the Instantaneous Power Register
H_ByteC = SPI.transfer(0xFF);  //Reads high byte and writes sync1
M_ByteC = SPI.transfer(0xFF);  //Reads middle byte and writes sync1
L_ByteC = SPI.transfer(0xFF);   //Reads low byte and writes sync1

The problem is that you are sending two bytes (Read, then 0x00) instead of one (00010010 = 0x12).  You have the correct description at the top.

The "P" register is at address 9.  To read register 9, you have to send

Code: [Select]
        SPI.transfer( Read | (9 << 1) ); // LSB "B0" is always zero
H_ByteC = SPI.transfer(0xFF);  //Reads high byte and writes sync1
M_ByteC = SPI.transfer(0xFF);  //Reads middle byte and writes sync1
L_ByteC = SPI.transfer(0xFF);   //Reads low byte and writes sync1

Note how the "9" is shifted left by one bit, and the same byte has B6 clear for Read, and set for Write.  See 5.16.5 (register picture) and Figure 1 (read sequence).    However, you should probably read the Status register first (15).

As far as Logic Analyzers,

  • Spend $10 and get a cheap USB LA that has 8 channels (you need 4 or more).  It is really a 3.3V device, but it can be made to work with 5V (soldering required), and it takes some scary Windows hacking to get the software to work (USB VID/PID shenanigans).  I've done it, but it's not pretty.
  • I was going to suggest USBee ZX, but they went out of business Sep 10!  :(
  • Use a second Arduino as a 4-channel logic analyzer with this.  It requires installing the SUMP client on your PC.  I've never tried it.
  • Spend $110 or more for the fantastic saleae USB LA.  Rock solid, everybody loves 'em.
Anybody else have suggestions?

Cheers,
/dev

Blizzart

Is the MODE pin connected?

Regarding the software, I don't think you're reading the "Instantaneous Power" register with this code:

The problem is that you are sending two bytes (Read, then 0x00) instead of one (00010010 = 0x12).  You have the correct description at the top.
Sorry for the misleading information, there was a copy paste mistake from my main sketch, it should have said: "Read the Config Register" that is why I am sending the 0x00 bit to initialize the read operation and "collect" the bytes with synch1.
I fixed the mistake of sending two read bytes (Read and 0x00).
Right now I am just reading zeros on the high middle and low bit of the config register, though I am expecting (0x34); (0xC); (0x34) because I just set the register to those values.
I will try to check what information the status register will provide me.
I connected the mode pin to pin 9 on my Arduino and pulled it high to initialize auto boot.
Thanks for the advice with the logic analyzers, can you provide more information about that 3,3V to 5V mod? Soldering should not be an issue (I have a fair amount of SMD soldering experience). Considering the price I could still buy a better unit later on if I need the analog inputs or more features.

Here is my updated code:
Code: [Select]

/*
 CS5463 Single Phase Power Measuring IC

 Circuit:
 CS5463 attached to pins 8, 9, 12, 13:

 
 /*
// CS5463 Register Addresses
// B7 B6 B5 B4 B3 B2 B1 B0
// 0 W/R RA4 RA3 RA2 RA1 RA0 0
// W=1 R=0
        Read Write           Address
1 Config    = 0x0     0x40 0b00000  ; // Configuration
2 IDCoff    = 0x2     0x42 0b00001  ; // Current DC Offset
3 Ign         = 0x4     0x44 0b00010  ; // Current Gain
4 VDCoff      = 0x6     0x46 0b00011  ; // Voltage DC Offset
5 Vgn         = 0x8     0x48 0b00100  ; // Voltage Gain
6 CycleCount  = 0xA     0x4A 0b00101  ; // Number of A/D conversions used in one computation cycle (N)).
7 PulseRateE  = 0xC     0x4C 0b00110  ; // Sets the E1, E2 and E3 energy-to-frequency output pulse rate.
8 I           = 0xE     0x4E 0b00111  ; // Instantaneous Current
9 V           = 0x10   0x50 0b01000  ; // Instantaneous Voltage
10 P           = 0x12   0x52 0b01001  ; // Instantaneous Power
11 PActive     = 0x14   0x54 0b01010  ; // Active (Real) Power
12 IRMS        = 0x16   0x56 0b01011  ; // RMS Current
13 VRMS        = 0x18   0x58 0b01100  ; // RMS Voltage
14 Epsilon     = 0x1A   0x5A 0b01101  ; // Ratio of line frequency to output word rate (OWR)
15 Poff        = 0x1C   0x5C 0b01110  ; // Power Offset
16 Status      = 0x1E   0x5E 0b01111  ; // Status
17 IACoff      = 0x20   0x60 0b10000  ; // Current AC (RMS) Offset
18 VACoff      = 0x22   0x62 0b10001  ; // Voltage AC (RMS) Offset
19 Mode        = 0x24   0x64 0b10010  ; // Operation Mode
20 T           = 0x26   0x66 0b10011  ; // Temperature
21 QAVG        = 0x28   0x68 0b10100  ; // Average Reactive Power
22 Q           = 0x2A   0x6A 0b10101  ; // Instantaneous Reactive Power
23 IPeak       = 0x2C   0x6C 0b10110  ; // Peak Current
24 VPeak       = 0x2E   0x6E 0b10111  ; // Peak Voltage
25 QTrig       = 0x30   0x70 0b11000  ; // Reactive Power calculated from Power Triangle
26 PF          = 0x32   0x72 0b11001  ; // Power Factor
27 Mask        = 0x34   0x74 0b11010  ; // Interrupt Mask
28 S           = 0x36   0x76 0b11011  ; // Apparent Power
29 Ctrl        = 0x38   0x78 0b11100  ; // Control
30 PH          = 0x3A   0x7A 0b11101  ; // Harmonic Active Power
31 PFA         = 0x3C   0x7C 0b11110  ; // Fundamental Active Power
32 QF          = 0x3E   0x7E 0b11111  ; // Fundamental Reactive Power / Page


 created 17. September 2015
 
 
 */

// the CS5463 communicates using SPI, so include the library:
#include <SPI.h>



const int CS = 8; // Assign the Chip Select signal to pin 8
const int RESET = 13; // Assign Reset to pin 13
const int MODE = 9; // Assign Mode to pin 9

byte H_ByteC;          //High Byte
byte M_ByteC;          //Middle Byte
byte L_ByteC;          //Low Byte

byte H_ByteV;          //High Byte
byte M_ByteV;          //Middle Byte
byte L_ByteV;          //Low Byte

byte Read  = 0B0000000;
byte Write = 0B0100000;
int junk;

void setup() {   

  pinMode(CS, OUTPUT); //initalize the chip select pin;
  pinMode(RESET, OUTPUT); //initalize the RESET pin;
  pinMode(MODE, OUTPUT); //initialize the MODE pin;

  digitalWrite(CS, HIGH);
  digitalWrite(RESET, HIGH);
  digitalWrite(MODE, HIGH);
 
  delay (100);
 
 
 //Create a serial connection to display the data on the terminal.   
  Serial.begin(9600);
 
  //start the SPI library;
  SPI.begin();
 
    SPI.setBitOrder(MSBFIRST);
 SPI.setClockDivider(8);
 
 digitalWrite(RESET, LOW);
  delay (100);
  digitalWrite(RESET, HIGH);
 delay (100);
 
 
 digitalWrite(CS, LOW); //Chip select to low to initialise comms with CS5463
 
 //Set Config register
 
 SPI.transfer(0x40);
 SPI.transfer(0x34);  //3 bytes of data to set 24bits of config register       
   SPI.transfer(0xC);     
   SPI.transfer(0x34);
   
 digitalWrite(CS, HIGH);  //Chip select to HIGH to disable comms with CS5463 
}


void loop()
{
 digitalWrite(CS, LOW);
 SPI.transfer(0x00);             //Read the Config Register                                 
 H_ByteC = SPI.transfer(0xFF);   //Reads high byte and writes sync1                                     
 M_ByteC = SPI.transfer(0xFF);   //Reads middle byte and writes sync1                                   
 L_ByteC = SPI.transfer(0xFF);   //Reads low byte and writes sync1                                   
 digitalWrite(CS, HIGH);
 
 delay (100);

 digitalWrite(CS, LOW);
 SPI.transfer( Read | (9 << 1 )); //Instantaneous Voltage // LSB "B0" is always zero
 H_ByteV = SPI.transfer(0xFF);   //Reads high byte and writes sync1                                     
 M_ByteV = SPI.transfer(0xFF);   //Reads middle byte and writes sync1                                   
 L_ByteV = SPI.transfer(0xFF);   //Reads low byte and writes sync1
digitalWrite(CS, HIGH);
 
   delay (100);

Serial.print("Config: ");
Serial.println(H_ByteC,BIN);
Serial.println(M_ByteC,BIN);
Serial.println(L_ByteC,BIN) ;
delay (100);

Serial.print("Instantaneous Voltage: ");
Serial.println(H_ByteV,BIN);
Serial.println(M_ByteV,BIN);
Serial.println(L_ByteV,BIN) ;
delay (100);
}



Blizzart

Here my main code if that's for any help, though I would like to figure out how to read and write the config file properly and read the status register before I put it all together and start measuring and reading the calculated values.

sonnyyu

...
3. Eliminate interference from power supply:

Use isolated DC/DC Converter for Arduino Yun only. motor shield use its own DC/DC converter




...
Use isolated (few KV isolated)  DC/DC Converter to separate power supply.


ADUM3151 (ADUM315X)  3.75 kV, Dedicated Isolators for SPI Interfaces








Blizzart

Use isolated (few KV isolated)  DC/DC Converter to separate power supply.


Is that really necessary for my test setup?
I am powering the CS5463 through the Arduino Yun and have no other external source coming in.
Even in my second step I believe that the 0,7V sinus signal should do no harm to the CS5463 or the Arduino Yun.
I do know that I need the isolation as soon as I start doing real measurements and when I am connecting an external power source to my bread board, but for now the Arduino is doing it all.

Cheers

sonnyyu

for  0,7V sinus signal , No
for  line voltage 110/220/240 V AC, Yes

...
I soldered the CS5463 to a breakout board and connected everything on a breadboard.
...
I'm sure you understand breadboard the does not meet safety requirements once at line voltage.




Blizzart

for  0,7V sinus signal , No
for  line voltage 110/220/240 V AC, Yes

I'm sure you understand breadboard the does not meet safety requirements once at line voltage.


Perfect so I can focus on the code for now.
The first test with line Voltage will be on a soldered stripboard, as soon as that works I'll carry on to an actual PCB layout.

-dev

Quote
I connected the mode pin to pin 9 on my Arduino and pulled it high to initialize auto boot.
According to the spec,

Quote
MODE - High, enables the "auto-boot" mode. The mode pin has an internal pull-down resistor.

Section 8. AUTO-BOOT MODE USING E2PROM

In auto-boot mode, the CS5463 downloads the required commands and register data from an external serial E2PROM, allowing the CS5463 to begin performing energy measurements.
So... I don't think you want auto-boot mode.  Your schematic does not show an EEPROM.  This is really for letting the CS5463 configure itself, without any SPI commands from a host.  It will pull the configuration from the EEPROM and start running by itself.  You should have the MODE pin floating or tied to ground.

Quote
can you provide more information about that 3,3V to 5V mod?
There are a few ways to do it... You can replace the internal 5V-intolerant buffers with a 5V-tolerant part (some SMD soldering), or you can make an external voltage divider array.  I chose the latter.  That's the HW side.

For the SW, you also have to download some Cypress tools to modify a few bytes inside the cheapie LA.  That lets it be recognized by the Windows USB drivers for the LA software.  Of course, you have to modify some Windows INF files first before the Cypress tools will recognize the cheapie. :P

If you want to try it, go ahead and place your order, 'cuz it'll take a week to get to you.  I'll write up the step-by-step process in the meantime.  The reviews for the cheapie on DX.com point to all the information, but I'll gather it up into one place.

You can do some debugging with the oscilloscope.  Hook it to the MISO line to see what the CS5463 is sending, or to the MOSI line to see what your arduino is sending.  If you have two channels, do both.

Cheers,
/dev

Blizzart

According to the spec,
So... I don't think you want auto-boot mode.  Your schematic does not show an EEPROM.  This is really for letting the CS5463 configure itself, without any SPI commands from a host.  It will pull the configuration from the EEPROM and start running by itself.  You should have the MODE pin floating or tied to ground.

I did as you said and tied the mode pin to ground.
Now I am getting results from the CS5463 back but its still not the expected config values:
Code: [Select]

Config: 11111111
11111111
11111100
Config: 11111111
11111111
0
Config: 11111111
11111111
11110000
Config: 11111111
11111111
0
Config: 11111111
11111111
11111100
Config: 11111111
11111111
11110000
Config: 11111111
11111111
11000000
Config: 11111111
11111111
11000000
Config: 11111111
11111111
0
Config: 11111111
11111110
0
Config: 11111111
11111111
11110000
Config: 11111111
11111111
11111100
Config: 11111111
11111111
11111100
Config: 11111111
11111111
11111111
Config: 11111111
11111111
11111111
Config: 11111111
11111111
11110000
Config: 11111111
11111111
0



I am expecting :
Code: [Select]

Config:110100
1100
110100
Config:110100
1100
110100

and so on

Could that be a timing issue of the SPI Bus or is there still something wrong with me read and write routine?

Cheers

Go Up