Author Topic: Weird problem with nonsensical received SPI data  (Read 4801 times)

0 Members and 1 Guest are viewing this topic.

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Weird problem with nonsensical received SPI data
« on: April 05, 2017, 05:15:55 pm »
I've got a weird problem with an SPI triple half-bridge driver IC that I can't find the cause of. I'm talking to it with an Arduino (ATmega328P), but not using the Arduino SPI library (although the problem does occur when using that too).

The problem is this: when I have it hooked up using an I/O pin for Chip Select that's not the AVR's SS pin (PB2), the first time (since reset) I try to talk to the chip I get seemingly nonsense status output that doesn't reflect what's actually happening (the chip actually performs as expected, regardless of what the status data says it's doing). All further communication with the chip works perfectly fine.

Some details on the chip: On each SPI transfer, the driver chip takes an input 16-bit control word, and outputs a 16-bit status word. The control word has bits for which outputs to enable, whether to shut down on error conditions, as well as a bit that instructs it clear any previous status flags. The output status word has bits indicating error conditions, the state of outputs, and an over-temp warning. Accordingly, my method of communication is as follows:

1. Transfer a control word with the 'status reset' flag on. Ignore the output status.
2. Wait a few hundred microseconds.
3. Transfer the same control word again, but with status reset flag unset.
4. Read the output status.

I have my code dumping some debug info showing what is being transmitted and received. Here's an example of what I see when the problem occurs:

Code: [Select]
===> Control input word: 1110000000001101
[15] Overvoltage Lockout: ON
[14] Underload Shutdown: ON
[13] Overcurrent Shutdown: ON
[6] HS Switch 3: OFF
[5] LS Switch 3: OFF
[4] HS Switch 2: OFF
[3] LS Switch 2: ON
[2] HS Switch 1: ON
[1] LS Switch 1: OFF
[0] Status Register Reset: ON
===> Control input word: 1110000000001100
[15] Overvoltage Lockout: ON
[14] Underload Shutdown: ON
[13] Overcurrent Shutdown: ON
[6] HS Switch 3: OFF
[5] LS Switch 3: OFF
[4] HS Switch 2: OFF
[3] LS Switch 2: ON
[2] HS Switch 1: ON
[1] LS Switch 1: OFF
[0] Status Register Reset: OFF
<=== Status output word: 1110000000001101
[15] Supply Voltage Fault: ON
[14] Underload / Open Circuit: ON
[13] Overload / Short Circuit: ON
[6] HS Switch 3: OFF
[5] LS Switch 3: OFF
[4] HS Switch 2: OFF
[3] LS Switch 2: ON
[2] HS Switch 1: ON
[1] LS Switch 1: OFF
[0] Overtemperature Prewarning: ON

As you can see, I get back status showing that all fault/warning flags are on, but also that the commanded outputs are still on, which should be impossible if those faults are really occurring. What also confirms that this is nonsense data is that if I have no power supply voltage (separate from logic supply) turned on, it normally flags a "supply voltage fault" and keeps all outputs off, but in the problem scenario, it still tells me that outputs are on as commanded, when it patently will never do that!

I've eliminated the following as causes:

- My SPI code, as problem also occurs when using the Arduino SPI library.
- Bugs in the function I'm using to print out the output status.
- The specific chip - swapped for another one, same issue.
- The period between asserting the chip's 'enable' line before SPI communication (in case, I dunno, it's not 'waking up' properly) - added a few ms delay, still problem.

Another oddity I discovered is when I have two driver chips, A & B, hooked up in parallel on the SPI bus - with A's CS on SS/PB2 and B's CS on, say, PB0. If I communicate with B first followed by A, I get the problem with B's status output. But if I reverse that order - A then B - then B's status output is fine.

So, the problem appears to be related to whether the chip's CS line is on the AVR's SS/PB2 pin or not, but also whether first SPI communication is with a device that does have CS controlled by SS/PB2.

I'm flummoxed. |O :-//

And I wish I had a proper multi-channel scope with SPI serial decode, so that I could at least determine whether this problem is perhaps some kind of register/memory issue on the AVR only, by verifying what is actually going over the MISO wire is the same as what is presented on SPDR in the micro. :(
 

Online MK14

  • Super Contributor
  • ***
  • Posts: 4539
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #1 on: April 05, 2017, 05:55:44 pm »
when I have it hooked up using an I/O pin for Chip Select that's not the AVR's SS pin (PB2)

One possible thing to look at...

Have you compared the waveform on a scope between using the SS pin (PB2) and PB0, using a suitable synchronizing trigger ?

It sounds like you need to capture the two above traces SEPARATELY (i.e. 2 different runs, one with SS and the other using PB0, keeping everything else the same as far as practicable) and compare them.
E.g. are the timings different or something ?

N.b. Make sure you do this for the first (problematic) SPI transfer.
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: Weird problem with nonsensical received SPI data
« Reply #2 on: April 05, 2017, 06:39:17 pm »
There are lots of opportunities to screw this up (ETA: I have done all of them).  MSB vs LSB first is one opportunity.  CPOL and CPHA are important.  Raising CS' too soon after stuffing the last byte/word in the data register is another.  Reading the data sent back as the command was transmitted MIGHT be another.  I usually shift out all 1's when I want to read a status register that I selected during a previous write operation.

The thing is, we don't have the datasheet for your driver, we can't see your code, at best all we can do is write down some of the gotcha's and you have probably already worked through all of them.

When I want to see what SPI is sending from the master, I write a short loop of code that repeats the transmission over and over.  Same data every time.  I can see this on a scope without decoding.  I trigger the scope on CS'.  You can extend this to a couple of transactions if they are close enough together to fit on one screen.  In code, set the return value to all 1's just before reading the data register to make sure you are reading anything at all.
« Last Edit: April 05, 2017, 06:50:46 pm by rstofer »
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #3 on: April 05, 2017, 07:57:27 pm »
Have you compared the waveform on a scope between using the SS pin (PB2) and PB0, using a suitable synchronizing trigger ?

It sounds like you need to capture the two above traces SEPARATELY (i.e. 2 different runs, one with SS and the other using PB0, keeping everything else the same as far as practicable) and compare them.
E.g. are the timings different or something ?

N.b. Make sure you do this for the first (problematic) SPI transfer.

I wish I could. Don't have a multi-channel scope nor with external trigger. :( I did have a look at CS on both SS and PB0, but didn't see anything funny going on.

Hmm... A logic analyser would help here, would it not? I seem to recall there are some ways of using an Arduino as a basic one. Perhaps I could rig up a second Arduino to do that, and I suppose that might at least get me a handle on timing.

There are lots of opportunities to screw this up (ETA: I have done all of them).  MSB vs LSB first is one opportunity.  CPOL and CPHA are important.  Raising CS' too soon after stuffing the last byte/word in the data register is another.  Reading the data sent back as the command was transmitted MIGHT be another.  I usually shift out all 1's when I want to read a status register that I selected during a previous write operation.

No, it's not anything to do with how I have SPI set up. I have the correct bit order, polarity and phase. I mentioned earlier that overall everything works just fine - it's just the erroneous output data from the first round of communication with the device that's problematic. I suppose I could try adding a delay between making the SPI transfer and raising CS.

This driver doesn't have multiple registers that can be selected. Data clocked in goes into the control register, and the status register's data is clocked out at the same time.

The thing is, we don't have the datasheet for your driver, we can't see your code, at best all we can do is write down some of the gotcha's and you have probably already worked through all of them.

Oops, I totally forgot to mention which driver chip it is. :-[ It's an Infineon TLE6208-3G.

I can post my code if it'll help.
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #4 on: April 05, 2017, 08:12:38 pm »
Oh, by the way, I forgot to also mention that SPI clock speed has no bearing on the matter. Problem happens whether it's 1MHz or 125 KHz.
 

Online MK14

  • Super Contributor
  • ***
  • Posts: 4539
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #5 on: April 05, 2017, 08:21:32 pm »
It makes it harder or a lot harder if you have no decent way of seeing the signals, that are generated. They could be electrically funny or have the wrong logic values, or even subtleties in the timing. Because debugging is often finding out or seeing the differences between what you THINK is/should/must be happening and what is happening in PRACTICE.
It can give vital (even if tiny) clues, which help you pinpoint what the problem is.

A real long shot, but have you got an initial delay (if needed) ?

From the datasheet.

Quote
SPI-Interface
Delay Time from Stand-by to Data In/Power on Reset
Setup time tset – – 100 µs

I've only had a relatively quick glance at the datasheet, so could easily be mistaken.

The schematics and code, might make you more likely to get useful help, for this.
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #6 on: April 05, 2017, 08:51:52 pm »
A real long shot, but have you got an initial delay (if needed) ?

From the datasheet.

Quote
SPI-Interface
Delay Time from Stand-by to Data In/Power on Reset
Setup time tset – – 100 µs

Yeah, tried that already. I mentioned it in my first post. I put a few milliseconds delay between switching the enable/inhibit pin high and switching CS low to start the transfer. Didn't make any difference. I might give it another go to make doubly sure.

Here's my code:

Code: [Select]
/****** tle6208-3g_test.ino ******/

#include "spi_master.h"

#define SPI_MOSI_PIN 11
#define SPI_MISO_PIN 12
#define SPI_SCK_PIN 13
#define SPI_CS_PIN 8 // 10
#define INHIBIT_PIN 9

#define TLE62083G_CTRL_OVLO 15
#define TLE62083G_CTRL_ULSD 14
#define TLE62083G_CTRL_OCSD 13
#define TLE62083G_CTRL_HS3 6
#define TLE62083G_CTRL_LS3 5
#define TLE62083G_CTRL_HS2 4
#define TLE62083G_CTRL_LS2 3
#define TLE62083G_CTRL_HS1 2
#define TLE62083G_CTRL_LS1 1
#define TLE62083G_CTRL_SRR 0

#define TLE62083G_STAT_PSF 15
#define TLE62083G_STAT_UL 14
#define TLE62083G_STAT_OL 13
#define TLE62083G_STAT_HS3 6
#define TLE62083G_STAT_LS3 5
#define TLE62083G_STAT_HS2 4
#define TLE62083G_STAT_LS2 3
#define TLE62083G_STAT_HS1 2
#define TLE62083G_STAT_LS1 1
#define TLE62083G_STAT_TW 0

void setup() {
pinMode(SPI_CS_PIN, OUTPUT);
pinMode(INHIBIT_PIN, OUTPUT);

Serial.begin(115200);
Serial.println(F("TLE6208-3G SPI TEST"));
Serial.println(F("-------------------"));

spi_init(1000000, SPI_LSB_FIRST, SPI_MODE_1);
}

void loop() {
digitalWrite(INHIBIT_PIN, HIGH);

updateDriver(_BV(TLE62083G_CTRL_HS1) | _BV(TLE62083G_CTRL_LS2), SPI_CS_PIN);
delay(2000);
updateDriver(0, SPI_CS_PIN);
delay(2000);
updateDriver(_BV(TLE62083G_CTRL_LS1) | _BV(TLE62083G_CTRL_HS2), SPI_CS_PIN);
delay(2000);
updateDriver(0, SPI_CS_PIN);
delay(2000);

digitalWrite(INHIBIT_PIN, LOW);

delay(5000);
}

uint16_t updateDriver(uint16_t input, const uint8_t csPin) {
uint16_t buf;

input |= (_BV(TLE62083G_CTRL_SRR) | _BV(TLE62083G_CTRL_OCSD) | _BV(TLE62083G_CTRL_ULSD) | _BV(TLE62083G_CTRL_OVLO));

printControlWord(input);

buf = input;
digitalWrite(csPin, LOW);
spi_transfer_buf(&buf, sizeof(buf));
digitalWrite(csPin, HIGH);

delayMicroseconds(500);

input &= ~(_BV(TLE62083G_CTRL_SRR));

printControlWord(input);

buf = input;
digitalWrite(csPin, LOW);
spi_transfer_buf(&buf, sizeof(buf));
digitalWrite(csPin, HIGH);

printStatusWord(buf);

if(!controlStatusMatch(input, buf)) {
Serial.println(F("    ERROR! Control versus status switch states do not match!"));
}

return buf;
}

void printControlWord(const uint16_t ctrl) {
Serial.print(F("    ===> Control input word: "));
Serial.println(ctrl, BIN);
Serial.print(F("    [15] Overvoltage Lockout: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_OVLO)) ? F("ON") : F("OFF"));
Serial.print(F("    [14] Underload Shutdown: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_ULSD)) ? F("ON") : F("OFF"));
Serial.print(F("    [13] Overcurrent Shutdown: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_OCSD)) ? F("ON") : F("OFF"));
Serial.print(F("    [6] HS Switch 3: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_HS3)) ? F("ON") : F("OFF"));
Serial.print(F("    [5] LS Switch 3: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_LS3)) ? F("ON") : F("OFF"));
Serial.print(F("    [4] HS Switch 2: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_HS2)) ? F("ON") : F("OFF"));
Serial.print(F("    [3] LS Switch 2: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_LS2)) ? F("ON") : F("OFF"));
Serial.print(F("    [2] HS Switch 1: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_HS1)) ? F("ON") : F("OFF"));
Serial.print(F("    [1] LS Switch 1: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_LS1)) ? F("ON") : F("OFF"));
Serial.print(F("    [0] Status Register Reset: "));
Serial.println((ctrl & _BV(TLE62083G_CTRL_SRR)) ? F("ON") : F("OFF"));
}

void printStatusWord(const uint16_t stat) {
Serial.print(F("    <=== Status output word: "));
Serial.println(stat, BIN);
Serial.print(F("    [15] Supply Voltage Fault: "));
Serial.println((stat & _BV(TLE62083G_STAT_PSF)) ? F("ON") : F("OFF"));
Serial.print(F("    [14] Underload / Open Circuit: "));
Serial.println((stat & _BV(TLE62083G_STAT_UL)) ? F("ON") : F("OFF"));
Serial.print(F("    [13] Overload / Short Circuit: "));
Serial.println((stat & _BV(TLE62083G_STAT_OL)) ? F("ON") : F("OFF"));
Serial.print(F("    [6] HS Switch 3: "));
Serial.println((stat & _BV(TLE62083G_STAT_HS3)) ? F("ON") : F("OFF"));
Serial.print(F("    [5] LS Switch 3: "));
Serial.println((stat & _BV(TLE62083G_STAT_LS3)) ? F("ON") : F("OFF"));
Serial.print(F("    [4] HS Switch 2: "));
Serial.println((stat & _BV(TLE62083G_STAT_HS2)) ? F("ON") : F("OFF"));
Serial.print(F("    [3] LS Switch 2: "));
Serial.println((stat & _BV(TLE62083G_STAT_LS2)) ? F("ON") : F("OFF"));
Serial.print(F("    [2] HS Switch 1: "));
Serial.println((stat & _BV(TLE62083G_STAT_HS1)) ? F("ON") : F("OFF"));
Serial.print(F("    [1] LS Switch 1: "));
Serial.println((stat & _BV(TLE62083G_STAT_LS1)) ? F("ON") : F("OFF"));
Serial.print(F("    [0] Overtemperature Prewarning: "));
Serial.println((stat & _BV(TLE62083G_STAT_TW)) ? F("ON") : F("OFF"));
}

bool controlStatusMatch(uint16_t ctrl, uint16_t stat) {
ctrl &= (_BV(TLE62083G_CTRL_HS3) | _BV(TLE62083G_CTRL_LS3) | _BV(TLE62083G_CTRL_HS2) | _BV(TLE62083G_CTRL_LS2) | _BV(TLE62083G_CTRL_HS1) | _BV(TLE62083G_CTRL_LS1));
stat &= (_BV(TLE62083G_STAT_HS3) | _BV(TLE62083G_STAT_LS3) | _BV(TLE62083G_STAT_HS2) | _BV(TLE62083G_STAT_LS2) | _BV(TLE62083G_STAT_HS1) | _BV(TLE62083G_STAT_LS1));
return ((ctrl ^ stat) == 0);
}

/****** spi_master.h ******/

#ifndef SPI_MASTER_H
#define SPI_MASTER_H

#include <avr/io.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
SPI_MSB_FIRST = 0,
SPI_LSB_FIRST = _BV(DORD)
} spiDataOrder_t;

typedef enum {
SPI_MODE_0 = 0,
SPI_MODE_1 = _BV(CPHA),
SPI_MODE_2 = _BV(CPOL),
SPI_MODE_3 = _BV(CPHA) | _BV(CPOL)
} spiMode_t;

void spi_init(const uint32_t speed, const spiDataOrder_t order, const spiMode_t mode);
uint8_t spi_transfer_byte(const uint8_t data);
void spi_transfer_buf(void *buf, size_t count);

#ifdef __cplusplus
} // extern "C"
#endif

#endif // SPI_MASTER_H

/****** spi_master.c ******/

#include "spi_master.h"

void spi_init(const uint32_t speed, const spiDataOrder_t order, const spiMode_t mode) {
uint8_t clockDiv = 0;

DDRB |= _BV(DDB2);

for(uint8_t i = 2; i <= 128; i *= 2) {
if(speed >= F_CPU / i) break;
clockDiv++;
}

if(clockDiv == 6) clockDiv++;

clockDiv ^= 0x01;

SPCR = _BV(SPE) | order | _BV(MSTR) | mode | (clockDiv >> 1);
SPSR = (clockDiv & 0x01);

SPSR;
SPDR;

DDRB |= _BV(DDB3) | _BV(DDB5);
}

uint8_t spi_transfer_byte(const uint8_t data) {
SPDR = data;
loop_until_bit_is_set(SPSR, SPIF);
return SPDR;
}

void spi_transfer_buf(void *buf, size_t count) {
uint8_t *data;

if(!buf || count == 0) return;

if(bit_is_set(SPCR, DORD)) {
data = (uint8_t *)buf;
do {
*data = spi_transfer_byte(*data);
data++;
} while(--count > 0);
} else {
data = ((uint8_t *)buf) + (count - 1);
do {
*data = spi_transfer_byte(*data);
data--;
} while(--count > 0);
}
}

There were a bunch of comments in there that I've cut out for brevity so this post isn't too long, so I hope it's understandable.
 

Online MK14

  • Super Contributor
  • ***
  • Posts: 4539
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #7 on: April 05, 2017, 09:19:45 pm »
So this seems to set buf = 0, later in the code, which ...

Quote
updateDriver(0, SPI_CS_PIN);
 delay(2000);
 updateDriver(_BV(TLE62083G_CTRL_LS1) | _BV(TLE62083G_CTRL_HS2), SPI_CS_PIN);
 delay(2000);
 updateDriver(0, SPI_CS_PIN);

then seems to bomb out (as buf is 0)...

Quote
void spi_transfer_buf(void *buf, size_t count) {
 uint8_t *data;

if(!buf || count == 0) return;

Is that correct and what you want it to do ?

tl;dr
I don't easily understand why it returns if it (buf) is zero.
« Last Edit: April 05, 2017, 09:22:33 pm by MK14 »
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #8 on: April 05, 2017, 09:44:43 pm »
Yes, that is correct, because of two things:

a) updateDriver() always adds extra flags, making the value non-zero regardless of what was passed in.
b) That check is for a null pointer. :)
 

Online MK14

  • Super Contributor
  • ***
  • Posts: 4539
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #9 on: April 05, 2017, 09:47:24 pm »
Yes, that is correct, because of two things:

a) updateDriver() always adds extra flags, making the value non-zero regardless of what was passed in.
b) That check is for a null pointer. :)

I missed (a), making me a fool. But at least I did not miss the fact that buf was being accessed as an address rather than its value, making me a total fool.
Then there is (b)  :-[
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: Weird problem with nonsensical received SPI data
« Reply #10 on: April 05, 2017, 09:49:45 pm »

This driver doesn't have multiple registers that can be selected. Data clocked in goes into the control register, and the status register's data is clocked out at the same time.


I'm sure you have this covered but, strictly speaking, the status received from the first transmission is the result of the previous command and a previous command hasn't been sent.  The status received during transmission of command 'n' is the result of command 'n-1'.  Figure 3 in the datasheet.

 

Offline obiwanjacobi

  • Frequent Contributor
  • **
  • Posts: 988
  • Country: nl
  • What's this yippee-yayoh pin you talk about!?
    • Marctronix Blog
Re: Weird problem with nonsensical received SPI data
« Reply #11 on: April 06, 2017, 05:55:07 am »
It can be interesting to look at the state of the SPI pins of the sender when it resets.

I had a similar issue and my SPI pins toggled a bit during initialization which made the receiver (Slave in my case) think that communication was in progress. Setting the SS high on a Slave will also clear the data - you could use that to sync up bytes or groups of bytes (if you have multi-byte messages).

Playing with the order of setting SPI pins to input/output and initializing the control register fixed it. Can't remember what the order was exactly but that is easy enough to find out.

A master SPI can use any pins for SS to one or more of its Slaves. Configure the SS pin as output on the master and it will not be looked at by the SPI hardware. If SS on the Master is an input, you have to make sure it is high, because when it is low, the master mode is cleared from the control reg turning the SPI into slave mode. On a Slave SPI you have to use the dedicated SS pin afaict, for it is integral part of the handshake of communicating data between master and slave.

Hope it helps.
[2c]
Arduino Template Library | Zalt Z80 Computer
Wrong code should not compile!
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #12 on: April 06, 2017, 01:28:14 pm »
I'm sure you have this covered but, strictly speaking, the status received from the first transmission is the result of the previous command and a previous command hasn't been sent.  The status received during transmission of command 'n' is the result of command 'n-1'.  Figure 3 in the datasheet.

Yep, sure have. That's why I'm doing the following, as I already mentioned in my first post:

Quote
1. Transfer a control word with the 'status reset' flag on. Ignore the output status.
2. Wait a few hundred microseconds.
3. Transfer the same control word again, but with status reset flag unset.
4. Read the output status.

I suppose technically speaking, it's nonsense status output being returned from the second command, albeit the first communication 'cycle'.

A master SPI can use any pins for SS to one or more of its Slaves. Configure the SS pin as output on the master and it will not be looked at by the SPI hardware. If SS on the Master is an input, you have to make sure it is high, because when it is low, the master mode is cleared from the control reg turning the SPI into slave mode. On a Slave SPI you have to use the dedicated SS pin afaict, for it is integral part of the handshake of communicating data between master and slave.

Oh yes, I figured out the hard way that SS has to be an output before you can configure it as a master. ::) I initially had my spi_init() function setting SS to an output at the same time as for MOSI and SCK at the end of the function, but found that nothing worked at all. I had to load my code into Atmel Studio and run it through the emulator to realise that the MSTR bit wasn't taking hold. Didn't figure out what was going on until I more carefully read the ATmega datasheet. :palm:

Looks like I really need to get at least a logic analyser so I can see if there's odd things going on with the SPI lines during initialisation, and also verifying the data on the wire. I think my earlier idea of running an Arduino as one might not be too helpful, as it appears you really need something like a Mega (2560) to have enough memory to capture a lot of samples, which I don't have. Was just looking on eBay and Saleae clones are very cheap, so I might take a punt on one of those.
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #13 on: April 07, 2017, 03:02:28 pm »
As I want to be controlling two of these drivers, I thought I would give the daisy-chain topology a go and see if that exhibits a similar problem.



So, as per the diagram from the datasheet above, I hooked a pair of drivers up (let's call them A & B) as follows: Arduino MOSI to A's DI pin; A's DO pin to B's DI pin; B's DO pin to Arduino MISO pin; shared SCK and a single shared CS. I updated my code accordingly to transfer 32 bits - data for B followed by A.

But I think there must be something I'm misunderstanding or missing about how this SPI topology is supposed to work. There are virtually no details in the datasheet about daisy-chaining apart from statements that it is supported and the diagram above.

Are my assumptions about how it works wrong? I figured that it would work as follows:

1. CS pulled low.
2. Master shifts out B's 16-bit control word to device A.
3. Device A shifts out its 16-bits of status word to device B.
4. Device B shifts out its 16-bits of status word to Master.
5. Master shifts out A's 16-bit control word to device A.
6. Device A shifts out (i.e. overflows) its currently-held 16-bit control word (i.e. B's control) to device B.
7. Device B shifts out (i.e. overflows) its currently-held 16-bit control word (i.e. A's status) to Master.
8. CS pulled high; A & B latch their respective control words.

But all I ever get back as status output is zero for both. :-//

This is the updated code I was using. When calling updateDrivers(), I was just passing the same flags as before for both A and B.

Code: [Select]
void updateDrivers(uint16_t inputA, uint16_t inputB) {
uint16_t buf[2];

inputA |= (_BV(TLE62083G_CTRL_SRR) | _BV(TLE62083G_CTRL_OCSD) | _BV(TLE62083G_CTRL_ULSD) | _BV(TLE62083G_CTRL_OVLO));
inputB |= (_BV(TLE62083G_CTRL_SRR) | _BV(TLE62083G_CTRL_OCSD) | _BV(TLE62083G_CTRL_ULSD) | _BV(TLE62083G_CTRL_OVLO));

printControlWord(inputA);
printControlWord(inputB);

buf[0] = inputB;
buf[1] = inputA;

digitalWrite(SPI_CS_PIN, LOW);
spi_transfer_buf(buf, sizeof(buf));
digitalWrite(SPI_CS_PIN, HIGH);

delayMicroseconds(500);

inputA &= ~(_BV(TLE62083G_CTRL_SRR));
inputB &= ~(_BV(TLE62083G_CTRL_SRR));

printControlWord(inputA);
printControlWord(inputB);

buf[0] = inputB;
buf[1] = inputA;

digitalWrite(SPI_CS_PIN, LOW);
spi_transfer_buf(buf, sizeof(buf));
digitalWrite(SPI_CS_PIN, HIGH);

printStatusWord(buf[1]);
printStatusWord(buf[0]);
}
 

Online MK14

  • Super Contributor
  • ***
  • Posts: 4539
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #14 on: April 07, 2017, 03:55:25 pm »
If you can't obtain a scope (or logic analyzer), then you could connect LEDs, to some of the pin(s). Such as the main serial line(s), and temporarily put in delays (e.g. 1 second, faster if you are up to it), between each bit transmission.
Then you could make sure the serial data is at least going in to the chip(s) and see if any bits are trying to come out.

Alternatively spend 10 hours staring and reading through the entire project, repeatedly  :)

Obviously something is wrong, but without clues, you are playing a HUGE guessing game.

If the data goes in ok but comes out all zeros, you know it is probably wired up wrong.

If no data goes in then you have messed up your software.

If data goes in and comes out in non-zero patterns, then it is the software again.

tl;dr
It would be nice to know what is going on, externally.
 

Online MK14

  • Super Contributor
  • ***
  • Posts: 4539
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #15 on: April 07, 2017, 04:18:02 pm »
To explain it again in different words...

You probably have either got a problem with the software or one or more wires is now wired up wrong, when you introduced the extra device(s).

If we/you knew which (hardware/software), it would save a lot of time.

Also a scope or LED, would tell us if the serial wire between the two half-H bridge devices, is showing 1's and 0's or not.
 

Offline HwAoRrDkTopic starter

  • Super Contributor
  • ***
  • Posts: 1477
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #16 on: April 07, 2017, 04:42:48 pm »
Oh, don't get me wrong, I fully understand I need to find out exactly what's going on at the wire level in order to address my initial problem. I've ordered a cheap USB logic analyser, but that won't be here for a while, so in the meantime I thought I'd change tack and try something else.

I triple-checked my wiring on the daisy-chaining setup, and it seemed to be correct; that, coupled with the fact I'm essentially just guessing about how the software side of the daisy-chaining setup should be, led me to question my assumptions on the fundamentals of it. A third party's opinion on whether my assumptions make sense or not would be highly appreciated. :)
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: Weird problem with nonsensical received SPI data
« Reply #17 on: April 07, 2017, 06:01:30 pm »
Oh, don't get me wrong, I fully understand I need to find out exactly what's going on at the wire level in order to address my initial problem. I've ordered a cheap USB logic analyser, but that won't be here for a while, so in the meantime I thought I'd change tack and try something else.

I triple-checked my wiring on the daisy-chaining setup, and it seemed to be correct; that, coupled with the fact I'm essentially just guessing about how the software side of the daisy-chaining setup should be, led me to question my assumptions on the fundamentals of it. A third party's opinion on whether my assumptions make sense or not would be highly appreciated. :)

Your logic seems consistent with the datasheet.  Lower the CS' on both devices, shift out as a single 32 bit transaction, the 2 16 bit commands while simultaneously reading the 2 16 bit status words.  Then raise CS' on both devices.
 

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 627
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: Weird problem with nonsensical received SPI data
« Reply #18 on: April 08, 2017, 05:38:08 am »
As I want to be controlling two of these drivers, I thought I would give the daisy-chain topology a go and see if that exhibits a similar problem.
I wouldn't try other topologies before sorting out the original problem. Better to go simpler than more complex. And don't just try random things until it works - understand why it's failing.

Quote from: MK14
If you can't obtain a scope (or logic analyzer), then you could connect LEDs, to some of the pin(s). Such as the main serial line(s), and temporarily put in delays (e.g. 1 second, faster if you are up to it), between each bit transmission.
Good advice. Better yet, wait for a trigger (eg. push-button) before each clock so you can 'single step' the SPI and see exactly what is happening at a pace you control. 
 
 

Offline CJay

  • Super Contributor
  • ***
  • Posts: 4136
  • Country: gb
Re: Weird problem with nonsensical received SPI data
« Reply #19 on: April 08, 2017, 07:53:22 am »
Oh, by the way, I forgot to also mention that SPI clock speed has no bearing on the matter. Problem happens whether it's 1MHz or 125 KHz.

I haven't analysed the problem you're experiencing but I've been playing with Sigrok and one of the really cheap Cypress based Chinese logic analysers over the past few days, they work really nicely with the DS1307 (100KHz I2C) and a TM1638 based display that's being run as fast as I can (PIC 18F4550 and it's immensely useful for a quick visual indication of comms speed)

I reckon they're a really good investment (£7) if you don't need the advanced features of a 'real' LA.

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf