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.

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