Arduino Due I2C Integration

I'm building a project using the Arduino Due. I have an EEPROM (CAT24C512 ) that I am trying to store user data to. I am having issues getting it to run in my machine source code. I've used the IC successfully as well as another I2C IC (MMA8452Q) on a Sparkfun Redboard Plus (3.3v). I have been able to run the MMA8452Q and EEPROM on the Due when it is disconnected from a carrier board that is used for connections to peripheral devices (encoder, motor, etc). I can even get them both (sample programs from Sparkfun) to work when connected to the carrier board. However, when I try to integrate the EEPROM code into my machine code it hangs up on the .begin function and returns 0. I have included my other #includes below in case there is a conflict.

Any thoughts?

#include <PID_v2.h> //PID position control on the motor
#include <Wire.h> //EEPROM
#include <AccelStepper.h> //stepper motor driver
#include "SparkFun_External_EEPROM.h" //EEPROM
#include <Encoder.h> //user input encoder
#include "Nextion.h" //Nextion HMI

Arduino IDE 1.8.16
Using Wire (pin 20/21)

Sparkfun Redboard Plus (3.3v) : https://www.sparkfun.com/products/18158
That is a ATmega328P, 3.3V, 16MHz.

Can you tell more ?

Is that carrier board connected to the Due or not ? Can you give a link to that carrier board ? Can you show a photo of the project ?

If the examples sketches from Sparkfun work, then I assume you test one example sketch at a time ? (not combined).

Let's see : 50k // 4k7 // 10k // 1k5 = 1000 Ω
Your combined pullup resistor for the I2C bus is 1000 Ω, that means the sink current (to pull SDA or SCL low) is 3.3 mA and 3 mA is the maximum.
That's not so bad, but not ideal.

Can you show the full sketch between code tags ?

```
Your sketch
```

Did you download the AccelStepper from a random location, or are you sure that you have the latest version from the author ?
To which Serial port is the Nextion connected ?

It can be a memory problem, or a library conflict, or hardware, or something specific for the Due (the Due has issues of its own).
To deal with such a complex problem, you can make a sketch that only uses those two I2C devices (connect only those to the Arduino board and make a sketch that only uses those), and then step-by-step add the rest. It is normal to have a number of test sketches.

Thanks for the reply. I will try to answer as best as possible. The carrier board (images attached) is of my own design that I had printed through PCBWay and soldered. It is mostly just headers and connectors for the various peripherals. It has a set of headers for the Due to attach to.

I have tested the example sketches one at a time only. The final project only uses the EEPROM. I was using the other device only as a means to debug the system and make sure it wasn't an issue with the EEPROM breakout board/code.

Can you expound more on the combined resistance on the I2C bus? I am aware of the internal pull-up resistors on SDA/SCL where are the others? ....I just noticed the resistors on the breakout boards. However, I am connected to Wire on 20/21 so maybe I can look into disabling those, switching to Wire1, or removing the resistors from the breakout board. In the picture, I have SCL/SDA attached to Wire1 just for testing purposes.

The sketch is quite big (~1300 lines of code/comments) but I can attach the files and insert the relevant portions.

I got AccelStepper from either the author's website (AccelStepper: AccelStepper library for Arduino).

The nextion is connected to TX1 (Pin 16/17).

#include <PID_v2.h>
#include <Wire.h>
#include "table.h"


double manualStepSize = 0;
double feederPosition_desired = 0;  //wher I want it to be at any given time
double feederPosition_actual = 0;   //where it is right now
double feederPosition_delta = 0;    //difference between desired and actual
double feederPosition_zero = 0;   //the encoder count when it tripped the prox sensor
double feederPosition_boardLoad = 100;  
double PB_delta = 0;              //distance between the prox sensor and the blade zero point
double bladeKerf = 3.175;             //the thickness of the blade cut


double motorSpeed = 0; //value to be passed to the motor driver
double motorSpeed_last = 0;
double motorSpeed_delta = 0;
double motorSpeed_max = 15000.0;
double motorSpeed_loadRate = 10000.0;
double motorSpeed_homeRate = 1000.0;
double motorSpeed_homeRateSlow = 500.0;
double motorSpeed_ejectRate = 10000.0;

bool boardPosition_homed = false;
double boardPosition_zero = 0;

// Define the aggressive and conservative Tuning Parameters
double aggKp = 400, aggKi = 0, aggKd = 0;
double consKp = 120, consKi = 40, consKd = 0;
bool pidState = false;  //turns the PID on and off 

// These hold the current encoder count.
signed long encoder1count = 0;
signed long encoder2count = 0;

// defines motor driver pins numbers
const int stepPin = 8;
const int directionPin = 9;
const int enablePin = 11;
const int alarmPin = 12;

const int proxSensorPin = 10;
bool proxSensorState = false;
bool proxSensorState_last = false;

//define values and pins for encoder knob
int encoderValue = 0;
int encoderValue_last = 0;
int encoderValue_diff = 0;
double shaftAngle_actual = 0;
int EncoderChan_1 = 2;
int EncoderChan_2 = 3;

//here are some values for reading and storing a potentiometer on A0
const int potPin = A0;
int potPinCurrent = 0;
int potPinLast = 0;

uint32_t number = 0;
uint32_t numSteps = 0;


//parameter for units and units conversion
byte unitCase = 5;
int mmWhole = 0;
int mmDecimal = 0;
int cmWhole = 0;
int dmDecimal = 0;
int dmWhole = 0;
int cmDecimal = 0;
int mWhole = 0;
int mDecimal = 0;
int ftWhole = 0;
int inWhole = 0;
int inRemWhole = 0;
int inDecimal = 0;
int inSixteenth = 0;
int inThirtysecond = 0;
double ticPerMM = 4.0;
double mmPerTic = 1/ticPerMM;


/* feature edits
 *  addd code to change settings for the bluetooth radio
 *  
 *  
 *  
 *  
 *  
 *  
 *  
 */



/*overall pin map
0 RX for serial debug and programming
1 TX for serial debug and programming
2 knob encoder channel 1 (DT)
3 knob encoder channel 2 (CLK)
4 CS for encoder chip on SPI
5 SW for screen encoder
6 BT Enable
7 BT State
8 stepper motor step pin
9 stepper motor direction pin
10 (to be added to carrier board) prox sensor pin
11 stepper motor enable pin
12 stepper alarm
13
14 serial 3 TX - unused
15 serial 3 RX - unused
16 serial 2 TX nextion display
17 serial 2 RX nextion display
18 serial 1 TX bluetooth
19 serial 1 RX bluetooth
20 I2C SDA
21 I2C SCL

 */
 
void screenEncoder();
void do_every_so_often();
void potRead();
void findEnd();
void loadBoard();
void bounce();
void pidRun();
void ejectLeft();
void ejectRight();
void zeroPosition();
void goHome();
void releaseMaterial();
void holdMaterial();
void moveToPosition();
void unitConvert();
void encoderCountToMillimeter();
void millimeterToEncoderCount();
void updateScreen();
void convertNumberToString2();
void convertNumberToString3();
void checkSerial();
//byte EEPROM_write();
//byte EEPROM_read();


//using the Super Droids board for the LS7366R counter chip
//the arduino library can be found at https://github.com/SuperDroidRobots/Encoder-Buffer-Library
//for the Arduino Due make sure to use the SPI port on the board
//see the attached LS7366R.h file for pinouts
#include "LS7366R.h"

//initialize the encoder class
LS7366R encoder;

//--------------------------------------------------------------------------------------------//
//using the accel Stepper librar to control the speed and velocity
//library can be found here https://www.airspayce.com/mikem/arduino/AccelStepper/index.html
#include <AccelStepper.h>


//--------------------------------------------------------------------------------------------//
//ulibrary for the EEPROM
#include "SparkFun_External_EEPROM.h" // Click here to get the library: http://librarymanager/All#SparkFun_External_EEPROM

ExternalEEPROM myMem;
const byte EEPROM_ADDRESS = 0b1010000; //The 7-bit unshifted address for the 24LC1025




////This is the struct that contains all the user settings. Add as many vars as you want.
//struct struct_machineSettings {
//  byte unitCase;                     //the prefered units for the screen
//  //double PB_delta;              //distance between the prox sensor and the blade zero point
//  //double bladeKerf;             //the thickness of the blade cut  
//};
//
////These are the default settings for each variable. They will be written if the EEPROM is blank.
//struct_machineSettings settings = {
//  .unitCase = 5,
//  //.PB_delta = 3657,
//  //.bladeKerf = 3,
//};






//--------------------------------------------------------------------------------------------//
//this is an encoder library to read encoder values from the pins
//this may be too slow and processor heavy, so may want to add multiple LS7366R chips
#include <Encoder.h>


//initiate the encoder thingy
Encoder myEnc(EncoderChan_1,EncoderChan_2);

//--------------------------------------------------------------------------------------------//

// Define a stepper and the pins it will use
// 1 or AccelStepper::DRIVER means a stepper driver (with Step and Direction pins)
AccelStepper stepper(AccelStepper::DRIVER, stepPin, directionPin);

//--------------------------------------------------------------------------------------------//
//using the nextion library for communicating back and forth from the board
// library can be found here https://github.com/itead/ITEADLIB_Arduino_Nextion
#include "Nextion.h"
#include "nextionParam.h"

//--------------------------------------------------------------------------------------------//
// PID set up and parameters
//#include <PID_v1.h>

//Specify the links and initial tuning parameters
PID myPID(&feederPosition_actual, &motorSpeed, &feederPosition_desired, consKp, consKi, consKd, DIRECT);




void setup() {
  
  //initialize the nextion display
  nexInit();

  //set up the I2C for the EPROM
  while (myMem.begin(EEPROM_ADDRESS, Wire) == false)
  {
    Serial.println(F("No memory detected."));
    delay (250);
  }
  
  byte temp = 7;
  Serial.println("i made it 2");
  myMem.put(10,temp);
  Serial.println("i made it 3");
  
  byte myValue = myMem.get(10,temp);
  Serial.print("EEPROM read ");
  Serial.println(myValue);
  
  //delay(1000);
  if (temp < 0 && temp <= 8){
    unitCase = temp;
  }
  else{
    unitCase = 5; 
  }

  //the nextion library will start the serial (serial 2) for the display
  //as well as the debug serial at 250,000 baud

  //start the serial port for the HM-18 bluetooth adapter on serial 1
  Serial1.begin(9600);
  



  //load the standard units form memory and set the button on the units settings page
  //unitsSettings_unitCase.setValue(unitCase);
  switch(unitCase){
    case1:
      unitsSettings_bt0.setValue(1);
      break;
    case 2:
      unitsSettings_bt1.setValue(1);
      break;
    case 3:
      unitsSettings_bt2.setValue(1);
      break;
    case 4:
      unitsSettings_bt3.setValue(1);
      break;
    case 5:
      unitsSettings_bt4.setValue(1);
      break;
    case 6:
      unitsSettings_bt5.setValue(1);
      break;
    case 7:
      unitsSettings_bt6.setValue(1);
      break;
    case 8:
      unitsSettings_bt7.setValue(1);
      break;   
    default:
      unitsSettings_bt4.setValue(1);
      break;   
  }
  
 

  //set the built in LED to output and turn it off
  pinMode(LED_BUILTIN,OUTPUT);
  digitalWrite(LED_BUILTIN,LOW);

  //set up the prox sensor pin as an input and get an initial reading
  pinMode(proxSensorPin, INPUT);
  proxSensorState = digitalRead(proxSensorPin);

  //set the parameters for the stepper accel 
  // Change these to suit your stepper if you want
  stepper.setEnablePin(enablePin);
  //stepper.setPinsInverted(false, false, true);
  stepper.enableOutputs();
  stepper.setMaxSpeed(motorSpeed_max);  //tested using the ConstantSpeed_fromPot program
  stepper.setAcceleration(60000);
  stepper.setSpeed(0);
  digitalWrite(enablePin, LOW);   //turn off the motor

  //set the manual step size to 1/4" but need to conver to mm
  manualStepSize = 0.25 * 25.4;

  //set up functions for the nextion display
  //p1_b24.attachPop(p1_b24_Release, &p1_b24);

  manualPage_b0.attachPop(manualPage_b0_Release, &manualPage_b0);
  manualPage_b2.attachPop(manualPage_b2_Release, &manualPage_b2);
  manualPage_b3.attachPop(manualPage_b3_Release, &manualPage_b3);
  manualPage_b4.attachPop(manualPage_b4_Release, &manualPage_b4);
  manualPage_b5.attachPop(manualPage_b5_Release, &manualPage_b5);
  manualPage_b6.attachPop(manualPage_b6_Release, &manualPage_b6);
  manualPage_b7.attachPop(manualPage_b7_Release, &manualPage_b7);
  manualPage_b8.attachPop(manualPage_b8_Release, &manualPage_b8);
  manualPage_b9.attachPop(manualPage_b9_Release, &manualPage_b9);
  manualPage_bt0.attachPop(manualPage_bt0_Release, &manualPage_bt0);
  manualPage_bt1.attachPop(manualPage_bt1_Release, &manualPage_bt1);
  manualPage_bt2.attachPop(manualPage_bt2_Release, &manualPage_bt2);
  manualPage_bt3.attachPop(manualPage_bt3_Release, &manualPage_bt3);
  manualPage_bt4.attachPop(manualPage_bt4_Release, &manualPage_bt4);

  unitsSettings_bt0.attachPop(unitsSettings_bt0_Release, &unitsSettings_bt0);
  unitsSettings_bt1.attachPop(unitsSettings_bt1_Release, &unitsSettings_bt1);
  unitsSettings_bt2.attachPop(unitsSettings_bt2_Release, &unitsSettings_bt2);
  unitsSettings_bt3.attachPop(unitsSettings_bt3_Release, &unitsSettings_bt3);
  unitsSettings_bt4.attachPop(unitsSettings_bt4_Release, &unitsSettings_bt4);
  unitsSettings_bt5.attachPop(unitsSettings_bt5_Release, &unitsSettings_bt5);
  unitsSettings_bt6.attachPop(unitsSettings_bt6_Release, &unitsSettings_bt6);
  unitsSettings_bt7.attachPop(unitsSettings_bt7_Release, &unitsSettings_bt7);

  handFeedPage_bt0.attachPop(handFeedPage_bt0_Release, &handFeedPage_bt0);
  handFeedPage_bt1.attachPop(handFeedPage_bt1_Release, &handFeedPage_bt1);

  //put in a time stamp for the do_every_so_often function
  next = millis();

  //initiliaze and clear the encoders on th LS7366R
  encoder.initEncoders();       Serial.println("Encoders Initialized...");  
  //encoder.clearEncoderCount(1);  Serial.println("Encoder Cleared...");
  encoder.clearEncoderCount(2);  Serial.println("Encoder Cleared...");

  //initialize the variables we're linked to
  feederPosition_desired = feederPosition_actual;

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-motorSpeed_max,motorSpeed_max); //tell the PID to range the output from 0 to 15000 
  myPID.SetSampleTime(20);
}

void loop() {
  
  nexLoop(nex_listen_list);

  //every half second perform the function
  if(millis() >= next) {
    next = millis()+400;
    do_every_so_often();
  }
  
  pidRun();
  stepper.runSpeed(); 
}![IMG-4458|375x500, 75%](upload://70mdV7tROtwnxPLdOi6XlEyBgVd.jpeg)


I think I will start out by commenting out the rest of the pre-setup () code and see if I can get it to work.

Thanks in advance. I'm a mechanical engineer that has been playing with PIC and Arduino for the last 15 years. I know enough to get myself in trouble.



Well, I may have just solved it. I forgot to transfer the Wire.begin() over from the sample programs. Why is it always something so simple.

It is not always that simple.

May I write a few notes ? I took a look that the code anyway.

  1. I don't know if the line "next = millis();" is okay, because "next" is not declared.
  2. When you calculate a millis value in the future, then there is a problem during the rollover. Take a timestamp and use subtraction as you can see in the Blink Without Delay example. Work with the past, not a time in future.
    if(millis() >= next) {
      next = millis()+400;        // don't calculate a time in the future
  1. The Arduino pre-compiler should be able to do the functions prototyping for you. Sometimes it fails.
  2. The EEPROM_ADDRESS has the comment "The 7-bit unshifted address for the 24LC1025", but that can't be right. Arduino uses the 7-bit shifted I2C address and some manufacturers put the 8-bit unshifted value in their datasheet.
  3. When setting a pin as output with pinMode(), it is default set as LOW. So you don't have to set it low yourself.