LowPowerLab Forum

Hardware support => Moteino => Topic started by: henry hung on November 08, 2014, 10:07:29 PM

Title: Connecting Moteino with another SPI device
Post by: henry hung on November 08, 2014, 10:07:29 PM
Hi, I'm relative new in SPI communication, I wish to connect a SPI interface card reader(RC522) with Moteino, I believe that I have to assign different SS to card reader, I should also try to see if the SPI setting are the same between these 2devices.
Is there any similar project as been done, where I can reference to?
Title: Re: Connecting Moteino with another SPI device
Post by: Felix on November 09, 2014, 05:03:48 PM
You need to use a different CS signal.
You also need to handle the SPI communication to your device completely separately on every "transaction".
By transaction I mean every access to your device.
The library or code you use should make sure the SPI settings are what your device expects every single time.
You can look at the RFM69 library how this is accomplished to talk to the RFM69 transceiver, start by looking at the following functions:

RFM69::select()
RFM69::unselect()
Title: Re: Connecting Moteino with another SPI device(RC522 RFID)
Post by: henry hung on December 16, 2014, 10:04:31 PM
Hi, Felix,

I tried the unselect() function, but it's protected, I do not want to change it to unprotected. So, I first init radio, then digitalWrite(10, HIGH), so that I can init RFID and read RFID. it works.

I'm wondering while RFID is working, if RFM69 send a interrupt, would library will select() radio again? should I stop th interrupt wne working on RFID?
Title: Re: Connecting Moteino with another SPI device
Post by: Felix on December 16, 2014, 11:52:41 PM
Don't worry about the library, it does the selecting and interrupting in a smart way. You should never have to touch select() and unselect(). These functions and the SPI of the RFM should not interfere with other SPI devices. If you disable interrupts you might lose packets.
Title: Re: Connecting Moteino with another SPI device
Post by: henry hung on January 06, 2015, 08:37:39 AM
Hi, Felix,

I'm using a MFRC522 card reader together with Moteino. RC522 has SS on D7, and reset on D6,  separated from RF and SPI flash.I'm using a MFRC522 lib.
my goal is to get some info from RF, read card from RC522, and send out card data through RF.
I did a test on switching RF and card reader, first the gateway send out a messge with constant time interval. Node is looping between RF(to receive data) and RC522 to read card(if any)
for init, I first set high D7, then init 69HW. then set D10 high and init RC522
for loop, I set D10 high and D7 low to read card, then set D7 high, D10 low to change to radio.
It's working, only I need to reinit RC522 every time I switch to it.

I'm new to coding, I wonder if you can help me on these:
1.if this is what you mean by switch "transaction"? 
2. is this correct to switch SPI by setting SS high to keep that slave device out of SPI bus?
3. if during card reader section(when I set D10 high and D7 low), RF issue a INT on D2, what would happen with current lib? Or what is the right way to do to make it wait ?
Title: Re: Connecting Moteino with another SPI device
Post by: Felix on January 06, 2015, 09:03:42 AM
SPI transactions attempt to keep every device safely separated from other SPI transactions on the same bus.
The RFM69 lib does that by disabling interrupts from other sources and saving the SPI registers before each transaction and restoring them when done.
If you need to talk to other SPI devices like your card, ensure you use a different CS for each new device, and if there is an interrupt issue you can disable interrupts (including the INT0) which will resume once you are done with your own SPI communications.
SS must be kept as an OUTPUT if you want to use the SPI bus in master mode. If you have a RFM69 installed it must be also HIGH. The RFM69 library handles all that for you, nothing else you need to do.
Title: Re: Connecting Moteino with another SPI device
Post by: TomWS on January 06, 2015, 12:03:16 PM
Quote from: henry hung on January 06, 2015, 08:37:39 AM
Hi, Felix,

I'm using a MFRC522 card reader together with Moteino. RC522 has SS on D7, and reset on D6,  separated from RF and SPI flash.I'm using a MFRC522 lib.
my goal is to get some info from RF, read card from RC522, and send out card data through RF.
I did a test on switching RF and card reader, first the gateway send out a messge with constant time interval. Node is looping between RF(to receive data) and RC522 to read card(if any)
for init, I first set high D7, then init 69HW. then set D10 high and init RC522
for loop, I set D10 high and D7 low to read card, then set D7 high, D10 low to change to radio.
It's working, only I need to reinit RC522 every time I switch to it.

I'm new to coding, I wonder if you can help me on these:
1.if this is what you mean by switch "transaction"? 
2. is this correct to switch SPI by setting SS high to keep that slave device out of SPI bus?
3. if during card reader section(when I set D10 high and D7 low), RF issue a INT on D2, what would happen with current lib? Or what is the right way to do to make it wait ?
Henry,
as you have noticed, you need to make sure the SPI settings, including clock frequency and SS pin match your hardware.  What Felix is suggesting is that the code used in the RFM69 library is a good model for keeping each SPI device working properly without stomping on each other.  In this case, you need to examine the MFRC522 library to see how that code selects/deselects the SPI device.
Here is a generic version I use for a device I have that requires the bus speed to be changed to 1MHz:

//==========================================================================
//
//==========================================================================
/// Select the transceiver
void select() {
  noInterrupts();     // YOU NEED TO DO THIS!  This keeps the RFM69 from interrupting your 'transaction'
  //save current SPI settings
  _SPCR = SPCR;     // THIS saves the current settings so you can restore them when you're done
  _SPSR = SPSR;
  //set MY DEVICE SPI settings
  SPI.setDataMode(SPI_MODE0);   // SPI Transfer mode
  SPI.setBitOrder(LSBFIRST);         
  SPI.setClockDivider(SPI_CLOCK_DIV16);   // SELECT 1MHz transfer (on a 16MHz processor)
  digitalWrite(GW_SELECT_PIN, LOW);
}


//==========================================================================
//
//==========================================================================
/// UNselect the transceiver chip
void unselect() {
  digitalWrite(GW_SELECT_PIN, HIGH);
  //restore SPI settings to what they were before talking to MY DEVICE
  SPCR = _SPCR;
  SPSR = _SPSR;
  interrupts();    // re-enable interrupts
}




Looking at your code, DON'T DO THIS:

        digitalWrite(10, HIGH);        // you should not be playing with pin 10!
        digitalWrite(SS_PIN,LOW);  // don't enable your SPI device SS except using a mydevice.select() call.


same here, DON'T DO THIS:

    digitalWrite(SS_PIN,HIGH);// keep RC522 out of SPI
    digitalWrite(10, LOW);// enable RF    ESPECIALLY DON'T DO THIS!!!!!!!

Tom
Title: Re: Connecting Moteino with another SPI device
Post by: henry hung on January 06, 2015, 07:01:23 PM
Thank you Felix and Tom.

I should leave D10 (SS of RF69) handled by library, and then check out the card reader library, if it has similar function as select and unselect where the interrupt is arranged.
Title: Re: Connecting Moteino with another SPI device
Post by: TomWS on January 06, 2015, 08:39:45 PM
Quote from: henry hung on January 06, 2015, 07:01:23 PM
Thank you Felix and Tom.

I should leave D10 (SS of RF69) handled by library, and then check out the card reader library, if it has similar function as select and unselect where the interrupt is arranged.
Henry,
if the library assumes that you are managing the slave select and is simply doing SPI transfers, then you can 'wrapper' their methods that use SPI transfers with your own select()...unselect()functions.
I don't have time to look at the device library you're using, but this would be an appropriate approach if there are only a few methods that actually do SPItransfers.

Tom
PS: Yes, definitely leave D10 alone.  Felix manages that well enough  ;)