# Particle Photon OLED screen and SD card demo

**URL:** <https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145>\
**Category:** Tutorials\
**Created:** [December 9, 2015, 8:58pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145 "2015-12-09T20:58:21Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [March 26, 2016, 11:57am UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/21 "2016-03-26T11:57:24Z")

</div>

What if you alter the background color from BLUE to something else, does this happen as expected?  
Can you add some code to push the BMP data down `Serial` too, just to see if this looks OKish?

---

<div class="post-metadata">

**Author:** ![MikeSeeH](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/mikeseeh/32/7974_2.png) [@MikeSeeH](https://community.particle.io/u/MikeSeeH)\
**Post date:** [March 26, 2016, 3:02pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/22 "2016-03-26T15:02:11Z")

</div>

Have you checked that the bit depth of the BMP is 24?

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [March 26, 2016, 3:09pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/23 "2016-03-26T15:09:47Z")

</div>

If not, this should be flagged by a `Serial.print()` output - AFAIK (remember).

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 26, 2016, 3:49pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/24 "2016-03-26T15:49:08Z")

</div>

So this is what I found so far:

My OLED is responsive BEFORE the “if(!SD.begin(cs\_sd))”. Before that line, I can change the screen color multiple times no problem; but after, tft.fillScreen() no longer does anything. This seems very similar to Mike’s original [problem](https://community.particle.io/t/solved-sd-card-and-oled-troubles-adafruit-oled-1-5-1431/18051)

As for the pic, I’m using both the lily128.bmp (176x176) and another I found that is128x128. Both are 24bit are being read fine!

Also, the reading/writing portion of the code seems to be okay. I did a Serial.print() of the r, g, b values and they are within range and changing at each read, so I believe the problem lies in tft functions no longer working after the SD begins.

Thanks again for all the help!

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 26, 2016, 3:51pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/25 "2016-03-26T15:51:52Z")

</div>

Oh,here are both initializing lines:

Adafruit\_SSD1351 tft = Adafruit\_SSD1351(cs\_oled, dc, rst); // HARDWARE SPI

if (!SD.begin(cs\_sd)){ // HARDWARE SPI

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [March 26, 2016, 4:07pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/26 "2016-03-26T16:07:57Z")

</div>

@jahydin, looking at the SSD1351 display library from mikeseeh, the SPI is set to MODE3 while the SD library requires SPI MODE0. There is your conflict.

There is no simple way to fix this and this is a common problem with SPI. It is possible to switch modes on the fly but that tends to “glitch” the SPI bus causing problems.

The SSD1351 library only writes to the display, it does not read anything. You could use the software SPI mode for the display using only two extra pins for CLK and MOSI. The display CS line could be held low all the time since it is no longer on the common hardware SPI bus. 😉

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 26, 2016, 4:21pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/27 "2016-03-26T16:21:38Z")

</div>

Oh no!  
Okay, I changed my tft init to :  
Adafruit\_SSD1351 tft = Adafruit\_SSD1351(cs\_oled, dc, mosi, sclk, rst); // SOFTWARE SPI

How do I hold the display line low?

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [March 26, 2016, 4:25pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/28 "2016-03-26T16:25:19Z")

</div>

@jahydin, for now just use the cs\_oled pin you have presently connected. You will need to specify different pins for mosi and sclk since they will conflict with the hardware SPI pins.

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 26, 2016, 5:35pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/29 "2016-03-26T17:35:37Z")

</div>

So here is my new pin setup:

```
#define sclk A0
#define mosi A1
#define miso A4
#define dc D7
#define cs_oled D6
#define cs_sd A2
#define rst D5

```

I have pins A5 and A3 still connected to sclk and mosi (for SD right?)  
I also have pins A0 and A1 connected to sclk and mosi (for oled)

But now SD card failing to initialize.

---

<div class="post-metadata">

**Author:** ![peekay123](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/peekay123/32/810_2.png) [@peekay123](https://community.particle.io/u/peekay123)\
**Post date:** [March 26, 2016, 8:48pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/30 "2016-03-26T20:48:00Z")

</div>

@jahydin, here is the pin assignment as I believe it should be:

```auto
For microSD
------------
  A5 = MOSI
  A4 = MISO
  A3 = SCLK
  A2 = cs_sd

For OLED
------------
  A1 = MOSI
  A0 = SCLK
  D7 = dc
  D6 = cs_oled
  D5 = rst

```

If you can, use a different pin for the OLED `dc` pin since that pin has the onboard LED connected to it as well. The Adafruit constructor call should be:

`Adafruit_SSD1351 tft = Adafruit_SSD1351(cs_oled, dc, A1, A0, rst); // SOFTWARE SPI`

😄

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 26, 2016, 10:59pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/31 "2016-03-26T22:59:49Z")

</div>

So I have:

 ![](https://us1.discourse-cdn.com/flex026/uploads/particle/original/2X/7/7499808b5ffb170508846ad6c486babc8aa4c02c.JPG)

![](https://us1.discourse-cdn.com/flex026/uploads/particle/original/2X/d/ddd2db4aea9a63a29a7cda63d83e68c8416072a8.JPG)

![](https://us1.discourse-cdn.com/flex026/uploads/particle/original/2X/e/eccc3eef50c160c242b9567f404b0bb0080ecc5d.JPG)

With this config my screen works but SD fails to initialize. ☹

Thanks for taking the time to help me btw. I really want to be able to use this screen for my Photon.

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 28, 2016, 9:57am UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/32 "2016-03-28T09:57:00Z")

</div>

Well I finally got it to work, but it is far from stable. I’d say it works half the time, and only when I unplug my battery and pop it back in.The other times it will get to about half way than slow to a crawl then garble. Reset seems to cause the SD to fail init every time. I ordered a separate sd card reader in the hopes it will be better than the “all in one” package. Was really hoping to get this work though. ;(

Anyways, here is my code that got it to work:

```cpp
 #pragma SPARK_NO_PREPROCESSOR

 #include "Particle.h"
 #include "Adafruit_mfGFX.h"
 #include "Adafruit_SSD1351.h"
 #include "SdFat.h"

// SPI interface, these are the pins
 #define sclk A3
 #define mosi A5
 #define miso A4
 #define dc D4
 #define cs_oled D6
 #define cs_sd A2
 #define rst D5
const uint8_t chipSelect = cs_sd;

// 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

// for read16 and read32 to work properly
void bmpDraw(char *filename, uint8_t x, uint8_t y);
uint16_t read16(File &f);
uint32_t read32(File &f);

// instanciate an SD object
SdFat SD;

Adafruit_SSD1351 tft = Adafruit_SSD1351(cs_oled, dc, rst); // HARDWARE SPI
//Adafruit_SSD1351 tft = Adafruit_SSD1351(cs_oled, dc, mosi, sclk, rst); // SOFTWARE SPI

File bmpFile;
int bmpWidth, bmpHeight;
uint8_t bmpDepth, bmpImageoffset;

void setup(void) {
  Serial.begin(9600);
  //while (!Serial.available());

  // initialize the OLED
  Serial.println("init");

  tft.begin();
  //tft.setRotation(0);

  tft.fillScreen(BLUE); //make it colorful
  //delay(1000);

  // initialize the SD Card
  Serial.print("Initializing SD card...");

  //if (!SD.begin(mosi, miso, sclk, cs_sd)) { // SOFTWARE SPI
  if (!SD.begin(chipSelect, SPI_HALF_SPEED)){ // HARDWARE SPI
    Serial.println("failed!");
    return;
  }
  Serial.println("SD OK!");
  // draw the image from the card
  bmpDraw("logo.bmp", 0, 0);

}

void loop() {
}

// Code from https://github.com/adafruit/Adafruit-SSD1351-library/blob/master/examples/bmp/bmp.ino

// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates. It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel). Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster. 20 pixels seems a
// good balance.

 #define BUFFPIXEL 50

void bmpDraw(char *filename, uint8_t x, uint8_t y) {

  File bmpFile;
  int bmpWidth, bmpHeight; // W+H in pixels
  uint8_t bmpDepth; // Bit depth (currently must be 24)
  uint32_t bmpImageoffset; // Start of image data in file
  uint32_t rowSize; // Not always = bmpWidth; may have padding
  uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
  uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean goodBmp = false; // Set to true on valid header parse
  boolean flip = true; // BMP is stored bottom-to-top
  int w, h, row, col;
  uint8_t r, g, b;
  uint32_t pos = 0, startTime = millis();

  if((x >= tft.width()) || (y >= tft.height())) return;

  Serial.println();
  Serial.print("Loading image '");
  Serial.print(filename);
  Serial.println('\'');

  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    Serial.print("File not found");
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print("File size: "); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print("Image Offset: "); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print("Header size: "); Serial.println(read32(bmpFile));
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print("Bit Depth: "); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print("Image size: ");
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        // If bmpHeight is negative, image is in top-down order.
        // This is not canon but has been observed in the wild.
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width()) w = tft.width() - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        for (row=0; row<h; row++) { // For each scanline...
          tft.goTo(x, y+row);

          // Seek to start of scan line. It might seem labor-
          // intensive to be doing this on every line, but this
          // method covers a lot of gritty details like cropping
          // and scanline padding. Also, the seek only takes
          // place if the file position actually needs to change
          // (avoids a lot of cluster math in SD library).
          if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          // optimize by setting pins now
          for (col=0; col<w; col++) { // For each pixel...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format, push to display
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];

            tft.drawPixel(x+col, y+row, tft.Color565(r,g,b));
            Serial.print(".");
            // optimized!
            //tft.pushColor(tft.Color565(r,g,b));
          } // end pixel
        } // end scanline
        Serial.print("Loaded in ");
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) Serial.println("BMP format not recognized.");
}

// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.

uint16_t read16(File &f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File &f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

```

* * *

_Reformatted by ScruffR_  
To get this just wrap your code in

````nohighlight
 ```cpp
 // your code

````

```auto

```

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 28, 2016, 9:58am UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/33 "2016-03-28T09:58:42Z")

</div>

Sorry about the format. I have no idea how to get it in a nice window like everyone else… 😕

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [March 28, 2016, 11:02am UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/34 "2016-03-28T11:02:44Z")

</div>

Not sure if this would make a difference, but try

```cpp
// either use
SYSTEM_THREAD(ENABLED)
// or
SYSTEM_MODE(SEMI_AUTOMATIC)
// and call Particle.connect() after you're done
// or use both ST & SM together

```

An ext card reader shouldn’t be required and might not help anyway.

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 28, 2016, 6:15pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/35 "2016-03-28T18:15:01Z")

</div>

Seemed about the same with STSTEM\_THREAD, and I thought I was at 100% success (even with resets) using the SEMI\_AUTOMATIC mode, but it stopped working consistantly after a a few resets or so. Thanks!

---

<div class="post-metadata">

**Author:** ![MikeSeeH](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/mikeseeh/32/7974_2.png) [@MikeSeeH](https://community.particle.io/u/MikeSeeH)\
**Post date:** [March 29, 2016, 7:22am UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/36 "2016-03-29T07:22:22Z")

</div>

Which power supply do you use?  
I had similar problems some time ago and after replacing the power supply it worked.

---

<div class="post-metadata">

**Author:** ![jahydin](https://avatars.discourse-cdn.com/v4/letter/j/9fc29f/32.png) [@jahydin](https://community.particle.io/u/jahydin)\
**Post date:** [March 29, 2016, 8:34am UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/37 "2016-03-29T08:34:30Z")

</div>

OMG, lol. Yup, that’s it. I’ve been using a little Li-ion 850mAh. I was using my usb for power (and the serial prompts) in the beginning, but that’s when I was getting my code sorted out (the SPI\_HALF\_SPEED is critical). Once I didn’t need the serial prompts I switched to my battery for convenience, got the code working, but never thought my battery could be the reason things were erratic.

Happy to say everything is running perfectly now. Multiple restarts and flashes and it draws the entire thing within a second!

Thanks to everyone who took the time to help me out, and especially you for putting this tutorial up to begin with. 😄

Oh… so what power source did you end up using…?

---

<div class="post-metadata">

**Author:** ![nfriedly](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/nfriedly/32/4700_2.png) [@nfriedly](https://community.particle.io/u/nfriedly)\
**Post date:** [April 13, 2016, 5:07pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/38 "2016-04-13T17:07:12Z")

</div>

BTW, I just bundled up @MikSeeH’s code with a spark.json and slightly tweaked demos from Adafruit and published it to particle build as Adafruit\_1351\_Photon. So you can now include it via the Libraries tab in the Web IDE and get a quick start from the example code.

I didn’t (yet) manage to get the SD card working though, so if anyone here would like to help add that and add in a second example, it would be much appreciated. My copy is at [https://github.com/nfriedly/Adafruit\_SSD1351\_Photon](https://github.com/nfriedly/Adafruit_SSD1351_Photon)

---

<div class="post-metadata">

**Author:** ![nacsajulia](https://avatars.discourse-cdn.com/v4/letter/n/b782af/32.png) [@nacsajulia](https://community.particle.io/u/nacsajulia)\
**Post date:** [April 13, 2016, 7:01pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/39 "2016-04-13T19:01:05Z")

</div>

@nfriedly your test code is a huge help, right now I am trying to get the SDFat library working, but when I try to include it, it always gives this error:

 ![](https://us1.discourse-cdn.com/flex026/uploads/particle/original/2X/0/0fb026d4829bdced31e5d900e6b39beee8fe9d8e.png)

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [April 13, 2016, 8:28pm UTC](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145/40 "2016-04-13T20:28:04Z")

</div>

If you are using Dev (as I assume by your screenshot) you’d need to have the library files locally stored in your project folder _and_ `#include "SdFat.h"` I’d say.

But actually I’d rather do this in Build since `SdFat` is quite an elaborate library to include locally 😉

[Previous page](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145.md?page=1)

[Next page](https://community.particle.io/t/particle-photon-oled-screen-and-sd-card-demo/18145.md?page=3)
