HELP NEEDED PARALLEL COMMUNICATION

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

i am writing a code in which i have to send two register values from one board to another board using one port. the pins of the port will each carry one bit of the register so in essence it is parallel communication.

I have to send two register values consecutively so how should the code be such that the receiving board is sure to get both registers separately and properly. Its kinda urgent so any help as soon as possible will be appreciated. I am using an arduino nano board with an ATMEGA328P and require the code in assembly language as i need really high speed.

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

RajashreeRavi wrote:
i am writing a code...

Stop!

 

Before you start to write any code you need to design your interface. Think about how this is going to work:

 

  • You will need extra pins in addition to the data pins to control the transfer.
  • Do you need any feedback to confirm that data has been accepted?
  • Do you need error detection/correction?
  • What, exactly, does "really high speed" mean? Put some numbers to it!
  • etc, etc, ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am writing a code to read number of pulses from an encoder connected to a dc motor that will be running at close to 4000rpm. The encoder outputs 1336 pulses per revolution. I need to send data every 1msec to a central board. I dont need feedback or error detection/correction for now. The isr to send data in the sending board needs to be short so that i dont miss out on the main reading. 

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

So now you can work out your numbers for the speed requirement, and think about the extra pins to control the transfer.

 

You'll soon be ready to start coding it ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

can u help me out with how to control the transfer. what exactly should i do to make sure both values are indvidually registered by the receiving board. I tried out a code in which two registers are being sent every 0.5sec but the receiver only reads one of the two values. The other one is lost no matter how much delay i give between the two instructions. I also tried sending a standard value like 0xff between register values which when detected indicate a change in the register that is being sent. but here it gets stuck in a loop and never detects 0xff and even if it did oxff might also be a data value so data can be mistaken for the flag indicating register change. What should i do now?

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

How about looking at how some other parallel interfaces work?

 

Think about how the "reader" will know that there is valid data to be read ...

 

Again: Think first - code later!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One would think that the uart or spi would be a simpler solution in this instance.

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

One would think that the uart or spi would be a simpler solution in this instance.

+1

 

But if you insist on parallel then (if you are old enough) think back to how a Centronics printer interface worked. Basically there were 9 not 8 wires connected. As well as the 8 for the data you have an additional wire called "strobe". You put the 8 bits to be transferred into the output of the sender then he briefly takes strobe high-low-high (or low-high-low if you prefer). The receiver sees the transition on the strobe line (low-high or high-low) as an indication that a "new byte is ready" and reads and stores that byte. Rinse and repeat.

 

If you want the receiver can have yet another line ("Ack") that it can wiggle to say "received and understood" but I've worked on computer designs that implemented Centronics and ignored the Ack - so you don't really need it.

 

Here are some pretty pictures to look at:

 

 

https://www.google.co.uk/search?...

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

thanks a lot. I worked a similar protocol out and i wrote the code for it

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

You haven't said the nature of the information that needs to be transferred.  At your given max speeds, there is about 90000 pulses per second.  If this is a position value, then it will very quickly get into a 32-bit position value.  If rate, then how wide does it need to be?

 

90000 edges per second is doable with an AVR8, quadrature decoding.  (so budget 10us?)  Is your input a simple pulse and you need to handle just one pulse?  Or quadrature, where you need to handle x2 or x4?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

I had to transmit net angle with respect to reference in number of pulses. So maximum value could be 1336 (0x538) and that will come within a 16 bit register. I am using a quadrature encoder so x2. I am giving the code that i am using right now. It seems to work fine on a whole but i am worried that it is not fast enough to catch all the pulses. I am checking for a high-low edge on one input line and then checking the other input line for direction and accordingly either increasing or decreasing my net number of pulses and direction of rotation. I have to send data every 1 ms. Is there any way to do that parallely without disturbing the main routine coz when the motor is running this will disrupt edge detection.  I am using atmega328P on an arduino nano board. 

 

.include "m328Pdef.inc"
.org 0
rjmp start
.org OC1Aaddr
rjmp send;

start:
    ldi r22,0xd3;        pd4 and pd5 for sending signal,pd2 and pd3 for encoder
    out DDRD,r22;
    ldi r22,0xff;
    out DDRC,r22;
    ldi r22,(1<<WGM12) | (5<< CS10)
    sts TCCR1B,r22;
    ldi r22,(1<< OCIE1A);
    sts TIMSK1,r22;
`    ldi r22,0x00;
    sts OCR1AH,r22;
    ldi r22,0x15;             overflow every 1ms
    sts OCR1AL,r22;        timer interrupt setup
    sei;
    ldi r28,0x10;        pd4 sends signal,pd5 receives ack
    ldi r24,0x00;
    ldi r25,0x00;
    ldi r21,0x00;
a:
    in r22,PIND;
    sbrs r22,2;        pd2 checked for high
    rjmp a;

a1:    
    in r22,PIND;
    sbrc r22,2;        pd2 checked if low
    rjmp a1;

a2:
    sbrs r22,3;        pd3 checked if high
    rjmp cw;

ccw:
    mov r17,r24;
    or r17,r25;
    breq initial;
    cpi r23,'+'
    breq dec0;
    rjmp inc0;
initial:
    ldi r23,'-';
    rjmp inc0;

cw:
    mov r17,r24;
    or r17,r25;
    breq initial1;
    cpi r23,'-'
    breq dec0
    rjmp inc0
initial1:
    ldi r23,'+';
    rjmp inc0;

inc0:        
    cpi r25,0x05;
    brne inc1;
    cpi r24,0x38;
    brne inc1;
    ldi r24,0x00;
    ldi r25,0x00;
inc1:
    adiw r25:r24,1;
    rjmp a;

 

dec0:
    cpi r24,0x00;
    brne dec1;
    cpi r25,0x00;
    brne dec1;
    ldi r24,0x38;
    ldi r25,0x05;
dec1:
    sbiw r25:r24,1;
    rjmp a;

 

send:
    in r27,SREG;
    out PORTD,r28     sending ready signal
    out PORTC,r24;     sending first data
ack:
    in r26,PIND;
    sbrs r26,5;           waiting for ack
    rjmp ack;
    out PORTD,r21;    sending ready signal
    out PORTC,r25;     sending second data
    out SREG,r27;
    reti;

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

Why do you need to use an interrupt? You could simply poll the uart as part of your main loop and not have to worry about losing counts.
That is some of the nastiest human written asm i've seen. I'd expect that from a disassembler and then i'd put comments on it. How do you keep track of register usage?

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

If i poll, every time i count a pulse i check for this condition too which is a waste of time in my main routine. I have used timer interrupt here but mostly i will be using pin change interrupts later i think. I have a mental list of what register i use and when i write i make sure different registers are used. 

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

How much time is it going to waste? Not as much time compared to when the interrupt fires and it stacks some registers.
As for keeping a mental list of what registers you've used, unless you're a savant, this technique is not going to scale too well. When you need to look at the code again in 6 months - will you remember?

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

My question now is tht is there any way in which i could run the transmission part of the routine parallelly so tht it doesnt disturb my pulse counting? Irrespective of whether i do polling or use an isr while transmission is going on i am going to miss a pulse if it comes then. Is there any way to prevent tht

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

If you want something to not be disturbed ("higher priority") then do it in an interrupt. Put the rest of the stuff for which the timing doesn't matter in the main loop and it'll just plod along when it gets a chance.

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

Cliff, if he's running flat out counting pulses, then the interrupt will cause seemingly random count misses.
Raj, we still don't know what sort of speed the pulses are. As for running in 'parallel', the AVR has a finite amount of cycles available. If you're using all of these for counting, then whether you use interrupts or polling is not going to solve your problem. If you know your maximum input speed and you calculate the time your code takes for one count you can see how many spare cpu cycles you have left.

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

I am trying the same program but with pin change interrupt. I am trying to see if the basic transmission is working fine and i am sending two empty registers as value for it. When i look at the serial monitor i get random value like 0x3d,0x14 and 0x3f,etc. When i remove the pwm setup and change it to timer interrupt it works fine. Why is this happening? I am attaching the sender and receiver code here.

Attachment(s): 

Last Edited: Mon. Jun 29, 2015 - 02:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Apart from having to do mental gymnastics to make sense of your code, you seem to assume things happen immediately. There are hidden delays that you don't take account of that mean it might work sometimes but not others. You need to draw a timing diagram at take into account the port output delay, propagation delay and input setup times as well as the instruction execution times. A few minutes doing this will tell you if you want time to run backwards.
If you write an isr, give it a label with isr in it. Makes reading the code easier rather than 'a'
How about using cbi/sbi instructions?

Last Edited: Mon. Jun 29, 2015 - 11:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i tried to isolate where i am going wrong so i rewrote the whole code keeping in mind what you said about delays. I wrote a code that would act when it sees a change on PB0 and then go to ISR. After it enters the isr it will send a data ready signal on PD5 and then place the data on PORTC. It will then wait till it receives an acknowledge signal from the receiver to clear the ready signal and exit the isr. In the receiver i toggle PB0 at constant time intervals using an timer overflow isr. after it sends the signal on PB0 it will wait till it receives the data ready signal and then it will receives the data on PORTC. It will then send an acknowledge signal that it clears eventually. It then prints the result that it has received. 

 

The whole code works as such wrt the parallel transmission and pin change interrupt. When i set up pwm on PD6 with timer0 the serial monitor starts to print out gibberish. Why is this happening? I have attached a more hopefully comprehensible code again . 

Attachment(s): 

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

Why do you say dsta ready before you've output the data?

You're using pin change interrupts. Any change on that port will interrupt. Are the other pins on that port floating?
Somehow spi seems much easier and faster.

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

I am giving data ready signal to say that the sender has entered the isr and that data will be ready thereafter.

About the pin change interrupt i have configured the interrupt mask register only for change in pb0 but made all portb pins input. But how is that related to pwm?

My project guide wanted parallel because it is much faster than spi so i am stuck working with it.

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

RajashreeRavi wrote:
My project guide wanted parallel because it is much faster than spi

I think your "project guide" is misguided here.

 

Although, in general, it is true that a parallel interface has the potential to be much faster than a serial one, is is rather more doubtful that any interface bit-banged in software is going to be (much) faster than a proper hardware SPI controller.

 

And, anyhow, if the SPI is fast enough - it is entirely irrelevant that a parallel interface could be faster.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

We come back to the timing diagram - that would give you hard evidence so you can prove which is faster.

Pwm might capacitively couple into floating pins and cause stray interrupts.
You're supposed to output the data first then strobe it. Your receiver is not synchronised to the transmitter so the timing doesn't work out as clean as you might hope. You might also have electrical issues like crosstalk - i have no idea of how it is physically wired.
I'd suggest you get hold of a logic analyser like a salae logic to get a picture of what is really happening. Or a 4chan oscilloscope.

My guess is there is a number of problems that need to be individually solved.

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

In the old days, there were specific peripheral chips for each microprocessor. E.g. a 6520 or 6522 for a 6502 cpu.
These support chips did the handshaking in hardware and raised an interupt for the cpu.
Nowadays, microcontrollers like the AVR do not really support parallel transfers in hardware. As you have seen, you need to do it all by yourself in the ISR(). And you also need to understand the importance of preserving registers and status when using interrupts.
Yes, I think that you can probably do the parallel transfer quite fast. I doubt that you can do it faster than the hardware SPI or even USI.
If your professor is adamant that you do things this way, concentrate on writing your code neatly first. e.g. using SFR_NAMES and BIT_NAMES. And document which registers you are intending to trash and which you want to preserve.

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

david.prentice wrote:
If your professor is adamant that you do things this way...

Then you should be speaking to him (or her) for guidance - after all, you yourself called him/her your "project guide"

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the OP drew up some simple timing diagrams; looked at the potential throughput; compared this with SPI; determined SPI required less hardware and software resource but was almost as fast or faster than 8 bit parallel (OP needs to determine if this is the case); and presented these findings to their Professor they would almost certainly gain significant credit towards their course.  However pointing this out sort of defeats the object....

 

David

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

Perhaps it was a trick question, and that's what the Prof really wanted ...

 

wink

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i changed the pwm output to a different board and now have no problems with transmission except for the really important one of not being able to output pwm. I am using an arduino nano board and atmega328p and i have given the part of code that i wrote below. I am taking pwm output from d6 (timer 0, ocra) but when i checked with a scope i am getting practically 0V from the pin. Am i not getting output because it is a digital pin?

 

   ldi r22,(1<<COM0A1) | (1<<WGM00) | (1<<WGM01);
    sts TCCR0A,r22;
    ldi r22,(1<< CS01);
    sts TCCR0B,r22;            
    ldi r22,128;
    sts OCR0A,r22;        pwm setup mode 7, non-inverted

    ldi r22,(1<<DDD3) | (1<<DDD6) | (1<<DDD5)
    out DDRD,r22;         pwm output from D6

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

I have looked at some timing diagrams before for basic instructions but am not able to quite understand how to draw one for SPI and compare it against what i have already done. Could you give me some pointers or some references that i can look up for it.

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

The datasheet has nice pictures of spi. If we assume the spi clock is 1MHz, that 1us per clock times 8 bits plus one more because thats how it works. 9us per byte.
Instructions take one or two clocks (generally) so you add up the cycles. An oscilloscope helps.

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

thanks. could you help me out with the pwm too?

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

Use mode 3. Using your meter to measure pwm isn't going to give useful results. Use a logic analyser or oscilloscope.

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

When we use SPI, if i configure the receiver as the master and the sender as the slave, will the slave transmit only when the master does too and if so then where do i place the transmit code in the slave for spi. Does spi act like an ISR such that whenever the master starts to transmit this will leave the main program, transmit data and then return to the main program?

 

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

Did you solve your pwm problem?
I would make the sender the master. Does the spi act like an ISR? You're clearly missing some fundamental knowlege. Read the datasheet carefully. In short, the spi is hardware that runs in parallel with the processor. It can interrupt the processor if you want, but in your application that would only slow down the process. Put it this way, the max speed of the spi is half the processor speed. Thus it takes 18 clocks to send and receive 8 bits of data. How many clocks does it take your parallel scheme to do the same thing?

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

When we use SPI, if i configure the receiver as the master and the sender as the slave, will the slave transmit only when the master does too and if so then where do i place the transmit code in the slave for spi.

All SPI transfers involve both ends both sending and receiving a byte. It's not really a question of sender and receiver. Both ends are both sender and receiver. The only difference between a master and a slave is that the master is the one that produces the SCK pulses and is, therefore the only one who can initiate the transfer. You can, if you want, have the slave use some way to notify the master that it has something it needs to transfer and this then triggers the master to write to SPDR and initiate the transfer. Another technique would be to have the master "poll" the slave where it keeps writing SPDR to make a transfer and see if the slave has something useful to deliver.

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

I think i understood the concept somewhat now. In my case where i need to send two bytes from board1(b1) on request from board2(b2) is the following attached code right? I am really confused with where i should place the code for transmission in the slave board(b1). When does the slave go into the piece of code that keeps checking if the transfer is over or not and how do i specify if r24 or r25 should be transmitted according to what i receive from master. 

Attachment(s): 

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

If you use the <> icon in the toolbar when you write a comment you can embed your code - for example:

 

/* master uses spi every 1 sec to send either 1 or 0 to get r25 or r24
respectively. and then it serially prints it out */


.include "m328Pdef.inc"
.org 0x00
rjmp start;
.org OC1Aaddr
rjmp ISR_SPI;
.equ BR=9600
.equ FOSC=16000000
.equ BRS=(FOSC/(16*BR))-1

.MACRO spt   //for serial printing
r: lds r31,UCSR0A;
 sbrs r31,5;
 rjmp r;
rx: sts UDR0,@0;
.ENDMACRO

START: ldi r22,0x18;   
 sts UCSR0B,r22;
 ldi r22,0x06;
 sts UCSR0C,r22;
 ldi r22,high(BRS);
 sts UBRR0H,r22;
 ldi r22,low(BRS);
 sts UBRR0L,r22;  serial setup 
 ldi r22,(1<<WGM12) | (5<< CS10)
 sts TCCR1B,r22;
 ldi r22,(1<< OCIE1A);
 sts TIMSK1,r22;
` ldi r22,0x1e;
 sts OCR1AH,r22;
 ldi r22,0x84;
 sts OCR1AL,r22;  timer interrupt setup
 sei;
 SPI_Init:
 sbi DDRB,DDB3; MOSI as output
 sbi DDRB,DDB5; sck as output
 sbi DDRB,DDB2; ss' as output
 ldi r16,(1<<SPE) | (1<<MSTR) | (1<<SPR0); spi as master, interrupt disabled
 out SPCR,r16
loop:
 rjmp loop; 


ISR_SPI:

 ldi r16,0x01
 out SPDR,r16
Wait:
 lds r17,SPSR
 sbrs r17,7
 rjmp Wait
 in r24,SPDR 
 
    ldi r16,0x00
 out SPDR,r16
Wait1:
 lds r17,SPSR
 sbrs r17,7
 rjmp Wait1
 in r25,SPDR
 
Print:
 ldi r17,'0'
 spt r17
 
 ldi r17,'x'
 spt r17
 
 ldi r17,'0'
 add r17,r25
 spt r17
 
 mov r18,r24
 swap r18
 andi r18,0x0f
 cpi r18,0x0a
 brge char
 ldi r17,'0'
 add r17,r18
 spt r17
 rjmp next
char:
 ldi r17,'7'
 add r17,r18
 spt r17
next:
 mov r18,r24
 andi r18,0x0f
 cpi r18,0x0a
 brge char1
 ldi r17,'0'
 add r17,r18
 spt r17
 rjmp next1
char1:
 ldi r17,'7'
 add r17,r18
 spt r17 
next1:
 ldi r17,'\r'
 spt r17

 ldi r17,'\n'
 spt r17
 reti;   

David

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

These finer details are what you need to figure out. As I said before, I'd have the source of the data be the master - that is the time critical end. The slave end that receives the encoder values is under less stress. There's a number of solutions to your problem. Have the master assert the SS signal. On the slave end this is tied to an interrupt. The master waits an amount of time to allow the slave to respond to the interrupt then sends the two bytes. When the slave receives the two bytes, it returns from the isr. Thus your byte order is preserved.

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

I am really sorry to trouble you but i cant understand what you are trying to say. From what i could understand you are having the master(data source) send a signal to the slave(receiver) to make the slave receive data. But i need it to work the other way around. I need the data source to send only when queried by the receiver. That is why i ended up making the receiver the master to initiate query. If you could please take the time and write a skeleton code it would be very helpful for me.

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

I'd suggest you sit down and solve the problem for yourself. I could write the code, but that means you miss out on a learning opportunity. Nevertheless, you need to design the solution, then write the code. You haven't done the design yet.

From what i understand of your problem, one avr has an encoder connected to it. The avr will keep track of the encoder counts. Another avr will query this for the encoder counts. Since you haven't told us what this encoder is and how fast it will rotate, we don't know if it will even work. You were worried about losing counts. There was mention of sending the encoder counts every millisecond. This seems to have changed.
Write down the unknowns, then prioritise them. Seek to resolve them one by one. Missing encoder counts seems high to me, so seek to answer this first. The answer will dictate how you solve the question of communication.

Last Edited: Sat. Jul 4, 2015 - 12:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the optical quadrature encoder has 1336 pulses per rotation count. The motor runs at close to 14400rpm. The code i have written counts pulses at 2usec rate for every pulse and the pulse rate from encoder is definitely slower than this. Right now i have written the code in such a way that the encoder pulse counting will keep going till by a pin change the board2 will enquire board1 for data and b1 will enter an isr to send data parallely . The only way the encoder counts will be missed right now is when it is in the pin change isr where it sends data to the other board parallely. I am seeking to avoid this too by using spi. I read about spi from some sites and am right now having no clear picture of how the code execution works. Everywhere they have given code for initialisation and then data transmission. But where do i place this code and if i add lines to it will it make a difference?  

 

 .include"m328Pdef.inc"
 .org 0
rjmp start

start:
 SPI_Init:
    sbi DDRB,DDB4;    MISO as output
    cbi DDRB,DDB2;    ss' as input
    cbi PINB,2
    ldi r16,(1<<SPE) | (1<<SPR0);    spi as slave, mode3
    sts SPCR,r16
    ldi r24,0x00
    ldi r25,0x00
SPI_SEND:
    sbrc r18,0
    rjmp next;

    Wait:
    lds r17,SPSR
    sbrs r17,7
    rjmp Wait
    in r18,SPDR
    
    out SPDR,r24;
next:
    out SPDR,r25
    inc r24;
    inc r25;
loop:
    rjmp loop;

 

In the above code when the master calls on the slave will it go to SPI_SEND Label and follow the code or not? Will the comparison of r18 to determine what register needs to be sent happen? I am unable to proceed due to this confusion

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

You're trying to solve two problems at once. This causes your confusion.
First time through ( if we assume r18 is 0) you wait for a spi byte, this loads r18. You then output r24 then don't wait for the spi and output r25. That might work if the timing is perfectly aligned, but very unlikely. You might want to wait for the spi before sending r25.
The slave spi depends on the master - it cannot initiate the transfer.

According to your numbers, you have 1.12us spare. How long will a spi transfer take?

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

I thought I'd throw a bone in here...

 

I built a six-channel quadrature encoder counter using seven AVRs awhile back (yep, seven on one board).  Six Tiny2313s and one 32u4.  It used the hard interrupts on the 2313s to count encoder pulses, and had a parallel bus for dumping the data (32 bits, although it was originally designed for 40 bits, and could be easily upconverted again) out to the "master" AVR, the u4, which then sent it all on via USB.

 

Two things I found out:

 

1) Encoders dither something fierce.  The first thing my interrupt routines had to do was check if anything had changed, and if not, exit.  Yah, the interrupt triggers with something changing, and the first thing my ISR did was see if anything changed...  This fixed a huge spurious count problem.

 

2) More modern AVRs have the ability to toggle a pin by writing to the PINx register.  By starting each data transfer in a known state, my AVRs could simply toggle 'Read' and 'Ready', which made for much simpler code.  The u4 had to have eight pins of bus, two of bus control, and six chip select pins - Fortunately, as a u4, it had lots of pins.  I wound up using ALL the pins on the 2313s.

 

Have fun,

 

S.

 

PS - you NEED shadow registers if you're shipping multi-byte data out that could change in the middle of shipment...  S.