Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 12 of 12

Thread: Spi for both wiz820io and OLED ssd1332 not working correctly

  1. #1

    Spi for both wiz820io and OLED ssd1332 not working correctly

    Hi,

    I've tested the wiz820io and an ssd1332 OLED with a teensy 3.2, each separately and they both work.

    Now I'm trying to use both at once with different chip select pins.
    To test it I have a counter that is displayed on the oled and the upd send receive string example with processing.
    At first the counter works fine and the wiz receives some of the processing strings but then the serial monitor shows that the wiz received some random junk upd and the oled freezes.

    Code:
    Received packet of size 53394
    From 149.79.84.47, port 40219
    Contents:
    �/08g7�g����zvGM:A�w��-�~
    Received packet of size 59142
    From 207.170.92.51, port 59013
    Contents:
    �����_9L���v;��$
    It seems like a problem with the spi sharing. I've tried wrapping each segment with beginTransaction endTransaction, put pull up resistors on both CS (10k).
    I'll also post a picture of my breadboard later.
    I'm using the ethernet library straight from paul's github and the oled library and modified adafruit graphics library from sumotoy.

    Any hints or ideas?

    Here is my code
    Code:
    #include <Adafruit_GFX.h>
    #include <OLED_SSD1332.h>
    
    
    /*
    Note for Teensy 3.x !!!!!!!!!!!!!!!!!!!
     You should choose from those pins for CS and RS:
     2,6,9,10,15,20,23
     */
    #define cs   15
    #define rst  6
    #define dc   2
    
    
    // Color definitions
    #define  BLACK           0x0000
    #define BLUE            0x001F
    #define RED             0xF800
    #define GREEN           0x07E0
    #define CYAN            0x07FF
    #define MAGENTA         0xF81F
    #define YELLOW          0xFFE0  
    #define WHITE           0xFFFF
    #define TRANSPARENT     -1
    
    int count = 0;
    OLED_SSD1332 display = OLED_SSD1332(cs, dc, rst);
    
    
    #include <SPI.h>         // needed for Arduino versions later than 0018
    #include <Ethernet.h>
    #include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008
    //#include <SPI.h>
    
    // Enter a MAC address and IP address for your controller below.
    // The IP address will be dependent on your local network:
    byte mac[] = {
      0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
    };
    IPAddress ip(10, 10, 10, 2);
    
    unsigned int localPort = 8888;      // local port to listen on
    
    // buffers for receiving and sending data
    char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,
    char ReplyBuffer[] = "acknowledged";        // a string to send back
    
    // An EthernetUDP instance to let us send and receive packets over UDP
    EthernetUDP Udp;
    
    
    void setup() {
      //oled 
      pinMode(9, OUTPUT);
      digitalWrite(9, LOW);   // reset the WIZ820io
      pinMode(10, OUTPUT);
      digitalWrite(10, HIGH);  // de-select WIZ820io
      pinMode(cs, OUTPUT);
      digitalWrite(cs, HIGH);   // de-select the SD Card
    //  SPI.setCS(cs);
    
      SPI.setCS(cs);
    //  SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));
      display.begin();
      display.setBitrate(24000000);
      display.setRotation(270);
    //  SPI.endTransaction();
    
      SPI.setCS(10);
      // start the Ethernet and UDP:
    //  SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
      Ethernet.begin(mac, ip);
      Udp.begin(localPort);
    //  SPI.endTransaction();
      Serial.begin(115200);
    //  SPI.begin();
      
    }
    
    void loop() {
      SPI.setCS(10);
      
      digitalWrite(10, LOW);
      delay(2);
      SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
      // if there's data available, read a packet
      int packetSize = Udp.parsePacket();
      if (packetSize) {
        Serial.print("Received packet of size ");
        Serial.println(packetSize);
        Serial.print("From ");
        IPAddress remote = Udp.remoteIP();
        for (int i=0; i < 4; i++) {
          Serial.print(remote[i], DEC);
    //      gotPacket = true;
          if (i < 3) {
            Serial.print(".");
          }
        }
        Serial.print(", port ");
        Serial.println(Udp.remotePort());
    
        // read the packet into packetBufffer
        Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
        Serial.println("Contents:");
        Serial.println(packetBuffer);
    
        // send a reply to the IP address and port that sent us the packet we received
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
        Udp.write(ReplyBuffer);
        Udp.endPacket();
      }
      SPI.endTransaction();
      digitalWrite(10, HIGH);
      delay(40);
    
      //oled 
    //  if(gotPacket)
    //  {
      SPI.setCS(cs);
      digitalWrite(cs, LOW);
      delay(2);
      
      SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));
      
      display.clearScreen();
      display.setTextColor(WHITE);  
      display.setTextSize(1);
      String st;
      for(int i = 0; i < 7; i++)
      {
        if(i == 0)
        display.setTextColor(RED);  
        else
        display.setTextColor(WHITE);  
        display.setCursor(0, i*9);
        display.println(count);
      }
      
      
      SPI.endTransaction();
      digitalWrite(cs, HIGH);
      
      delay(40);
    //gotPacket = false;
    //  }
      count ++;
    }
    
    
    /*
      Processing sketch to run with this example
     =====================================================
    
     // Processing UDP example to send and receive string data from Arduino
     // press any key to send the "Hello Arduino" message
    
    
     import hypermedia.net.*;
    
     UDP udp;  // define the UDP object
    
    
     void setup() {
     udp = new UDP( this, 6000 );  // create a new datagram connection on port 6000
     //udp.log( true );     // <-- printout the connection activity
     udp.listen( true );           // and wait for incoming message
     }
    
     void draw()
     {
     }
    
     void keyPressed() {
     String ip       = "192.168.1.177"; // the remote IP address
     int port        = 8888;    // the destination port
    
     udp.send("Hello World", ip, port );   // the message to send
    
     }
    
     void receive( byte[] data ) {      // <-- default handler
     //void receive( byte[] data, String ip, int port ) { // <-- extended handler
    
     for(int i=0; i < data.length; i++)
     print(char(data[i]));
     println();
     }
     */

  2. #2
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    If the ethernet interface uses a software driver with an interrupt upon receipt of message (IP packet), and a read is ever-present so as not to miss packets, then the ISR for that interface may use the SPI port without "asking". This is the basic issue with sharing an SPI port, even with independent chip select pins.

    The driver for the wiznet... does its ISR use the SPI port?
    Same applies to any device that uses a shared SPI port in an ISR.

    SPI transactions, as best as I know, facilitates SPI port sharing among application layer functions, but cannot deal with the ISR issue - other than blocking the interrupt for a time. That latency can be brief enough to be viable in some communications methods.

    Of course, one can have a driver whose ISR sets a flag or changes a task's state, or changes a finite state machine's state to do the work later in a non-ISR context were sharing might work. Since the Wiznet chips have on-chip packet buffers, this would work. SPI based devices like low cost data radios that don't have such a buffer have to get the ISR to use the SPI port.

    This can happen eve with, say, an LCD driver where the LCD interrupts to say "last graphics command is finished", and if that ISR uses the SPI port, the same issue arises; deferred SPI I/O is needed, and in this case, it's not perishable data as is the case for received communications data.

    So, if these situations arise, one must use Paul's SPI transactions to manage sharing of the SPI port at the ISR level.
    Last edited by stevech; 04-12-2016 at 04:54 PM.

  3. #3
    Hi,

    Actually nope, it's not using the interrupt, and I'm using beginTransaction/endTransaction in the code to guard against this kind of potential problem.

  4. #4
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    Is the Wiznet interface then done with high-rate Polling of its interrupt request bit - though it's not used to actually interrupt? Else polling where each poll is SPI traffic would be very inefficient and require the overhead of SPI Transactions for each poll?

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    26,380
    Quote Originally Posted by stevech View Post
    Is the Wiznet interface then done with high-rate Polling of its interrupt request bit - though it's not used to actually interrupt?
    Nope. The Wiznet IRQ signal isn't used in any way, not even polling.

    Else polling where each poll is SPI traffic would be very inefficient and require the overhead of SPI Transactions for each poll?
    Oh how this underestimates the terribly inefficient design of the Arduino Ethernet library!

    Actually, with Teensyduino 1.28 I've published a new version that removes much of the redundant register access, which speeds it up dramatically... about to this inefficient level.

  6. #6
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    as you probably know, to avoid polling by sending SPI inquiries in a polling superloop, one can connect the interrupt request bit from the Wiznet to a GPIO input bit. But not use it as an interrupt. So avoid the architectural impact and SPI sharing impact of an ISR that uses SPI, the polling loop can look at the GPIO bit. If true, it means that at a future time when the SPI port can be "taken", the reason for the GPIO polled bit being true can be ascertained via an SPI read of status. But only when the chip has a status change that necessitates doing the SPI read. Most changes are packet transmit complete and packet received. The latter is the hard nut.

    This might be easily implemented and not affect the overall structure. Just a different criteria in the polling loop.

    I take it that no one has implemented a real interrupt driven handler for the Wiznet chips for the Arduino world?

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,008
    stevech: This seems like what I did on the ILI9341 Touch driver. Put in an (optional) interrupt pin that sets a flag in the library that retards polling when no touch has been registered. It doesn't do any SPI I/O on the interrupt and it cuts down on polling SPI noise, but allows 'polling' when wanted to keep the touch responsive rather than cutting back to save I/O, making the touch sluggish. It was ~20 line PULL request - included struct adds.

  8. #8
    So am I getting this issue from the arduino's ethernet library inefficiency?
    As I understand it the polling and interrupt shouldn't be a problem in my case?

    Any other suggestions?

    Thanks

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    26,380
    Quote Originally Posted by lucasparis View Post
    Any other suggestions?
    Please give it a try with the just-released Teensyduino 1.28. The Ethernet lib has lots of improvements in 1.28. When compiling, pay attention to any messages about duplicate libs. You want to make sure it's using Ethernet from hardware/teensy/avr/libraries.

    If that doesn't pan out, can you give me a link to the OLED_SSD1332 library, and the least expensive display it supports. Maybe I'll get one and try to reproduce the problem here.

  10. #10
    Just tried teensyduino 1.28 with arduino 1.6.8 and still the same problem.

    I was using the ethernet library straight from your github Paul, now I'm just using the one in the teensyduino package.

    Here is the library I'm using https://github.com/sumotoy/OLED_SSD1332 it also needs a modified version of the adafruit gfx library: https://github.com/sumotoy/Adafruit_GFX


    And here is the OLED I'm using: http://www.waveshare.com/0.95inch-rgb-oled-b.htm
    I thought the (sparce) documentation for it was a bit misleading as it says it uses the ssd1331 controller but somotoy's sdd1332 library worked with it whereas his ssd1331 library didn't. But I just tested the adafruit library for ssd1331 and it works, expect it's really slow (adafruit doesn't use hardware spi) and so the teensy's loop refresh rate drops to about 1hz.

    I'll try to get back into sumotoy's library and see if I can hack something.

    Thanks Paul!!

  11. #11
    So indeed it seems this oled is actually a ssd1331, there are exemples in this thread of people getting the 1332 library working with a 1331 oled but not getting the 1331 library to work.
    https://forum.pjrc.com/threads/25719...hlight=ssd1332

  12. #12
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    26,380
    I ordered that display from Waveshare. I'm guessing "E-packet" means it'll be here in a couple weeks...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •