Data logging with code using SPI OLED

Hi,
I’m using your very nice library for writing text data to an SPI OLED, and I really like being able to switch easily between large or small text. The issue with the code below is that when I turn data logging “on” with a compile directive the data are correctly logged – in the example about once every 15 seconds – but data are no longer displayed on the OLED.
Clearly, there is some kind of conflict between these two SPI devices – the OLED and the SD card. I know (or assume?) that when setting up the SPI connections for the OLED, I should use a CS pin other than 10, which is hard-wired on the data logging shield. Any suggestions how to fix this issue, so that data are displayed on the OLED (updating about once per second in the code) even while data are being logged?
Any help will be greatly appreciated!

#define DELAYTIME 1000L
#define SMALL 1
#define LOG 1
#include <PololuOLED.h>
  // SPI pins in this order: CLK(SCK), MOS(SDA), RES, DC, CS
  // CS to 7 instead of 10 to avoid conflict with data logger?
  PololuSH1106 display(13, 11, 8, 9, 7);
// thermistor setup
  const float B=3950.,R_base=100000.;
  const int R_Pin=A1; float V_T,V_R,R_T,T_thermistor;
  float T_base=25+273.15; // Base temperature to kelvins.
// RTC setup
  #include <Wire.h>
  #include <RTClib.h>
  RTC_DS1307 rtc;  // old dataloggers
  //RTC_PCF8523 rtc; // new dataloggers
  int YR,MON,DAY,HR,MIN,SEC;
// logging setup
  #if LOG
    #include <SPI.h>
    #include <SD.h>
    const int SDpin=10; // For UNO data logging shield.
    File logfile;
    char filename[]="SPI_TEST.CSV";
    const int N=15; int cnt=0.;
  #endif LOG  
void setup() {
  Wire.begin(); rtc.begin();
  #if LOG
    if (!SD.begin(SDpin)) Serial.println("Card failed.");
    Serial.println("card initialized.");
    logfile = SD.open(filename, FILE_WRITE);
    if (!logfile) Serial.println("Couldn't create file.");   
    Serial.print("Logging to file "); Serial.println(filename);      
    // Optionally, write header line here, with logfile.flush
    logfile.println("file header...");
    logfile.flush();      
  #endif LOG
  display.noAutoDisplay();
  display.rotate180();
  #if SMALL
    display.setLayout21x8(); // 21 characters in 8 rows
    display.gotoXY(0,0); display.print("Small");
    display.gotoXY(0,1); display.print("OLED font");
    display.gotoXY(0,2); display.print("21x8 chars");
  #else
    display.setLayout11x4(); // 11 characters in 4 rows
    display.gotoXY(0,0); display.print("Basic");
    display.gotoXY(0,1); display.print("OLED font");
    display.gotoXY(0,2); display.print("11x4 chars");
  #endif SMALL
  display.display();   delay(2000);
  display.gotoXY(0,2); display.print("           ");
  display.display();
}
void loop() {
  DateTime now=rtc.now();
  YR=now.year(); MON=now.month();
  DAY=now.day();
  HR=now.hour(); MIN=now.minute(); SEC=now.second();
  V_R=5.*analogRead(R_Pin)/1023;
  //V_R is the voltage across the resistor.
  // 5. - V_R is the voltage across the thermistor.
  V_T=5.-V_R; R_T=R_base*V_T/V_R;
  // In Arduino programming log() is the natural logarithm.
  T_thermistor=(1./((log(R_T/R_base)/B)+(1./T_base)))-273.15;
  //Serial.print("thermistor T: "); Serial.println(T_thermistor,2);
  #if SMALL
    display.setLayout21x8();
  #else
    display.setLayout11x4();
  #endif SMALL  
  display.gotoXY(0,0);
  display.print("Thermistor:");
  display.gotoXY(0,1); display.print("           ");
  display.gotoXY(0,1);
  display.print(T_thermistor,1);display.print(" C");
  display.gotoXY(0,3); display.print("           ");
  display.gotoXY(0,3);
   if (HR<10) display.print('0');
  display.print(HR);display.print(':');
  if (MIN<10) display.print('0');display.print(MIN);
  display.print(':');
  if (SEC<10) display.print('0');display.print(SEC);
  display.display();
  #if LOG
    cnt++;
    if(cnt==N) {
      logfile.print(YR); logfile.print('/');
      logfile.print(MON);logfile.print('/');
      logfile.print(DAY);logfile.print(' ');
      logfile.print(HR); logfile.print(':');
      logfile.print(MIN);logfile.print(':');
      logfile.print(SEC);logfile.print(',');
      logfile.print(DAY+HR/24.+MIN/1440.+SEC/86400.,6);
      logfile.print(',');
      logfile.print(T_thermistor,2);
      logfile.println();logfile.flush(); cnt=0;
    }
  #endif LOG
  delay(DELAYTIME);
}

Hello.

I am glad you have found our OLED library helpful.

It looks like you’re using hardware SPI for your datalogger; unfortunately, since our library uses software SPI and you’re using it on the same pins as your hardware SPI, they are conflicting. There are probably a number of ways you could go about getting around this issue, but making your own core class for the OLED library that uses hardware SPI would probably be my recommendation. If you have other free pins, you could also choose different ones for the OLED and the SD card (although I realize this somewhat defeats the purpose of a shared SPI bus).

Brandon

OK. Thanks! In fact, assigning pins like this:
//pins in order on OLED: SCK,SDA,RES,DEC,CS
PololuSH1106 display(7,6,5,4,3);
works just find and shouldn’t interfere with SPI pins required for using a data logger. Software serial is allegedly much slower that hardware Serial, but this isn’t a problem for my applications.

True, using code with this OLED and a data logger will up a LOT of digital pins but, again, this isn’t a problem for my applications which typically use I2C devices, with maybe something like a GPS module that uses a RX pin.

1 Like