Multi processor project

Discussion in 'Embedded Systems and Microcontrollers' started by KansaiRobot, Jun 23, 2015.

  1. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Hello and thanks for your help.

    I am thinking in rather general terms about my next project. (Which I have to propose in a couple of days) and I was thinking:
    so far I have programmed the PIC18F2550 to control LEDs, Steppers, DC etc.

    What if I want to have several of these PICs as modules controlling a particular process and I want them to communicate with each other ?(In which fashion, master slave or different I dont know yet)

    What to use? SPI, I2C, CAN??? what do you guys recommend?

    This is still a rather general topic so any idea or comment will be greatly welcomed
     
  2. kubeek

    AAC Fanatic!

    Sep 20, 2005
    4,669
    804
    All that will pretty much depend on what the process is. Some will be more suited for a master-slave model, and some for a peer-peer model. Do you have any particular process in mind?
     
    Sangam Singh likes this.
  3. DickCappels

    Moderator

    Aug 21, 2008
    2,647
    631
    If you want to keep it highly achievable have one master that runs the application program and set up the others as slave peripheral processors that do little more respond to commands from the host. The peripheral processors can have their own "smarts" but only with respect to their assigned tasks. Peer-to-peer might greatly complicate the picture, so it would be best to avoid it, at least at the start.

    If the system only has a few processors on the same PCB or in close proximity to one-another I2C or SPI should work fine. SPI is particularly good for high data rates. You don't have to rule out using multiple types of interfaces in your system. Can't comment on CAN.
     
  4. RJohnson

    New Member

    May 29, 2011
    21
    3
    Agree with Dick here. A single Master and multiple slaves is easier to implement.
    I have done this with longer distances using an RS-485 bus (2 wire) and Com Ports. All devices share the same bus but only one
    talker at a time controlled by a Master.
    For short distances use SPI or I2C.
     
  5. crutschow

    Expert

    Mar 14, 2008
    12,969
    3,218
    KansaiRobot likes this.
  6. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Well, I haven't decided yet, but say which is better for master-slave and which for peer to peer?
    Frankly I agree with Dick that master slave would be preferable, a master and some slaves doing their own thing.

    Thank you for your insight. One thing to clarify: So I2C and SPI are only recommended for close proximity??
    Right now I was thinking of having each processor in its own board and connected with wires but I think that would not work right?
    On the other hand it can be as you say, several processors on a single board and the actuators they control in different positions and the ones connected with cables

    RS-485? I ll look into it... So again SPI and I2C are not recommended for say wires right?
     
  7. DickCappels

    Moderator

    Aug 21, 2008
    2,647
    631
    You can go a couple of meters with I2C -Philips proposed it as a standard computer peripheral interface less than a year before the USB was introduced. The greater the distance between devices the more chance for signal quality issues.
     
  8. RJohnson

    New Member

    May 29, 2011
    21
    3
    RS-485 is a balanced line and longer lines can be tolerated. Driver chips are standard and easily gotten. All microcontrollers would require UARTS.
    A link:
    https://en.wikipedia.org/wiki/RS-485
     
  9. kubeek

    AAC Fanatic!

    Sep 20, 2005
    4,669
    804
    Let´say your slave processors are monitoring some inputs upon which the master processor needs to act. With a master-slave bus arrangement such as I2C or SPI the slaves cannot send a message on their own, but need to wait for the master to ask them. If you have lots of slaves then it will take considerable time between the input happening and the master cpu knowing about it.
    In a multi-master bus such as CAN any device can send a message on their own, so whenever the event happens the slave cpu will send a message on its own and the information will get to the master cpu much quicker.

    Now, this was about the bus architecture. For the actual relation between the cpus, there are other things to keep in mind. Lets say the cpus are doing some long computation, for example searching for a solution to some problem. In the beginning the master distributes parts of the space to be searched between the worker cpus. However there will be times where the worker cpu decides that there cannot be any more solutions in the workload it received, so it asks for another part of the job to work on.

    In a master-slave relation the master decides who of the slaves gives some of its work to the empty one.
    In a peer to peer relation the empty one asks its peers and they collectively decide who gives the work to the empty one. This could be done by some parallel computation and might be faster than in the master-slave model.
     
    absf and KansaiRobot like this.
  10. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5

    Very interesting. I have done some CAN communications in the past but using a ARM cortex A processor.
    But times passes and I forget things (I had to read SPI and I2C again to remember the concepts)

    So, CAN is interesting as an option. now the question is Can PICs handle CAN??
     
  11. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,902
    2,154
    With SPI slaves you can also use interrupts to signal the master it needs to be serviced. The slave cannot initiate the data transfer but it can alert the master that it has data ready using an external interrupt, so the master can query the slave in response.

    Here is a simple prototype board that uses a PIC32MX250 (That handles data logging to a fat32 formatted SD-card and other functions on one SPI link) as the master with a PIC18F45K80 as the slave on the other SPI link for ADC inputs and serial data via light-links. The PIC18 can send interrupts to the PIC32 to quickly service SPI when serial or other data is ready for it to receive or it can poll in a timed loop.
    [​IMG]
     
    Last edited: Jun 24, 2015
    KansaiRobot and absf like this.
  12. kubeek

    AAC Fanatic!

    Sep 20, 2005
    4,669
    804
  13. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,902
    2,154
    With a PIC32 the external interrupt from the slave can be assigned using PPS (pin 10 in this simple example)
    C32 2.02 plib
    Code (Text):
    1.  
    2. ....
    3. setup an ISR vector for the interrupt
    4.  
    5. void __ISR(_EXTERNAL_1_VECTOR, ipl2) External_Interrupt_1(void)
    6. {
    7.    blink_led(RED_LED, LED_OFF, FALSE);
    8.    blink_led(GREEN_LED, LED_ON, TRUE);
    9.    spi_flag=1;
    10.    mINT1ClearIntFlag();
    11. }
    12. ....
    13. config the pin to receive INT1
    14.  
    15.    PORTSetPinsDigitalIn(IOPORT_A, BIT_3); // for SPI 2 slave interrupt input
    16.    PPSInput(4, INT1, RPA3); // EXT Interrupt #1 Port A bit 3, chip pin 10
    17.    ConfigINT1(EXT_INT_PRI_2 | FALLING_EDGE_INT | EXT_INT_ENABLE);
    18.    SetSubPriorityINT1(EXT_INT_SUB_PRI_3);
    19.    mINT1ClearIntFlag(); // clear before enable
    20. ....
    21.   // Enable multi-vectored interrupts
    22.    INTEnableSystemMultiVectoredInt();
    23.  
    24. Monitoring the spi_flag in the debugger for a write when pin 10 goes to ground (with a jumper here)
    25.  
    ICD3 with a AC164110 RJ12 (6P6C) to ICSP adapter
    [​IMG]

    Linux MPLAB®X 3.05: http://www.microchip.com/pagehandler/en-us/family/mplabx/
    [​IMG]
     
    Last edited: Jun 25, 2015
  14. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Well, after a couple of months I ve returned to this.
    I ve implemented successfully a 2 PIC system that communicates through SPI. It is rather simple, the slave just transmit what the master sends to it.
    I have several questions on this.

    1) First, in my implemented project there is always one delay from what the master sends to what it receives. Say the master sends (one by one) "HELLO WORLD", the slave would bump back "%HELLO WORL" (with % being garbage the first time, and on reset being 'D' the last letter of the previous message. I wonder why is this so...

    2) The slave can only transmit on a master command right? so if I want to implement a master controlling a slave process, the slave can do its work , put the results on some variable and then when asked by the master reply.
    I am reading your posts on the slave notifying the master through interruptions. Can you tell me more about this?
    What kind of interruptions?? I am guessing (and I can be totally wrong), some cable from the slave to the master so that the master gets an interruption from the I/O pins... is this so??

    Any comment or advice will be greatly appreciated

    Btw, if any of you have any comment, or observation on SPI, not even related to the above two questions, I would like to hear them as well thanks :)
     
  15. kubeek

    AAC Fanatic!

    Sep 20, 2005
    4,669
    804
    Please start your own thread.
     
  16. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    The interrupt referred to is the traditional external interrupt caused by an input line that forces an interrupt call in the code. To implement this you need one line per slave. Since you are using SPI you thus need two lines per slave plus two lines for clock and data. Example: 5 slaves need 5 x 2 + 2 = 12 lines.

    The time I needed a master controlling multiple (10 total) slaves I did it all with 2 wires over an I2C bus. After giving the GO command to each slave the master would then loop and frequently ask each slave was it done.
     
  17. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Thank you for your replies. I understand your assertion that it would need 2 lines per slave for the implementation. However I have been advised of a way to use only one line per slave (but the number of slaves is limited to four). I will explain this here and would appreciate your comments.

    The trick is to use as CS pins the IOC pins of the master (in my case RB4~RB7). Instead of setting these pins as outputs we set them as inputs (high impedance).
    Now, whenever the master wants to select a slave, it sets the corresponding CS as output, clears it (therefore notifying the slave to start SPI) and transmit. Once it is finished, sets the CS and then tristate it by making it an input again.

    Now, when the slave finish what is doing, and wants to notify the master it sets this line (SS) to 1 therefore changing the state of the IOC pins of the master, therefore generating an interrupt.

    This interrupt in the master will again start SPI communication with the corresponding slave.

    It seems like a good idea (did I explain the idea well??) but the only thing that puzzles me is: yeah we can change the CS input/output direction but can we do that with the slave SS if we have set SSPM3~0 as 0100?? Or do I have to use SSPM3=0 as 0101?? but then if there is no SS control enabled how the slave recognize it is the one being called to transmit??
     
  18. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    If yoy use SPI you need a way to control the chip select. Final answer.

    If you try to use that line as an input then you have nothing holding the slaves off.
     
  19. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,902
    2,154
    You can 'fake' a tri-state multi-directional one-wire line on a PIC to (many) PIC(s) by using a pull-up on the line. All ports to the line are inputs to keep it HIGH until a port pin pulls it LOW to send a signal with a TRIS to make it a output with the latch set LOW to control the line from it's side (then switch back to a input to bring the line back HIGH) to send a signal to another or (better) to a master interrupt to poll slaves. You could do this with the CS line but then there would be a window where the slave could have a collision unless it was coded to dump data during this CS back to master time with open-drain and all HIGH bits idle state in its SPI buffer. IMO more trouble than it's worth to implement.
     
    Last edited: Aug 13, 2015
    KansaiRobot likes this.
  20. nsaspook

    AAC Fanatic!

    Aug 27, 2009
    2,902
    2,154
    A external interrupt from the slave example using the board in this thread: PIC32 master/PIC18 slave
    You can use polling and delays but this method gives max throughput (~108us per sample with overhead) and is decoupled from the slaves exact timing.

    Top to bottom traces
    SRQ Service request line from PIC18 to PIC32
    SDI
    SCK clocks for each transmission of a byte
    SDO
    [​IMG]

    The PIC32 input pin is configured to INT1 set to trigger on a negative edge sent from a output pin from the PIC18.
    32 sends request for ADC data to 18 via SPI then waits for SRQ or timeouts out
    18 sets the SRQ line HIGH when the ADC request is received and starts the conversion
    18 completes the conversion (39.1 us), loads the ADC data into the SPI buffer then sets the SRQ line low
    SRQ negative edge triggers the 32 ISR routine to set the spi_flag TRUE in the wait routine and it exits
    32 then talks to the 18 slave to receive the data in the buffer (~10us from SRQ received)

    PIC32 SPI wait routine
    Code (C):
    1.  
    2. /*
    3. * branch macros for MIPS
    4. */
    5. #define likely(x)      __builtin_expect(!!(x), 1)
    6. #define unlikely(x)    __builtin_expect(!!(x), 0)
    7. ...
    8. /*
    9. *  delay a short time after spi command or exit on slave SRQ signal if srq is true
    10. *  flag will always be unset to low on exit
    11. */
    12.  
    13. static void DelaySPI(WORD delay, int srq)
    14. {
    15.     unsigned int int_status;
    16.  
    17.     while (delay--) {
    18.         if (likely(srq & spi_flag)) // make the instruction cache preload the exit code
    19.             goto DelaySPI_exit;
    20.         int_status = INTDisableInterrupts();
    21.         OpenCoreTimer(500000 / 2000);
    22.         INTRestoreInterrupts(int_status);
    23.         mCTClearIntFlag();
    24.         while (!mCTGetIntFlag());
    25.     }
    26. DelaySPI_exit:
    27.     mCTClearIntFlag();
    28.     spi_flag = LOW;
    29. }
    30. ...
    31. int SpiADCRead(unsigned char channel)
    32. {
    33.     V.adc_count++;
    34.     xmit_spi_bus(CMD_DUMMY_CFG, 1);
    35.     spi_flag = HIGH;
    36.     cmd_response_port = xmit_spi_bus(CMD_ADC_GO_H | (channel & 0x0f), 1);
    37.     DelaySPI(50, HIGH); // delay for adc conversion time and look for SRQ signal
    38.     cmd_data[0] = xmit_spi_bus(CMD_ADC_DATA, 1);
    39.     cmd_data[1] = xmit_spi_bus(CMD_DUMMY_CFG, 1);
    40.     return(short int) (cmd_data[0] | (cmd_data[1] << 8));
    41. }
    42. ...
    43. /*-----------------------------------------------------------------------*/
    44. /* Transmit a byte via SPI2  (Platform dependent)                  */
    45.  
    46. /*-----------------------------------------------------------------------*/
    47.  
    48. unsigned char xmit_spi_bus(unsigned char dat, WORD pace)
    49. {
    50.     unsigned char rec_buffer;
    51.  
    52.     V.spi_count++;
    53.     SpiChnPutC(BUS_CHAN, dat); // Send data on the master channel, SPI2
    54.     while (SpiChnIsBusy(BUS_CHAN));
    55.     rec_buffer = SpiChnGetC(BUS_CHAN); // Get the received data
    56.     DelaySPI(pace, LOW);
    57.     return rec_buffer; // Get the received data
    58. }
    59.  
    The Likely Macro in the delay function uses branch prediction hints (GCC __builtin_expect) to tell the compiler (if it's a good compiler) to generate code for the CPU pipeline to order the exit code inline instead of the timer code to optimize speed. Most of the time the delay function is called without checking for the flag so the prediction would be unlikely to just exit. Making exit likely reorders the code to directly exit without jumps and moves jumps/flushes into the delay code where it doesn't matter much.

    http://kernelnewbies.org/FAQ/LikelyUnlikely

    I could easily expand the use of SRQ for every master/slave SPI transmission instead of just ADC conversions to reduce fixed delays needed for the PIC18 to process data in its ISR but the time gained vs overhead is small as the PIC18 ISR is quick.
    [​IMG]
     
    Last edited: Aug 14, 2015
    JohnInTX likes this.
Loading...