How to find library clash issue

Hi

I have an ATmega328p IC, programmed using UNO as the processor.
I have an 0.96" Oled on the I2C bus.

I want to use a DMX library with it, but if I use any DMX library (DMXsimple, DMXserial or DMXserial2) it stops the screen working and I cannot work out why.

The code is horrible, as I have commented out bits to try and narrow down the culprit.

Using USBasp to upload, so no serial debug. But it doesn't throw up an error when loaded.

Screen loads text when the DMX library's are commented out

//#include <Wire.h>                                                                                                 // I2C comms
//#include <SPI.h>                                                                                                  // Serial comms

//#include <DMXSerial.h>                                                                                            // DMX library. 
#include <DMXSerial2.h>

//#include <Bounce2.h>                                                                                              // Button bouce library
#include <Adafruit_GFX.h>                                                                                         // Graphics library
#include <Adafruit_SSD1306.h>                                                                                     // Oled screen
// include <EEPROM.h>                                                                                               // EEPROM                   ---  Already included in the DMXserial library?
// include <Servo.h>                                                                                               // Servo library

//Bounce enterbutton = Bounce();
//Bounce selectbutton = Bounce();

#define SCREEN_WIDTH 128                                                                                          // OLED display width, in pixels
#define SCREEN_HEIGHT 64                                                                                          // OLED display height, in pixels
#define OLED_RESET    -1                                                                                          // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//#define enterbutton A7
#define pin1 2
#define pin3 3
#define pin4 4
#define pin5 5
#define pin6 6
#define pin7 7
#define pin8 8
#define pin9 9
#define pin10 10
// Pin 11 = Mosi
// Pin 12 = Miso
// Pin 13 = SCK
//#define selectbutton 14
#define heartbeat 15
#define pin2 16
#define DMXdirection 17
// Pin 18 SDA
// Pin 19 SCL

unsigned long currentMillis;                   // Timing variables
unsigned long heartbeatMillis;

byte h;                                        // BMP display variables
byte w;
byte row;
byte col;
int buffidx = 0;

int RXDMXaddress = 0;                          // DMX variables
int TXDMXaddress = 0;
int TXDMXvalue = 0;
int RXDMXvalue = 0;
int OldRXDMXvalue = 0;

//----------------------------------------------------------------------------------------------------------------------------------------------------------------
void setup() {
  pinMode (heartbeat, OUTPUT);
  pinMode (DMXdirection, OUTPUT);
  //pinMode (enterbutton, INPUT);
  //pinMode (selectbutton, INPUT);
  pinMode (pin1, INPUT);
  pinMode (pin2, INPUT);
  pinMode (pin3, INPUT);
  pinMode (pin4, INPUT);
  pinMode (pin5, INPUT);
  pinMode (pin6, INPUT);
  pinMode (pin7, INPUT);
  pinMode (pin8, INPUT);
  pinMode (pin9, INPUT);
  pinMode (pin10, INPUT);

  Wire.begin();

  //DMXSerial.init(DMXReceiver);
  //DMXSerial.init(DMXController);

  //enterbutton.attach(A7,  INPUT);
  //selectbutton.attach(14,  INPUT);
  //enterbutton.interval(5);                                                                            // interval in ms
  //selectbutton.interval(5);                                                                           // interval in ms

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);                                                

  digitalWrite(DMXdirection, HIGH);

  //----------- Set the display up-------------

  // Clear the buffer.
  display.clearDisplay();

  display.drawRoundRect(0, 0, 128, 64, 4, WHITE);                                                     // Draws a rectangle with rounded corners.  Starts at 0,0 (top left) and then 128 wide x 64 high with corners rounded to radius 4
  display.drawRoundRect(2, 2, 124, 60, 4, WHITE);

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(24, 8);
  display.println(F("DMX CONTROLLER"));
  display.display();

  delay(1000);
}


//#####################################################################################################################
void loop() {

  currentMillis = millis();

  if (currentMillis - heartbeatMillis == 1000) {
    digitalWrite(heartbeat, HIGH);
  }

  if (currentMillis - heartbeatMillis > 2000) {
    heartbeatMillis = currentMillis;
    digitalWrite(heartbeat, LOW);
  }



  // DMXSerial.write(TXDMXaddress, TXDMXvalue);   // Send a DMX value

/*
  unsigned long lastPacket = DMXSerial.noDataSince();                                               // Calculate how long no data packet was received

  if (lastPacket < 5000) {                                                                          // Read DMX value
    RXDMXvalue = DMXSerial.read(RXDMXaddress);

    if (RXDMXvalue != OldRXDMXvalue) {
      //display.fillRect(100, 45, 20, 12, BLACK);
      //display.setCursor(102, 47);
      //display.println(RXDMXvalue);
      //display.display();
    }
    OldRXDMXvalue = RXDMXvalue;

  } else {                                                                                          // Display DMX Receive error
    //display.fillRect(100, 45, 20, 12, BLACK);
    //display.setCursor(102, 47);
    //display.println("ERR");
    //display.display();
  }
*/
}
//#####################################################################################################################

OK. in DMXSerial.h, the DMXMODEPIN is defaulted to pin 2. If I change that to 17 (my pin), it works.

So, how do I change that pin in my code, rather than change it in the library? (can you do that?)

#define DMXMODEPIN (17)

Pointless thread! Sorry

OH, ok, now the Bounce2 stops the screen working.

This is painful

Cannot use bounce on ADC7 anyway, so just using standard analogue input.

All now loading, except as soon as I call the screen print command, it hangs e.g: display.println("Test"); doesn't work.

Ideas? Comment out the DMXSerial.init(DMXReceiver); and it works again.

Goddam libraries

Anyone? I believe it is a clash between the graphics library and the DMX library
I cannot find replacements (that work) for these, so any suggestions?
Been through the library files and looked for anything obvious, but I can't see anything.

The whole thing will load fine, except the line display.println(F("DMX CONTROLLER")); makes it hang.

Something maybe to do with serial? (the DMX uses the default serial port)

You showed only small pieces of your code - it makes no sense to look for an error in them...
If the program hangs without an error message, then it is usually a problem with memory or incorrect access to it.

That's the whole code.... it's only for testing

Bits that are commented out are not needed for testing.
During the initial screen draw, the graphics border draws fine, but it hand if you uncomment the text command.

#include <Wire.h>                                                                                                 // I2C comms
#include <SPI.h>                                                                                                  // Serial comms

#include <Adafruit_GFX.h>                                                                                         // Graphics library
#include <Adafruit_SSD1306.h>                                                                                     // Oled screen       Adafruit SSD1306.H has list of commands

#include <DMXSerial.h>                                                                                            // DMX library.
//#include <DMXSerial2.h>                                                                                         // DMX library. Includes EEPROM.h and RDM but it's not fully implemented

//include <EEPROM.h>                                                                                              // EEPROM
//include <Servo.h>                                                                                               // Servo library

#define DMXMODEPIN (17)                                                                                           // Define the DMX direction change pin (it's pin 2 default in the DMXSerial library)
#define DMX_USE_PORT0
#define DMXSPEED 250000L

#define SCREEN_WIDTH 128                                                                                          // OLED display width, in pixels
#define SCREEN_HEIGHT 64                                                                                          // OLED display height, in pixels
#define OLED_RESET    -1                                                                                          // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define enterbutton A7
#define pin1 2
#define pin3 3
#define pin4 4
#define pin5 5
#define pin6 6
#define pin7 7
#define pin8 8
#define pin9 9
#define pin10 10
// Pin 11 = Mosi
// Pin 12 = Miso
// Pin 13 = SCK
#define selectbutton 14
#define heartbeat 15
#define pin2 16
#define DMXdirection 17
// Pin 18 SDA
// Pin 19 SCL

unsigned long currentMillis;                   // Timing variables
unsigned long heartbeatMillis;

byte h;                                        // BMP display variables
byte w;
byte row;
byte col;
int buffidx = 0;

int RXDMXaddress = 0;                          // DMX variables
int TXDMXaddress = 0;
int TXDMXvalue = 0;
int RXDMXvalue = 0;
int OldRXDMXvalue = 0;

//----------------------------------------------------------------------------------------------------------------------------------------------------------------
void setup() {
  pinMode (heartbeat, OUTPUT);
  pinMode (DMXdirection, OUTPUT);
  pinMode (enterbutton, INPUT);
  pinMode (selectbutton, INPUT);
  pinMode (pin1, INPUT);
  pinMode (pin2, INPUT);
  pinMode (pin3, INPUT);
  pinMode (pin4, INPUT);
  pinMode (pin5, INPUT);
  pinMode (pin6, INPUT);
  pinMode (pin7, INPUT);
  pinMode (pin8, INPUT);
  pinMode (pin9, INPUT);
  pinMode (pin10, INPUT);

  Wire.begin();

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

 DMXSerial.init(DMXReceiver);                       
 DMXSerial.init(DMXController);            
 // DMXSerial.init(DMXProbe);            //Both ways?         

  digitalWrite(DMXdirection, HIGH);

  //----------- Set the display up-------------

  // Clear the buffer.
  display.clearDisplay();

  display.drawRoundRect(0, 0, 128, 64, 4, WHITE);                                                     // Draws a rectangle with rounded corners.  Starts at 0,0 (top left) and then 128 wide x 64 high with corners rounded to radius 4
  display.drawRoundRect(2, 2, 124, 60, 4, WHITE);

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(24, 8);
  //display.print(F("DMX CONTROLLER")0;          // This causes it to hang
  display.display();

/*
  delay(1000);
  
    h = 64;                                                                 // Cods logo
    w = 128;
    buffidx = 0;
    for (row = 0; row < h; row++) {                                         // For each scanline...
      for (col = 0; col < w; col++) {                                       // For each pixel...
        display.drawPixel(col, row, pgm_read_word(Codslogo + buffidx));         // To read from Flash Memory, pgm_read_XXX is required.   Since image is stored as uint16_t, pgm_read_word is used as it uses 16bit address
        buffidx++;
      }                                                                     // end pixel
    }
  */
}


//#####################################################################################################################
void loop() {

  currentMillis = millis();

  if (currentMillis - heartbeatMillis == 1000) {
    digitalWrite(heartbeat, HIGH);
  }

  if (currentMillis - heartbeatMillis > 2000) {
    heartbeatMillis = currentMillis;
    digitalWrite(heartbeat, LOW);
  }

  //--------------------- Buttons ----------------------

  int entervalue = analogRead(enterbutton);
    if (entervalue>800) {                                      // The ENTER button is analogue only
      digitalWrite(heartbeat, HIGH);
      delay(5000);
      digitalWrite(heartbeat, LOW);
    }
  
    if (digitalRead(selectbutton) == HIGH) {
      display.clearDisplay();
      digitalWrite(heartbeat, HIGH);
      delay(3000);
      digitalWrite(heartbeat, LOW);
    }


  //----------------------- DMX --------------------------

  // DMXSerial.write(TXDMXaddress, TXDMXvalue);   // Send a DMX value

  /*
    unsigned long lastPacket = DMXSerial.noDataSince();                                               // Calculate how long no data packet was received

    if (lastPacket < 5000) {                                                                          // Read DMX value
      RXDMXvalue = DMXSerial.read(RXDMXaddress);

      if (RXDMXvalue != OldRXDMXvalue) {
        //display.fillRect(100, 45, 20, 12, BLACK);
        //display.setCursor(102, 47);
        //display.println(RXDMXvalue);
        //display.display();
      }
      OldRXDMXvalue = RXDMXvalue;

    } else {                                                                                          // Display DMX Receive error
      //display.fillRect(100, 45, 20, 12, BLACK);
      //display.setCursor(102, 47);
      //display.println("ERR");
      //display.display();
    }
  */
}
//#####################################################################################################################

Post the minimal code that causes the error. And not code where half of the pieces are commented out, but not removed from the code. How is an outsider supposed to figure out what to take into account and what not?
Otherwise, don't be surprised that no one wants to help you. To begin with, do not create additional problems for others.

So, if I select Pro or Pro-mini, it uploads and works (not Uno)

What's that about

What the Arduino IDE say after compiling about the memory usage?

Sketch uses 15108 bytes (49%) of program storage space. Maximum is 30720 bytes.
Global variables use 882 bytes (43%) of dynamic memory, leaving 1166 bytes for local variables. Maximum is 2048 bytes.

But it says the same when UNO is selected

In DMXSerial.h the default direction pin is selected using:

#define DMXMODEPIN 2 ///< Arduino pin for controlling the data direction is the default value.

In my setup code I added:
#define DMXMODEPIN 17

As I need to change this pin allocation, but it doesn't change it. Ideas?

So you change the pin allocation in the library and it all works. Go to bed happy.

Next day....doesn't work again. I just don't get it

I realise nobody is following this thread but whatever...

So, it now clashes with the Servo library (and all other servo librarys I could fnd).
The DMX library clearly is timer heavy and basically uses up all the resources.

So, my single servo will need to be controlled manually (using micros?). I believe the signal is 20000ms or something.

Ho do I implement that, so that the timing is always correct each loop, accounting for other processes that may slow the loop down?

Am I going entirely mad here.... ATmega328p

Why doesn't the timer work for the servo update in the main loop? (Its a horrible method, but 24hrs later and every conceivable library checked, it's all I have)

This 300ms servoMillis timer check freezes the loop. I cannot see why. Its the same method as the (to be removed) heartbeat led timer at the start of the main loop.

  All known servo library's clash with the timers used by the DMX library
*/

#include <Wire.h>                                                                                                 // I2C comms
#include <SPI.h>                                                                                                  // Serial comms

#include <DMXSerial.h>                                                                                            // DMX library.
//#include <DMXSerial2.h>                                                                                         // DMX library. Includes EEPROM.h and RDM but it's not fully implemented

#include <Adafruit_GFX.h>                                                                                         // Graphics library
#include <Adafruit_SSD1306.h>                                                                                     // Oled screen (Adafruit SSD1306.H has list of commands)

#include <EEPROM.h>                                                                                               // EEPROM

//#define DMXMODEPIN 17                                                                                           // Define the DMX direction change pin (it's pin 2 default in the DMXSerial library)
//#define DMX_USE_PORT0                                                                                           // ATmega328p only has one serial port (0)
//#define DMXSPEED 250000L                                                                                        // Already defined in the library

#define SCREEN_WIDTH 128                                                                                          // OLED display width, in pixels
#define SCREEN_HEIGHT 64                                                                                          // OLED display height, in pixels
#define OLED_RESET    -1                                                                                          // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Pin 0 = Serial RX                     Incoming DMX data
// Pin 1 = Serial TX                     Transmitted DMX data
#define pin1 2                           // PCINT18
#define pin3 3                           // PCINT19 - PWM
#define pin4 4                           // PCINT20
#define pin5 5                           // PCINT21 - PWM
#define pin6 6                           // PCINT22 - PWM - AIN0
#define pin7 7                           // PCINT23 - AIN1
#define pin8 8                           // PCINT0
#define pin9 9                           // PCINT1 -  PWM
#define pin10 10                         // PCINT2 -  PWM - SS
// Pin 11 = Mosi                         //  Used for programming but actually are available on the programming header
// Pin 12 = Miso                         //  Used for programming but actually are available on the programming header
// Pin 13 = SCK                          //  Used for programming but actually are available on the programming header
#define selectbutton 14                  // // Onboard/remote SELECT button (PCINT8 - A0 - ADC0)
#define heartbeat 15                     // Onboard LED indicator
#define pin2 16                          // PCINT10 - A2 - ADC2
#define DMXdirection 17                  // HIGH = Transmit.  LOW = Receive
// Pin 18 SDA                            // I2C SDA to onboard OLED screen
// Pin 19 SCL                            // I2C SCL to onboard OLED screen
#define enterbutton A7                   // Onboard/remote ENTER button

unsigned long currentMillis;             // Timing variables
unsigned long heartbeatMillis;
unsigned long servoMillis;

bool servodir;
byte servoangle;

int entervalue;                          // Analogue value from the ENTER button pin

int RXDMXaddress = 0;                    // DMX variables
int TXDMXaddress = 0;
int TXDMXvalue = 0;
int RXDMXvalue = 0;
int OldRXDMXvalue = 0;

//----------------------------------------------------------------------------------------------------------------------------------------------------------------
void setup() {
  pinMode (heartbeat, OUTPUT);
  pinMode (DMXdirection, OUTPUT);
  pinMode (enterbutton, INPUT);
  pinMode (selectbutton, INPUT);
  pinMode (pin1, INPUT);
  pinMode (pin2, INPUT);
  pinMode (pin3, INPUT);
  pinMode (pin4, INPUT);
  pinMode (pin5, INPUT);
  pinMode (pin6, INPUT);
  pinMode (pin7, INPUT);
  pinMode (pin8, INPUT);
  pinMode (pin9, OUTPUT);
  pinMode (pin10, OUTPUT);

  Wire.begin();

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  //DMXSerial.init(DMXReceiver);                      // DMX receiver
  DMXSerial.init(DMXController);                      // DMX transmitter
  digitalWrite(DMXdirection, HIGH);                   // Enable transmit

  //----------- Set the display up-------------

  display.clearDisplay();                             // Clear the buffer.

  display.drawRoundRect(0, 0, 128, 64, 4, WHITE);     // Draws a rectangle with rounded corners.  Starts at 0,0 (top left) and then 128 wide x 64 high with corners rounded to radius 4
  display.drawRoundRect(2, 2, 124, 60, 4, WHITE);

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(8, 8);
  display.print(F("DMX CONTROLLER"));
  display.display();
}

// ------------ Servo move (blocking) -----------

void movePulse(int x) {
  int del = (7 * x) + 500;
  for (int pulseCounter = 0; pulseCounter <= 50; pulseCounter++) {
    digitalWrite(9, HIGH);
    delayMicroseconds(del);
    digitalWrite(9, LOW);
    delay(20); // between pulses
  }
}



//#####################################################################################################################
void loop() {

  currentMillis = millis();

  if ((currentMillis - heartbeatMillis > 1000) and (currentMillis - heartbeatMillis < 1100)) {
    digitalWrite(heartbeat, HIGH);
  }

  if (currentMillis - heartbeatMillis > 2000) {
    heartbeatMillis = currentMillis;
    digitalWrite(heartbeat, LOW);
  }

  //--------------------------------------------- Buttons/Inputs ----------------------------------------------

  entervalue = analogRead(enterbutton);
  if (entervalue > 800) {                                    // The ENTER button is analogue only
    display.print(F("ENTER"));
    display.display();
    do {
      entervalue = analogRead(enterbutton);
    } while (entervalue > 800);
  }

  if (digitalRead(selectbutton) == HIGH) {
    display.print(F("SELECT"));
    display.display();
    do {} while (digitalRead(selectbutton) == HIGH);
  }

  if (digitalRead(pin1) == HIGH) {
    display.print(F("1"));
    display.display();
  }
  /*
    if (digitalRead(pin2) == HIGH) {
      display.print(F("2"));
      display.display();
    }
    if (digitalRead(pin3) == HIGH) {
      display.print(F("3"));
      display.display();
    }
    if (digitalRead(pin4) == HIGH) {
      display.print(F("4"));
      display.display();
    }
    if (digitalRead(pin5) == HIGH) {
      display.print(F("5"));
      display.display();
    }
    if (digitalRead(pin6) == HIGH) {
      display.print(F("6"));
      display.display();
    }
    if (digitalRead(pin7) == HIGH) {
      display.print(F("7"));
      display.display();
    }
    if (digitalRead(pin8) == HIGH) {
      display.print(F("8"));
      display.display();
    }
    if (digitalRead(pin9) == HIGH) {
      display.print(F("9"));
      display.display();
    }
    if (digitalRead(pin10) == HIGH) {
      display.print(F("10"));
      display.display();
    }
  */

  //----------------------- Servo output (cannot be done with Servo libraries due to timer clashes) -------------------

  if (currentMillis - servoMillis > 300) {
    servoMillis = currentMillis;
/*
    if ((servoangle < 181) and (servodir == 0)) {
      servoangle++;
    }
    else
    {
      servodir = 1;
    }

    if ((servoangle > 0) and (servodir == 1)) {
      servoangle--;
    }
    else
    {
      servodir = 0;
    }

    movePulse(servoangle);
 */   
  }

  //------------------------------------------------------ DMX --------------------------------------------------------

  // DMXSerial.write(TXDMXaddress, TXDMXvalue);   // Send a DMX value

  /*
    unsigned long lastPacket = DMXSerial.noDataSince();                                               // Calculate how long no data packet was received

    if (lastPacket < 5000) {                                                                          // Read DMX value
      RXDMXvalue = DMXSerial.read(RXDMXaddress);

      if (RXDMXvalue != OldRXDMXvalue) {
        //display.fillRect(100, 45, 20, 12, BLACK);
        //display.setCursor(102, 47);
        //display.println(RXDMXvalue);
        //display.display();
      }
      OldRXDMXvalue = RXDMXvalue;

    } else {                                                                                          // Display DMX Receive error
      //display.fillRect(100, 45, 20, 12, BLACK);
      //display.setCursor(102, 47);
      //display.println("ERR");
      //display.display();
    }
  */
}

Maybe someone can explain to me why this doesn't work.

Can't use any timers, as the resource hungry DMX library uses everything up.

If I load Servo.h and use pin10 (where my servo is), the sweep demo works fine.

So why does this basic method fail entirely to move the servo at all?


#define pin10 10

unsigned int pos = 500;
int pulse = 20;

void setup() {
  pinMode (pin10, OUTPUT);

}

void loop() {
  digitalWrite(pin10, HIGH);
  delayMicroseconds(pos);
  digitalWrite(pin10, LOW);
  delay(pulse);
}

I understood that servos need a 20ms signal, which is approx 500us for 0 degrees to 2500ms for 180 deg. Nothing

500uS may be a bit short for some servos, try 1500uS as a midpoint and experiment from there.

I have been playing around. Turned out the range was 710 to 2300

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.