SPI network problems.

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all

I've spent many hours now searching the forums for this topic but I cannot find anything useful. If someone knows any useful threads please, can you give me the link? Thanks.

Now, let's go to the problem:

I have a project in which is planned to use the SPI communications protocol to manage several (6 up to now) motion control circuits by sending instructions to them by means of another master circuit, connected to the PC.

All circuits have an AVR: the motion control ones have ATMega16's configured as SPI slaves and the master circuit has an ATMega16 configured as the SPI master. All of the circuits are connected to the same buses (all of the MISO lines together, the SCK lines together and the MOSI lines together). Individual slave's SS pins are connected by means of a cable to different PORTC (could be any IO port!) pin to allow the master to select them when desired.

I tested this kind of connection with one master and two slaves in a Protoboard (blasphemy, you will say... :wink:!) and it worked fine, but in the PCB version it doesn't work, or works intermitently. My guesses are that:

1) There's noise because of the connection between circuits. Slave circuits are connected to master by means of a 8-line ribbon cable that carries the signals:
- SKC, MISO, MOSI, SS
- 5VCC
- 12VCC
- GND
- An RC oscillator signal used by an L297 (stepper motor indexer/controller IC) to synchronize to the other L297's in the rest of the slave circuits, whose frequency is approximately 20kHz.
Electricians out there! Does the fact that the 5V logic signal's ground and the 12V power signal's ground are connected together matters? Should I separate or isolate them? How?

2) There's noise in the buses because there's only one slave circuit connected, and the pins in the master circuit intented to connect the rest of the slave circuits are unconnected now. What should I connect to them if not used? I suppose the High-Z state of the slaves could fix this problem if they were connected, but I still don't have their PCBs ready.

Both guesses are based on electrical "noise". I thought about it because of the behavior of both master and slave circuits in operation:

- Slave circuit is programmed to toggle an LED every time it receives data, in the SPI receive complete interrupt, and it either doesn't toggle or toggle even if I don't send any data. In fact, it sometimes toggle the LED if I put my hand close (not touching) the ribbon cable!!!!

- After many unsuccessful tries with a dedicated program in the master, I adapted the application note AVR303 (SPI-UART gateway) to compile it under WinAVR and for the ATMega16 target, and added a command to control the PORTC pins (remember that my slaves' SS lines are connected to this port?). When I run the program, using Hyperterminal on the PC side, it runs strangely, sending the prompt several times, or reseting the AVR, but, important to note, this behavior only happens when I connect the stepper motor in my slave circuit, which is always running to test it.

I have considerable experience as a programmer, in both the PC and in the AVR [i]but I'm a newbie in PCB design[/i]. I know I'm always prone to errors and in fact I'm aware we all make mistakes even in simple things from time to time, but I'm pretty sure the program, at least this simple testing program, is correctly configured, so I think the problem is in the hardware. But is good to have someone else to check your code, so here are the pertinent parts.

In the slave:

Quote:
static void avr_init(void) { // Initialize device here. DDRA = 0x00; PORTA = 0xFF; DDRC = DDRD = 0xFF; DDRB = _BV(MISO); #ifdef UART_ENABLED UCR = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); UBRR = 0x0C; set_8N1_frame(); #endif SPCR = _BV(SPIE) | _BV(SPE) | 0x00; // Fck/4 /* Step_Frequency = 8e6 / (2 * Presc * OCR0) [steps/s]*/ frequency = 39; TIFR = _BV(TOV0) | _BV(OCF0); TIMSK = _BV(OCIE0); TCNT0 = 0; OCR0 = frequency; TCCR0 = _BV(WGM01) | PRESCALER; // CTC mode TIFR |= _BV(OCF2) | _BV(TOV2); TIMSK |= _BV(OCIE2); TCNT2 = 0; OCR2 = 255; TCCR2 = _BV(WGM21) | _BV(CS22) | _BV(CS21) | _BV(CS20); // CK/1024 } SIGNAL(SIG_SPI) { unsigned char temp; temp = SPDR; // Read slave's content switch(temp) { case '+': // Increase steps/s rate frequency-= FREQ_INC; break; case '-': // Decrease steps/s rate frequency+= FREQ_INC; break; case 'r': case 'R': temp = (~PORTC) & _BV(CW_CCW); PORTC &= ~_BV(CW_CCW); PORTC |= temp; break; case 0: // Note this is number zero, not character zero!!!! TURN_OFF_TIMER(); TIFR = _BV(TOV0) | _BV(OCF0); TCNT0 = 0x00; // Reset count break; case 1: // See above TURN_ON_TIMER(); break; } OCR0 = frequency; temp = (~PORTC) & _BV(OK_LED); PORTC &= ~_BV(OK_LED); PORTC |= temp; }

And in the master:

Quote:
#define MOSI PB5 #define SS PB4 #define SCK PB7 #define SLAVE5 PC1 #define SLAVE4 PC2 #define SLAVE3 PC3 #define SLAVE2 PC4 #define SLAVE1 PC5 #define SLAVE0 PC6 #define ALLSLAVES (_BV(SLAVE0) | _BV(SLAVE1) | _BV(SLAVE2) | _BV(SLAVE3) | _BV(SLAVE4) | _BV(SLAVE5)) volatile int16_t CURRENT_SLAVE = SLAVE0; static void avr_init(void) { // Initialize device here. UCR = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); UBRR = 0x0C; set_8N1_frame(); DDRA = DDRC = 0xFF; PORTC = 0xFF; // Deselect all slaves DDRB = _BV(MOSI) | _BV(SS) | _BV(SCK); /* SS is set as an output to avoid an accidental switching of the MSTR bit in SPCR */ SPCR = _BV(SPIE) | _BV(SPE) | _BV(SPR1) | _BV(SPR0); // Fck/128 SPCR |= _BV(MSTR); } SIGNAL(SIG_UART_RECV) { static unsigned char temp; temp = UDR; switch(temp) { case '0': CURRENT_SLAVE = SLAVE0; break; case '1': CURRENT_SLAVE = SLAVE1; break; case '2': CURRENT_SLAVE = SLAVE2; break; case '3': CURRENT_SLAVE = SLAVE3; break; case '4': CURRENT_SLAVE = SLAVE4; break; case '5': CURRENT_SLAVE = SLAVE5; break; case 'E': case 'e': UDR = ENCODER_AND_SENSORS; return; default: // Let the slaves process every other byte PORTC &= ~_BV(CURRENT_SLAVE); SPDR = temp; // Transmit the byte to the slaves. break; } UDR = temp; } SIGNAL(SIG_SPI) { unsigned char temp; temp = SPDR; // Read data shifted from the slave's SPDR ENCODER_AND_SENSORS = temp; PORTC |= _BV(CURRENT_SLAVE); }

In the near future, it's desired to program a high level protocol to allow bidirectional comm. between the nodes in the network (master to one slave, master to several slaves, slave to slave, etc.), but for now just master to individual slave transmisions are needed.

I've ridden about the twi interface in the forums and in the datasheet, and it seems to be a much more suitable network protocol (interface), but I cannot use it now because of some time constraints in the deadline of the project (it's simply not affordable to redesign everything now, though I want to do it soon).

Does anyone see errors in the code?
Does anyone have a suggestion about the circuit connection?

Oh! I almost forget. In circuit design tutorials I've ridden about "high frequency" effects (increased impedance, transmision line behaviors, etc.) but, in practice, what's the practical "limit" (number) that separates between high and low frequencies? I just don't know if the 8Mhz of my cirtuit (and SPI freq. of up to Fosc/4 = 2 Mhz or Fosc/2 = 4Mhz) is a high enough frequency to take into account this effects.

Is a too long post, but I hope someone can help me.

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's a debug algo for 1 channel.... repeat for all channels... write a little debug menu on the master. Make menu item 1 send UUUUU out the spi to channel 1 till kbhit(). Make slave 1 output anything it gets in the spi to the uart. You ought to be able to see clock and data heading out the MOSI and SCK on the master, and you ought to see UUU coming out the uart on the slave. If you get something other than UUUs or nothing chase it down from the master to the slave.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Bob. I have something like that in a couple of ways:

1) a Led connected to the slave toggles when anything is received via the SPI
2) the motor controlled in the slave card changes its operation (increases/decreases speed, switch direction, turn on/off) depending of the command received via SPI.
3) the SPI-USART gateway application displays a message on the PC when SPI transmision is done: "0xdd sent, receive=0xdd", where 'd' is an Hex digit

In one of those rare ocassions where transmission do takes place (without modifying the SPI code), all three "indicators" work as expected, but the real problem is this, communication between master and slave cards occurs intermittently.

I've checked my code over and over and I cannot find a problem there (could you be so kind as to check it, please?), so I suppose the problem is in the hardware. Could a connection like this work properly?

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Remind me (us) once more about power supply, ground, length of spi cables, bypass caps, xtal speed and spi speed..... does error rate get better when you slow the spi down as slow as it will go (0x53)?

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
it sometimes toggle the LED if I put my hand close (not touching) the ribbon cable!

This kind of jumps off the page. I'll let the EEs here say what this really means, but
I've seen this sort of thing when my ground connections were goofy.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Power supply: 200W switching power supply 115V@60Hz (rescued from an old computer). Outputs:
+5V - 20A
+12V - 8A
-5V - 0.3A
-12V - 0.3A

Connection between master and slave cards is made via 8-line ribbon cables, whose lines are:
- +5V
- +12V
- GND
- MISO
- MOSI
- SCK
- PincXX (in master's circuit), SS pin (in slave's circuit)
- Synchronizated oscillator (chopper rate, to be more exact) running at 20kHz
5V-ground and 12V-ground are connected together in the master circuit.

No bypass caps (What are these for? I've heard a little about them, but I don't know how to use them)

The lenght of cables is between 5 and 10 cm (2 to 5 inch.)

Crystal osc. frequency for the AVR's is 8Mhz (all fuses are correctly set to accept an external crystal).

SPI speed was originally set to Fosc/4 (2Mhz), but I've tried even the lowest speed and the result is the same intermitent behavior. In the SPI-USART Gateway I can set the SPI speed as desired on the fly.

Current drawn by the motor is about 1.5A. The motor is connected following the L297's application note recommendation (see attachment, please). The motor is an stepper bipolar one.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What other info. could be useful?

The original PCB wasn't designed by me and I still don't have its schematic (I know the PCB was "designed" in Protel99 without an schematic, I don't know why). I'm trying to redesign it but, since my (still unfinished) job is programming of the controllers, I haven't found enough time to do it.

Quote:

I've ridden about the twi interface in the forums and in the datasheet, and it seems to be a much more suitable network protocol (interface), but I cannot use it now because of some time constraints in the deadline of the project (it's simply not affordable to redesign everything now, though I want to do it soon)

It's not only because time constraints, but also because of what I said above that I'm not switching to TWI yet. I *need* the final design to be in SPI, but I guess if I can find enough time to design the circuit by myself, it could be rewarding to use TWI. But do you, TWI users, think it would be better to learn to use TWI now?

Any suggestions about how the three SPI busses (SCK, MOSI, MISO) should be connected? I mean, types of cable (instead of the ribbon cable), AWG sizes, twisted pairs, to send in different-isolated sets the power lines and the signal lines, etc., ..everything that could make the communication reliable enough (in addition to a software protocol).

I've seen in the drawing of TWI bus interconection (see attachment) that the bus lines are pulled up to VCC by means of a discrete resistor (one for each line). What is this for? How it works? Could something like that be useful for the SPI network?

Quote:

I've seen this sort of thing when my ground connections were goofy.

The connections were checked simply for continuity with a digital multimeter (and they all were supposedly right). How should I check it to be sure they're well connected?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had many problems runing stepper motors from the same power supply than the uC. Even if they're drived by 12V and the uC by 5V from a linear regulator that also takes power from 12V. Noise, spikes and transients are very common wiht motors, and even worse with switched power supplies. Had you tried with a diferent power supply? I strongly recommend you to put the bypass capacitors (10nF to 100nF) at each power pin pair of every IC in the board, and also, to increase the capacity of the electrolytic capacitors on the board. I had worked a lot with PCB's designed by students (I was in charge of the prototyping machine at the university) for switched mode power supplies, and also some stepper motors and DC motors, and I learn a lot about power planes. If you don't have experience with this, most probably you have problems with grounding and bypassing. So pleas, bypass all IC's (one or more capacitors won't increase the price too much), and place a big (and open loop) ground plane.

Guillem.

Guillem.
"Common sense is the least common of the senses" Anonymous.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Guillem,

I haven't tried another type of power supply. We choose a computer power supply because of its very stable voltage and high current supply (if we drive all 6 motors at 1A, the output of our power supply we'll be roughly sufficient). Could it be useful to use a dedicated (PC type) power supply for logic and another for power connections (12V)? To follow a previous post, is it good or harmful to connect 5V and 12 grounds?

Can you please explain me what's an "open loop" ground plane and where to find comprehensive info. about power planes in general?

Should I also connect a bypass cap between the AVCC-AGND and AVref and AGND?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your problem is almost certainly due to ground bounce.
Supplying the 12v to your motor boards via a ribbon cable is not a good idea as standard ribbon cable is only rated for 1A.
The resistance of the cable will introduce voltage drops meaning that ground at one end of the cable is at a different level, causing the symptoms you describe.

The simplest way to test is to power your motor driver boards with two thickish wires directly from the power supply.

Yes you should decouple AVcc and ARef.

Hope this helps,

Jim

Your message here - reasonable rates.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My intuition says 'too much juice down the ribbon cable'. #22 ribbon cable is rated about 100ma per conductor... How about get a 16 pin ribbon cable and run 3 or 4 pins for 5v and gnd? Test: if it runs with just the leds and no motors , and takes a poop when you hook up the motor, I'm right.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks to all. I'll try this and post about the results.

One more question, an EE here told me to use optoisolators and separate the circuits (power and logic ones), and even to use different power sources (one for the logic and another for the power) because the switching power supply causes problems in the power stage. While this sounds somehow convincent, I'd like to know someone else' opinion about it. Although I can isolate the signals between the L297(logic) and the L298(power), how could I isolate the analog signal of the sensing resistors (a voltage used to regulate current chopping in the motor). Is circuit isolation really needed? Power and ground planes are needed?