Conflicts with Libraries (SSD1306 OLED & PCM/SD Audio)

If I include these 5 libraries in a program, the OLED functions will not work anywhere in the sketch. If I try to play audio within the same button press (for example, push a button, play a sound and pop a message on the OLED), the audio doesnt work.

If I place a simple function to put a message on the screen anywhere in the sketch, the speaker will play an irritating sound.

Any thoughts on the cause and what the solution might be if there is one?

#include <pcmRF.h>
#include <pcmConfig.h>
#include <TMRpcm.h>
#include <SD.h>

#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>

Which board?
Please provide your full code and some manner of schematic.
Sounds like you have some pin and/or timer conflicts, but who knows without more info?

Arduino UNO.

Initially I thought it was conflict with the library but research since I posted this suggests maybe it's a problem with utilizing SPI for both.

#include <pcmRF.h>
#include <pcmConfig.h>
#include <TMRpcm.h>
#include <SPI.h>
#include <SD.h>
#include <LedFlasher.h>
#include <Shifter.h>

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>

#define OLED_WIDTH 128
#define OLED_HEIGHT 64

#define OLED_ADDR   0x3C
#define OLED_RESET     4

Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT);

#define SER_Pin 1 //SER_IN
#define RCLK_Pin 2 //L_CLOCK
#define SRCLK_Pin 0 //CLOCK

#define NUM_REGISTERS 2 //how many registers are in the chain


//initaize shifter using the Shifter library
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS); 

// Setup - Scene 1 - The Motion Picture 
  const int TMPButton = 14; //TMP Button Pin
  int TMPButtonState = 0; //flag to check ig button has been pressed
  const int TMPTime [8] = {1760, 3240, 5080, 6720, 8560, 10200, 17000}; // Timeline in milliseconds between floodlights 
  const int TMPLed [7] = {8, 9, 10, 11, 12, 13, 14,};
  int TMPStart = 9360; // Time before first floodlight starts the sequence (in milliseconds)
  int TMPCounter = 0; // Counter used to keep track of floodlight number in sequence
  long TMPSeqStart = 0; // Time in milliseconds when drydocksequence was initiated
  long TMPSeqEnd = 0; // Variable used to check if it's time for the next floodlight to light up



// Setup - Scene 2 - The Wrath of Khan - Effect 1 
  const int TwokButton = 15; // TWOK Effect
  int TwokButtonState = 0; // flag to check if button has been pressed
  const int PreFixClock [5] = {1000, 1980, 2860, 3400, 19690}; // Timeline in milliseconds between floodlights 
  const int PreFix [5] = {1, 16, 163, 1630, 16309};
  int PreFixStart = 18500; // Start-up delay
  int PreFixStack = 1; // Variable used to calculate value to be written to 74HC595 Shift Register
  int PreFixTimer = 0; //Light Number variable 
  unsigned long PreFixSeq = 0; //
  unsigned long PreFixSeqStart = 0; // Time since sequence was started
  
 
 // Setup - Scene 2 - Effect 2   
  const int Phaser [2] = {19692, 23173}; // Phaser timing array 
  unsigned long PhaserStart = 0; // The time at which the phaser effect should start 
  int PhaserActive = 0; // The time at which the phaser effect should end 
  int PhaserCount = 0;
  int PhaserTimer = 0; 
  int PhaserState = 0; // Intitial phaser state when attemping to use Blink w/o delay
  const int PhaserLed = 6; // Phaser LED Pin 
  int PhaserBurst1 = 2280; // length of phaser burst in milliseconds
  int PhaserBurst2 = 2100; // length of phaser burst in milliseconds

  LedFlasher phaserLights (6, 25, 25);

// Setup - Scene 3 - The Search For Spock
  const int TSFSButton = 16;
  int TSFSButtonState = 0;
  const int TSFSLed = 0b00000001;
  long TSFSStart = 0;
  

// Setup - Scene 4 - The Voyage Home
  const int TVHButton = 17;
  int TVHButtonState = 0;
  const int TVHEnd = 5000; // Timeline in milliseconds between floodlights 
  int TVHStart = 27500; // Start-up delay
  const int TVHLed = 0b10000001;
  int TVHTimer = 0; //Light Number variable 
  unsigned long TVHDelay = 0; //
  unsigned long TVHSeqStart = 0; // Time since sequence was started
  unsigned long TVHOff = 0;

// Setup - Scene 5 - The Final Frontier 
const int TFFButton = 18;
  int TFFButtonState = 0;
  const int TFFLed = 0b0000010;
  unsigned long TFFStart = 0; // Save the Start time of the Button Press
  long TFFEnd = 10000;
  unsigned long TFFOff = 0;


// Setup - Scene 6 - The Undiscovered Country
  const int TUCButton = 19;
  int TUCButtonState = 0;
  const int TUCLed = 0b0000100;
  unsigned long TUCStart = 0; // Save the Start time of the Button Press
  long TUCEnd = 10000;
  unsigned long TUCOff = 0;
  

  char mychar;
  const int CS_PIN = 10;
  TMRpcm audio;

 

  void setup() 
  {
    display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
    display.clearDisplay();
  // Setup for TWOK Phaser
    phaserLights.begin (); // Initializes phaser lights
    pinMode (PhaserLed, OUTPUT); // Phaser LED on pin 6
    pinMode (TMPButton, INPUT); // Scene 1 - TMP - Pin 14
    pinMode (TwokButton, INPUT); //Scene 2 - TWOK - Pin 15
//  pinMode (TSFSButton, INPUT); //Scene 3 - TSFS - Pin 16  
    pinMode (TVHButton, INPUT); // Scene 4 - TVH - Pin 17 
//  pinMode (TFFButton, INPUT); // Scene 5 - TFF - Pin 18 
//  pinMode (TUCButton, INPUT); // Scene 6 - TUC - Pin 19   
    
  // Set up pins for audio effects
    audio.speakerPin = 9; // Speaker pin on output pin 9
    //Serial.begin(9600);
  //Serial.println("Initializing Card");
  pinMode(CS_PIN, OUTPUT);
  if(!SD.begin(CS_PIN)) {
    //Serial.println("Card Failure");
    return;
  }
  //Serial.println("Card Ready");
  audio.setVolume(5);
  audio.quality(1);
  

  

  
    }  // end of setup

void loop() // The main program
  {
  shifter.clear(); //set all pins on the shift register chain to LOW
//      display.clearDisplay();
//     display.setTextSize(3);
//     display.setTextColor(WHITE);
//     display.setCursor(10, 0);
//     display.println("TEST");  
  
// Scene 1 = The Motion Picture
  display.clearDisplay();
  TMPButtonState = digitalRead (TMPButton);
  if (TMPButtonState == HIGH){
    audio.play("Intro1.wav");
 TMPSeqEnd = millis() + TMPStart;
  while (millis() < TMPSeqEnd) {} // Wait around until it's time for the first floodlight to light up
  // Switch on LEDs 0 to 5 according to Timeline
  TMPSeqStart = millis(); // Marks the time when the timeline initiates (first floodlight zero-time)
  TMPSeqEnd = TMPSeqStart + TMPTime[1];
  for (TMPCounter = 0; TMPCounter < 7; TMPCounter +=1) {
   shifter.setPin(TMPLed[TMPCounter], HIGH);
   shifter.write(); 
    TMPSeqEnd = TMPSeqStart + TMPTime [TMPCounter];
    while (millis() < TMPSeqEnd) {} // Pause between floodlights
  }
  }
 shifter.clear(); //set all pins on the shift register chain to LOW
  shifter.write(); //send changes to the chain and display them
   
// Scene 2 = The Wrath of Khan 

// Scene 2 = The Wrath of Khan 

  TwokButtonState = digitalRead (TwokButton);
  if (TwokButtonState == HIGH){
//      audio.play("TWOK.wav");
   
   PhaserActive = 1;
   PreFixSeq = millis() + PreFixStart;
   while (millis() < PreFixSeq){}  //Do Nothing Until Correct Audio Time has Elapsed 

   PreFixSeqStart = millis(); // Marks time when first leds turns on 

 for(PreFixTimer; PreFixTimer < 5; PreFixTimer += 1){
       display.clearDisplay();
       display.setTextSize(3);
      display.setTextColor(WHITE);
      display.setCursor(10, 0);
      display.println("PREFIX");  
 
      display.setTextSize(4);
      display.setTextColor(WHITE);
      display.setCursor(4, 32);
      display.println(PreFix[PreFixTimer]);
      display.display();
    PreFixSeq = PreFixSeqStart + PreFixClock [PreFixTimer];
    while (millis() < PreFixSeq) {  } // Pauses between Prefix Lightup sequence

      }
  }
  PhaserStart = PreFixSeqStart + Phaser [0];
  if (PhaserStart == millis()){
    PhaserState = 1;
  }
  if (PhaserStart + PhaserBurst1 == millis()){
    PhaserState = 0;
  }
  if (PhaserState == 1 and PhaserActive == 1) { // if phasers are active then update phaser flash
    phaserLights.update ();    
  }
  else {
   digitalWrite (PhaserLed, 0); // otherwise switch phasers off...
  } 
  PhaserStart = PreFixSeqStart + Phaser [1];
  if (PhaserStart == millis()){
    PhaserState = 1;
  }
  if (PhaserStart + PhaserBurst2 == millis()){
    PhaserState = 0;
  }
  if (PhaserState == 1 and PhaserActive == 1) { // if phasers are active then update phaser flash
    phaserLights.update ();    
  }
  else {
   digitalWrite (PhaserLed, 0); // otherwise switch phasers off...
  } 
  


//  TWOKButtonState = digitalRead (TWOKButton);
//  if (TWOKButtonState == HIGH){
//     audio.play("TWOK.wav");
 //   PhaserActive = True;
//   TWOKSeq = millis() + TWOKStart;
//   while (millis() < TWOKSeq){}  //Do Nothing Until Correct Audio Time has Elapsed 
   
//   TWOKSeqStart = millis(); // Marks time when first leds turns on 
  
//  for(TWOKCounter; TWOKCounter < 5; TWOKCounter += 1){
//    shifter.setPin(TWOKLed[TWOKCounter], HIGH);
//    shifter.write();
//   TWOKSeq = TWOKSeqStart + TWOKTimer[TWOKCounter];
//   while (millis() < TWOKSeq) {  } // Pauses between Prefix Lightup sequence
//    }
//    shifter.clear(); //set all pins on the shift register chain to LOW
//    shifter.write(); //send changes to the chain and display them
//  }

//}
  
// Scene 3 - The Search For Spock

// Scene 4 - The Voyage Home
//  TVHButtonState = digitalRead (TVHButton);
//  if (TVHButtonState == HIGH){
//      audio.play("TVH.wav");
//     TVHDelay = millis() + TVHStart;
// while (millis() < TVHDelay){}  //Do Nothing Until Correct Audio Time has Elapsed   
//    TVHSeqStart = millis();
//    digitalWrite (latchPin1, LOW); // Turn ON Saucer Spotlight
//    shiftOut (dataPin1, clockPin1, MSBFIRST, TVHLed);
//    digitalWrite (latchPin1, HIGH);
//    TVHOff = TVHSeqStart + TVHEnd;
 // while(millis() < TVHOff){}
 // digitalWrite (latchPin1, LOW); // Turn OFF Saucer Spotlight LED
  //  shiftOut (dataPin1, clockPin1, MSBFIRST, 0);
 //   digitalWrite (latchPin1, HIGH);
//  }
 

// Scene 5 - The Final Frontier

//  TFFButtonState = digitalRead (TFFButton);
//  if (TFFButtonState == HIGH){
//      audio.play("TFF.wav");
//    TFFStart = millis();   
//    digitalWrite (latchPin, LOW); // Turn ON Observation Lounge LED
//    shiftOut (dataPin, clockPin, LSBFIRST, TFFLed);
//   digitalWrite (latchPin, HIGH);
//    TFFOff = TFFStart + TFFEnd;
//  while(millis() < TFFStart + TFFEnd){}
//  digitalWrite (latchPin, LOW); // Turn OFF Officer's Lounge LED
//    shiftOut (dataPin, clockPin, MSBFIRST, 0);
//    digitalWrite (latchPin, HIGH);
//  }


// Scene 6 = The Undiscovered Country 
 
//  TUCButtonState = digitalRead (TUCButton);
//  if (TUCButtonState == HIGH){
//      audio.play("TUC.wav");
//    TUCStart = millis();   
//   digitalWrite (latchPin, LOW); // Turn ON Officer's Lounge LED
//    shiftOut (dataPin, clockPin, LSBFIRST, TUCLed);
//    digitalWrite (latchPin, HIGH);
//    TUCOff = TUCStart + TUCEnd;
//  while(millis() < TUCStart + TUCEnd){}
//  digitalWrite (latchPin, LOW); // Turn OFF Officer's Lounge LED
//    shiftOut (dataPin, clockPin, MSBFIRST, 0);
//    digitalWrite (latchPin, HIGH);
//  }

  
 

  
  }  // end of loop

Are you using the same CS line for both?
You need separate CS for each, then you can add as many SPI devices as you have spare pins.

Can you elaborate on that a bit? I'm not sure what you mean by CS line? Nor do I know how to make a separate line for each?

Start reading here:
How to Connect Multiple SPI devices to an Arduino Microcontroller (learningaboutelectronics.com)

Perfect! Much appreciated!

Based on this, I'm not sure if this is the problem now..

I'm not actually using SPI for the OLED display. It's utilizing I2C pins A4 & A5. The SPI library is required for compiling but the component isn't running on SPI.

Here is the page for your library
It can be used as SPI or I2C
Navigate the folders to the I2C examples.
I suggest you get the display working on its own first.

I've done that. As I said in the original post, I can get one or the other working but not both.

In fact, if I comment out the pcm libraries and the SD library, the OLED will work.. similarly if I comment out the OLED adafruit libraries, the audio works again...

I've pulled the snippet of code I'm working with, which in the main code above is Scene 2 - The Wrath of Khan, and placed into a new sketch WITHOUT the pcm audio libraries, and I can get the OLED to fire up and do exactly what I want, which is display a sequence of numbers on the screen within a certain timeframe.

I have no issue getting the OLED code to work on its own.

An Uno, right?

Using pin0 on an Uno has some issue with Serial comms.

Have you connected one I2C device, run I2C scanner, see 1 address, add another I2C device, run scanner, see 2 I2C devices, add another and so on and so forth to make sure all the devices have their own address.

No. But I'll look into what all that means and try it!

I'll also try to use a different pin for the shift register. I have noticed that the register does some funky things now when it's uploading new sketches.

I woudn't have thought the register was the issue since it still works fine and doesnt seem to have an issue running with either, but certainly work a look!

If you look at the code in the loop, Scene 1 - The Motion Picture plays audio and runs effects on the Shift register just fine.

Scene 2 - the Wrath of Khan goes mental when I try to run the audio and the OLED at the same time.

I'm in the don't use pin0 on a Uno camp. But:

[quote]You can use pins 0 and 1 as normal GPIO pins (input, input_pullup or output), as long as you're not using the hardware UART (i.e. if you don't call Serial.begin(...)).
If you connect pins 0 and 1 to some peripheral that has a low-impedance path to ground or 5v (like a switch, for example, or the output of a digital device), this could possibly short out the TX pin of the Arduino during a Serial transmission or during upload.

On a genuine Arduino board, the USB-to-Serial converter has a resistor in series with the TX pin, so you won't damage that pin when connecting something to the RX pin of the Arduino. However, you won't be able to receive anything.

This just means that you have to disconnect whatever is connected to pins 0 and 1 during upload.
During the execution of the program, you can do whatever you want with them.
[/quote]
From: Using digital pin 0 and 1 just like any other Digital Pin? - Using Arduino / Installation & Troubleshooting - Arduino Forum

You feel you are in line with the above?

What's the RAM used report you get?

I think I'm good with pin 0.

With RAM used, 72%.

I have been trouble shooting this all evening.

If you go back to my original post, I can run the entire code fine with OLED if I comment out the pcm and SD libraries.

If they're called upon, the OLED will do nothing.

My only thought is RAM use otherwise, at this point I'd have to run the code, and I do not have your hardware to reproduce the issue.

I appreciate you trying to help!

Thanks!

Here is my circuit schematic. I'm sorry that it's terribly bad.. This is the first time I've made one.

I didnt include the 10k Pull Downs on the 3 buttons, nor the 100ohm resistors on all the LEDS.

I still can't get this thing to work... I did find this library which apparently could work.. I just can't parse the commands to use in the main sketch. ex. current library I use display.display() to push the message to the OLED.

I would really LOVE to get this working with the audio

Okay. I think I finally solved this issue.

Things compile fine, but the two things, audio/sd card and OLED running at the same time blow through the UNO's RAM.

If I want this to work, I might have to move to something bigger like a Teensy 3.2 to get the RAM needed for both the audio and the OLED.... bummer..

I might abandon the effect altogether and run two ATMega's in my project. One doing some random stuff on the OLED, the other running the audio scenes.

super.

super.

cool.