Multiple SPI Communications

by gwilson5 on Thu Nov 29, 2012 9:49 pm

I have an Arduino Ethernet (built in Ethernet, not shield) and a SSD1306 128x64 OLED.

I used the adafruit SPI sample sketch to test out the display. I then modified it to output a simple clock to the display. No problem.

Then I started playing around with the NTP time server update sketch to see if I could get the current time from the internet. That worked, so I thought I would try to "weave" the two sketches together - a clock that gets it time from an NTP server and outputs it to the display via SPI.

When I attempt to just mesh the two sets of code together I get nothing on the display or any communication to an NTP server. I think with the attempt to get the time and also and send serial data to the OLED there needs to be some additional logic to "direct traffic" that isn't used (or needed) in the basic sketches?

I tried to find some example sketches that used serial communications in this way, but haven't been able to find any yet.

Can someone direct me to what I need to research or how I can go about accomplishing this? Any help would be greatly appreciated.
gwilson5
 
Posts: 16
Joined: Sun Nov 25, 2012 4:03 pm

Re: Multiple SPI Communications

by cjbaar on Fri Nov 30, 2012 12:24 am

I haven't used that model specifically, but the specs indicate it uses pin 10 for the ethernet select, just like the shield version. SPI allows you to communicate to multiple devices, but only one at a time. Like you said, you need to "direct traffic" to the right device. In this case, each device will have a software select (SS) or chip select (CS) pin. When this pin is low, the device will listen (or respond); when it is high, it will ignore the SPI data.

Based on my previous experience, the Ethernet library handled the toggling of the CS pin for the ethernet chip (on an Uno, pin 10). But, you'd probably need to handle the display CS yourself. Since you can't talk to both at once, you'll need to buffer or store whatever data you need to read.

For example, this is how the sketches that use the ethernet and the SD card work. Both are attached to the SPI bus.
1) set SD card CS pin to high (SD card will ignore SPI traffic)
2) use EthernetClient to read data over SPI bus
3) store data in buffer/variable
4) set SD card CS pin to low (SD card will now listen to SPI traffic)
5) write data to SD card over SPI bus
This method should apply directly to what you are trying to do. Just make sure to set the CS pin on the display to high whenever you are not talking directly to it. Hope that helps.
cjbaar
 
Posts: 73
Joined: Fri Aug 26, 2011 4:58 pm

Re: Multiple SPI Communications

by gwilson5 on Fri Nov 30, 2012 7:45 am

Thanks, I figured as much. Yes, pin 10 is ETHCS (luckily it was silk screened on the device). The other SPI pins weren't in the same order, so that was my first learning experience.

I guess I will have a pretty steep learning curve to get to the next level since it has been hack-and-try up to this point.

I appreciate your helping a newbie! :)
gwilson5
 
Posts: 16
Joined: Sun Nov 25, 2012 4:03 pm

Re: Multiple SPI Communications

by cjbaar on Fri Nov 30, 2012 10:53 am

Well, it sounds like you are on the right track, since you got each one working individually.

One thing I just noticed. I purchased a 128x64 ssd1306 display a while back, and while I haven't played it with it too much, the example sketch and the tutorial are not using standard SPI pin assignments. In fact, the code is not even using actual SPI. I'm not sure why, but they seem to have written their own version of SPI, which is using more pins than normal. This will definitely clash with the ethernet chip.

Native SPI should only require three pins... two of which (MOSI and CLK) are not changeable on the hardware. However, in the sketch and the tutorial, I am showing:
#define OLED_DC 11
#define OLED_CS 12
#define OLED_CLK 10
#define OLED_MOSI 9
#define OLED_RESET 13

To match the SPI bus that the ethernet (and other SPI devices) will use, I would try changing it to the following (make sure the hardware wiring changes to match):
#define OLED_MOSI 11
#define OLED_CLK 13
#define OLED_CS 9
#define OLED_DC 8
#define OLED_RESET 7

This will at least get the MOSI and CLK lines where they should be. The CS can be any pin that doesn't conflict with something already used. The DC and RESET lines are not part of standard SPI communication. It appears, from the code, that the device needs some extra toggling every time it receives serial data, so that it knows whether you are sending it data for display or a command string. It almost defeats the purpose of sharing the SPI bus, because now you're using up a lot more pins.

If that doesn't work, you could also try:
1) Using five completely different pins (such as 5-9) that don't overlap with the native SPI (10-13) at all.
2) Give the I2C communication method a shot. Normally, this is less desirable than SPI because it is slower and you would be taking up extra pins... however, since the library is not using native SPI anyway, it might end up being about the same... or even faster. And you're already using at least two extra pins.

I think the short answer here is this: in my mind, it is misleading to call this SPI... especially when working along side other true SPI devices.

Let me know what you discover.
cjbaar
 
Posts: 73
Joined: Fri Aug 26, 2011 4:58 pm

Re: Multiple SPI Communications

by adafruit_support_rick on Fri Nov 30, 2012 11:01 am

You're right about the 128X64 ssd1306 - the pin assignments in the tutorial conflict with the standard hardware SPI pin assignments. The communication protocol is indeed SPI, however. It is simply implemented as software SPI in the adafruit library, and you can use any set of free pins to drive the display - it's not limited to using the hardware SPI pins.

Assuming you have some free pins, this actually simplifies the problem of integrating your ethernet and ssd1306 sketches, since you can establish two completely independent SPI buses. No worries about buffering or sequencing bus access.
User avatar
adafruit_support_rick
 
Posts: 10914
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: Multiple SPI Communications

by gwilson5 on Fri Nov 30, 2012 12:50 pm

To match the SPI bus that the ethernet (and other SPI devices) will use, I would try changing it to the following (make sure the hardware wiring changes to match):
#define OLED_MOSI 11
#define OLED_CLK 13
#define OLED_CS 9
#define OLED_DC 8
#define OLED_RESET 7


cjbaarThis is exactly what I had figured out, as well. Thanks to driverblock for helping me with that stuff in the displays forum. I did also try the 5 independent pins, which worked as well. But from my reading the CS is the only one that has to be independent for each device.

However, I am unsure how to set OLED_CS high on the OLED when I want to do my internet send/receive. At least that is my understanding of what I should probably do first?
gwilson5
 
Posts: 16
Joined: Sun Nov 25, 2012 4:03 pm

Re: Multiple SPI Communications

by cjbaar on Fri Nov 30, 2012 1:11 pm

Actually, after a another quick glance into the code, it looks like the library should do it for you. Note in the functions ssd1306_command() and ssd1306_data(), it is automatically setting the CS line to low before sending data, and setting it back to high when it is done. So, I don't think you need to do anything in your code other than to make sure that an ethernet function isn't trying to run simultaneously with a display one (which would probably only happen if you're using interrupts).

If you use the completely independent method, and really need to get a pin back, you could drop the CS line altogether, because nothing else is sharing the secondary SPI bus. You'd have to comment out those portions in the library, and just tie the display CS line to ground.
cjbaar
 
Posts: 73
Joined: Fri Aug 26, 2011 4:58 pm

Re: Multiple SPI Communications

by cjbaar on Fri Nov 30, 2012 1:15 pm

The communication protocol is indeed SPI, however. It is simply implemented as software SPI in the adafruit library, and you can use any set of free pins to drive the display - it's not limited to using the hardware SPI pins.


It's an issue of semantics, I suppose. The wiki entry for SPI defines it as:
The SPI bus specifies four logic signals: SCLK, MOSI, MISO, and SS


I would argue that just because something is serial and uses a clock line, it's not necessarily "SPI"... and the fact that this display requires two additional pins for operation -- instead of implementing those functions into the serial command set -- disqualifies it from meeting the spec.

But, that's just me. :)
cjbaar
 
Posts: 73
Joined: Fri Aug 26, 2011 4:58 pm

Re: Multiple SPI Communications

by gwilson5 on Fri Nov 30, 2012 1:23 pm

OK, so here is what happens when I run my program. I get the "Please wait. Rebooting..." on the OLED and the serial monitor gets "After serial begin". That is where it all comes to a halt.


Code: Select all | TOGGLE FULL SIZE
void setup() {
  Serial.begin(9600);
 //  This is where the display is initialized 
   display.begin(SSD1306_SWITCHCAPVCC);
  // init done
  display.clearDisplay();
  display.display(); // show splashscreen
  delay(2000);

  // text display tests
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Please wait.");
    display.println("Rebooting...");
  display.display();
  delay(5000);
   
   
   
   int i = 0;
   int DHCP = 0;
   Serial.println("After serial begin");
   DHCP = Ethernet.begin(mac);
   //Try to get dhcp settings 30 times before giving up
   while( DHCP == 0 && i < 30){
     delay(1000);
     DHCP = Ethernet.begin(mac);
     i++;
     Serial.println("DHCP attempt ");
   }
   if(!DHCP){
    Serial.println("DHCP FAILED");
     for(;;); //Infinite loop because DHCP Failed
   }
   Serial.println("DHCP Success");
 /***/
gwilson5
 
Posts: 16
Joined: Sun Nov 25, 2012 4:03 pm

Re: Multiple SPI Communications

by adafruit_support_rick on Fri Nov 30, 2012 6:20 pm

gwilson5 wrote:That is where it all comes to a halt.


And that's also where you call this:
Code: Select all | TOGGLE FULL SIZE
  DHCP = Ethernet.begin(mac);


The 128X64 ssd1306 library requires a 1K frame buffer. That's fully half of the available SRAM on a UNO. DHCP is a major memory hog as well.

Give it a static IP address and comment out all the DHCP stuff. See if you get any further.
User avatar
adafruit_support_rick
 
Posts: 10914
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: Multiple SPI Communications

by gwilson5 on Fri Nov 30, 2012 11:02 pm

I actually had already set the IP address to static, so it was easy to go ahead and delete out the DHCP section -- didn't work either. I found a different NTP update sketch and added my display sketch code for grins. Again, I was able to get it to update the time, but it would never output anything to the display.

However, I just read this on the product page on Arduino website:
NB: Pins 10, 11, 12 and 13 are reserved for interfacing with the Ethernet module and should not be used otherwise.


I had done this early on when I was testing the display, but since it appeared to work on the shared pins, I thought the dedicated CS pin was all I needed to differentiate the two different serial streams. Plus, it freed up 3 pins.

So, I rewired. By not sharing the MISO, MOSI and CLK pins, it worked. I don't know if there is some sort of programming work around (I doubt it if they have put this disclaimer on the product page of their website). So much for making my life easier by getting a board with ethernet built in.... now I only have 2 digital pins for my project. I thought the whole point of SPI was to share the bus.

Oh well.
gwilson5
 
Posts: 16
Joined: Sun Nov 25, 2012 4:03 pm

Re: Multiple SPI Communications

by adafruit_support_rick on Sat Dec 01, 2012 12:31 pm

gwilson5 wrote:However, I just read this on the product page on Arduino website:
NB: Pins 10, 11, 12 and 13 are reserved for interfacing with the Ethernet module and should not be used otherwise.

Ah! That's good to know. With the ethernet shield, you can get away with sharing them.
gwilson5 wrote:now I only have 2 digital pins for my project.

How about an I2C port expander? They work great.
http://www.adafruit.com/products/593
http://www.adafruit.com/products/732

If you need PWM, there's also this:
http://www.adafruit.com/products/815
User avatar
adafruit_support_rick
 
Posts: 10914
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: Multiple SPI Communications

by gwilson5 on Sat Dec 01, 2012 5:59 pm

I guess that will work. I can go i2c on the display for now and have 6 pins available. If I need the faster sdi, then I can use i2c for my pin requirements.

Thanks again, everyone has been helpful - even if just for affirmation. I am glad this forum doesn't shun newbies!
gwilson5
 
Posts: 16
Joined: Sun Nov 25, 2012 4:03 pm

Re: Multiple SPI Communications

by cjbaar on Sat Dec 01, 2012 7:05 pm

Yeah.. that is weird that it doesn't want you to share those SPI pins. Sort of defeats the purpose of buying the all-in-one unit as you start to lose pins. I would try the I2C communication with the display. You only need two analog pins to drive it, and I doubt it will be any slower than the software SPI. I'll be interested to see what you find out, as I have a few of these little displays, and will be playing with them someday.
cjbaar
 
Posts: 73
Joined: Fri Aug 26, 2011 4:58 pm

Re: Multiple SPI Communications

by gwilson5 on Sat Dec 01, 2012 8:52 pm

i2C worked fine. Now I have 6 pins free. I am going to be 90% text and only 1 refresh per minute unless button press or serial packet received, so it shouldn't be an issue.

I wouldn't have paid extra for the all-in-one had I known. I also found out there is almost no dimming on the SSD1306 1.3" Monochrome OLED.
gwilson5
 
Posts: 16
Joined: Sun Nov 25, 2012 4:03 pm