Go Down

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

-dev

Neither your actual nor the expected Config register values match the last code that you posted.  You have to keep us up-to-date with your code.

Did you try just reading the status register?

BTW, You should consider defining some constants or types to make your code more readable.  For example:

Code: [Select]
// page 0 registers
static const uint8_t CONFIG         = 0;
static const uint8_t POWER          = 9; // instantaneous
static const uint8_t POWER_ACTIVE   = 10;
static const uint8_t STATUS         = 15;
static const uint8_t POWER_REACTIVE = 20;
   ...
// page 1 registers
static const uint8_t LOAD_MIN = 1;
   ...

// Write this first to select the "current" register page for successive Read/Write operations
static const uint8_t SELECT_PAGE = 0x1F;


...or with an enum:

Code: [Select]
enum CS5463_register_t {
  CONFIG         = 0,  // page 0 registers
  POWER          = 9,
  POWER_ACTIVE   = 10,
  STATUS         = 15,
  POWER_REACTIVE = 20,
     ...
  LOAD_MIN = 1, // page 1 registers
     ...
  SELECT_PAGE = 0x1F
};

You can define a few, as above, or all the registers.  Then accessing a register becomes:

Code: [Select]
SPI.transfer( Write | (CONFIG<<1) );
   or
SPI.transfer( Read | (CONFIG<<1) );

This will be much easier for you (and us) to understand what you meant to do.

Regarding the CONFIG register, I think you need to review the K value.  It's a divider to produce MCLK from crystal frequency.  While the crystal can be 2.5MHz to 20MHz, the MCLK must be between 2.5MHz and 5MHz (see section 5.12 and 6.1.1).  The config values in CS5463_SPI_V3.0.INO (0x000C00) and your first post (0x340C34) are not valid.

This is a fairly complicated chip, so I also encourage you to re-read the spec from top to bottom, making a note of any configurable item that affects its operation.  By the time you get to the bottom, you will know what the CONFIG register should contain.

Spec reading is something of an art... just accept that you may have to read all of it, every time you have a new question.  You may have ignored a sentence during a previous reading as being "irrelevant", and now you need the information it contains.  Unless you're lucky enough to have a photographic memory, you'll have to read it multiple times.

Cheers,
/dev

ShapeShifter

#16
Sep 18, 2015, 05:12 pm Last Edit: Sep 18, 2015, 05:13 pm by ShapeShifter
This is a fairly complicated chip, so I also encourage you to re-read the spec from top to bottom, making a note of any configurable item that affects its operation.  By the time you get to the bottom, you will know what the CONFIG register should contain.
Many times, the documentation will include a one or two page summary chart of all of the registers: no descriptions, just each register on its own line, with the individual fields shown and blocked out. If they have this, I will print out this page, and have it handy while reading the rest of the spec and the details of the registers. As details and settings become apparent, I write in the required field values on this printout. If the document doesn't have such a summary, like the one for this chip, I will make one.

If you fill in the fields as you are reading the document, by the time you get to the end, you probably have the full register contents figured out.


Quote
Spec reading is something of an art... just accept that you may have to read all of it, every time you have a new question.  You may have ignored a sentence during a previous reading as being "irrelevant", and now you need the information it contains.  Unless you're lucky enough to have a photographic memory, you'll have to read it multiple times.
VERY TRUE! 

You haven't lived until you've wasted days trying to get a programming pod to talk to a new processor chip, only to find that on page 240 of a 2259 page manual is the one and only sentence that indicates a particular pin MUST be pulled high on power up or else it comes up in a bootloader mode that ignores the JTAG port.  :smiley-mad:

And of course, this mostly happens when the customer is looking over your shoulder, wondering why the new board you built for them isn't doing anything...

Blizzart

#17
Sep 23, 2015, 04:25 pm Last Edit: Sep 23, 2015, 06:32 pm by Blizzart
I have been working on the code today and collected all the register addresses in an enum.
I did not understand fully why you split them into a page 0 and a page 1 register, could you please provide an explanation.

I did only write those values to the config register for testing so I could read out those same values to verify a working write and read process.
The default setting for the config register should be (0x000001). I am still not reading those values though.


And here the values the status register provides:
Code: [Select]

Status: 0
0
0
Status: 10000000
0
0
Status: 0
0
0
Status: 10000000
0
0
Status: 0
0
0
Status: 10000000
0
0
Status: 10000000
0
0
Status: 0
0
1
Status: 0
0
0
Status: 0
0
0
Status: 0
0
1
Status: 0
0
0
Status: 0
0
1


  

I did order a small logic analyzer and received it today, this one should work with the Saleae software. Logic Analyzer

-dev

Quote
I did not understand fully why you split [the registers] into a page 0 and a page 1...
See Section 6.  It is divided into three subsections, one for each page.  Why?

In a Read/Write command byte, there are only 5 bits to select a register.  That means you can address 0..31.  Because there are more than 32 registers in this complicated chip, Cirrus had to implement multiple "pages" (see Section 5.15).  The way you select a page is by Writing the Page Register, at address 31.  Having selected the page (0, 1 or 3), all successive Read/Write commands are with respect to that page's list of registers.  Page 0 has 31 registers, Page 1 has 4 registers, and Page 3 has 4 registers, for a total of 40 registers.  The Page Register is a special case, as it "appears" on every page... that's how you switch pages.

Notice how the "No Load Threshold" register is at address 1, just like "Current DC Offset".  They're actually on different pages: Page 1 vs. Page 0.

You start out on Page 0, so unless you need access to one of the 8 other registers, you don't have to mess with doing a Page Register Write before every Page 0 Read/Write.

Quote
And here the values the status register provides:
Code please.  Oops, I see it's attached... I'll take a look

Quote
I did order a small logic analyzer and received it today
The model you purchased has the same input buffer as the cheapie.  It will draw extra current when 5V logic signals are applied to the inputs.  This is definitely a problem on lines that are supposed to float (e.g., OneWire bus), and it may be a problem for the SPI lines.

IIRC, the input buffer, a NXP 74HC245, can end up sinking 5mA on a 5V logic high (~4.7V).  I think that's the max that the CS5463 can drive on a digital output, like the MISO line.  Actually, 5mA is about the total current of the CS5463.  I still suggest replacing the 74HC245 with 74LCX245 (SMD desoldering/soldering), or using a voltage divider on the inputs (much easier).

Here's a plug-in voltage divider I soldered up, using 33K and 56K resistors I had on hand:





The black pin at the bottom is GND.  Tain't pretty, but it does the job.  :P  There is no issue if you use this LA with a 3.3V system.

Cheers,
/dev

-dev

Quote
And here the values the status register provides:

  Status: 0
  0
  0
  Status: 10000000
  0
  0
Actually, those look ok.  See Section 6.1.11.  That high bit is toggling between DRDY and !DRDY as the chip performs conversions.

You commented out the CONFIG read/write, so I have no idea what happened.  You must think I'm Santa Claus, who knows when you are sleeping, and knows when you're awake...  ;)

Cheers,
/dev

Blizzart

Actually, those look ok.  See Section 6.1.11.  That high bit is toggling between DRDY and !DRDY as the chip performs conversions.

You commented out the CONFIG read/write, so I have no idea what happened.  You must think I'm Santa Claus, who knows when you are sleeping, and knows when you're awake...  ;)

Cheers,
/dev
Sounds great that the status register makes sense, I only commented the Config read out in order to see the status values by itself, when i was testing the config register the values where changing after every reading cycle which did not make sense to me, shouldn't they be persistent over time?

Cheers

-dev

Quote
shouldn't [the CONFIG register] be persistent over time?
Yes, it should not change.  However...

To be blunt, we can't trust your interpretation of what you saw.  You must show us the code and the output it produces... together.

After that, you'll need to hook up your LA to confirm that the sketch really sends and receives what it prints.  You may need to attach screen prints of the LA software for us to interpret.

It's all about verification, at many levels.

Blizzart

#22
Sep 28, 2015, 02:19 pm Last Edit: Sep 28, 2015, 04:46 pm by Blizzart
I have done some testing and checked the values that I am sending over SPI.
I observed that the Arduino is sending the correct values to the CS5463, although the CS5463 responds to it with two phrases alternately.
In some cases it responds ([0][0][0][1]) which would be correct for the Config register. The first byte is the response to the register selection and byte 2-4 are my high middle and low byte. This results in a low byte value of 1 on my serial monitor.
The second case however delivers a ([0][128][0][1]) which means that the MSB of the high byte is a logic one instead of the expected logic 0.
I confirmed this behavior with the serial monitor and both the logic analyzer and my oscilloscope. After rebooting the Arduino the CS5463 behaved in the same way.
I lowered the SPI CLK to 1MHz (arduino clock divider=16) but it did not change the behavior.
EDIT: After checking more of the brodcasted bytes I also found the value ([0][128][0][5]) in the config register. There must be something wrong that makes it change over time. Could it be a wrong initialization of the SPI BUS and the CS5463 chip itself?


I attached the code I am using and the pictures of the LA and oscilloscope.
Right now I am rereading the spec sheet to get the correct configuration for measuring a 50Hz sinus wave.


Cheers!
Blizzart

 

-dev



That clock signal looks nasty, but it could be aliasing.  You should zoom in (sample faster) to see how they look.  I'm a little suspicious because there's similar noise on the other lines.  How long are these wires? 

Do you have decoupling bypass caps?  See Figure 18, which shows three.  I don't see any on the schematic.

For now, I think I'd let the MODE pin just float LOW, instead of driving it from the Arduino.

Cheers,
/dev

ShapeShifter

Yes, there looks like a lot of nasty ringing on that clock pulse. It is very much worth it zooming in on them to get a better view. It looks like there are only four clocks per group, where the logic analyzer shows four? It seems like the scope has enough resolution to not be aliasing those pulses, but zooming in would prove that one way or another.

I agree, the noise on the other signals, which are coincident with the clock, makes me suspect long leads and insufficient bulk and/or bypass capacitance at the chip.

Blizzart

#25
Sep 29, 2015, 11:01 am Last Edit: Sep 29, 2015, 02:05 pm by Blizzart
I checked the leads on my oscilloscope and shortened them as much as possible, and made sure that the ground connection is decent.
Then I zoomed in on the clock line and and snapped a couple of pictures for you.




I also measured the SPI pins straight on the arduino with no connection to the CS5463 to provide a reference of the signal.




I added some decoupling caps to the VA+ and VD+ inputs with a capacity of 1uF each. (C1 and C2 in the schematic)



EDIT:
I found a mistake in my code, the WRITE byte in my enum should be 64 instead of 32.
After commenting out the reading of the status register the config register behaves completely normal and I can write values to it and verify them through the read process.
However, when I leave the status read in the code, my config values are still changing.

ShapeShifter

That clock signal looks reasonable. Adding some larger bulk capacitance is usually good, but for bypass caps, larger is not better: smaller caps can better smooth high frequency current changes. Usually 0.1uF or 0.01uF caps are used for bypass caps. The reference schematic uses 0.1uF. I would add some in addition to the caps you have. The larger caps smooth out the slower high current variations, the smaller ones take care of the higher frequency switching variations.

Blizzart

That clock signal looks reasonable. Adding some larger bulk capacitance is usually good, but for bypass caps, larger is not better: smaller caps can better smooth high frequency current changes. Usually 0.1uF or 0.01uF caps are used for bypass caps. The reference schematic uses 0.1uF. I would add some in addition to the caps you have. The larger caps smooth out the slower high current variations, the smaller ones take care of the higher frequency switching variations.
Thanks, for the explanation. I do understand the characteristics and behavior of a capacitor and high frequency signals or spikes on a power line, I added another 0.01uF capacitor for the power inputs.

Blizzart

#28
Sep 29, 2015, 03:22 pm Last Edit: Sep 29, 2015, 03:22 pm by Blizzart
I changed to a new version of code with more register writes.
The writing process seems totally fine in the LA.



I can read out the same register values as long as I only read one register and comment out everything else, as soon as I read the config and status in one sketch or any combinations of two registers the values are changing over time.
Code is attached.

-dev

I agree, those signals look much better!  There should also be a bypass cap on Vref.  That may affect the readings, but doubt it would affect the register contents.

Could I suggest something like this at the end of loop, to pace the output and keep serial interrupts from delaying the SPI transfers?  It keeps the LA traces together a little nicer:

Code: [Select]
  Serial.flush(); // let all the serial TX interrupts finish...

  static uint32_t lastTime = 0; // I would usually put this at file scope and
                                // initialize it to millis() at the end of setup
  while (millis() - lastTime < 1000) // or 2000ms?
    ;
  lastTime = millis();
}

This will make it a little easier to capture, too.

What output do you get when you read any two registers?

There is an IC bit in the status register that indicates an "invalid command" (if IC == 0).  Be sure to check that.

And you're reading too many bytes for VOLTAGE_RMS, CURRENT_RMS, POWER and TEMPERATURE.  Those are 1-byte registers.  Although the spec says

Quote from: Section 5.14
Register writes must be followed by three bytes of data.
Register reads can return up to four bytes of data.
...I can only find one-byte or three-byte registers.  ???

Cheers,
/dev

Go Up