collect rotary encoder data and load cell data simultaneously

Dear Community,
thank you very much in advance for taking your time to fly over my sketch! To say it in advance, I work rather in the product design field and have just basic knowledge with code - thats why the code might look a little messy, sorry for that.

The Task:
I build a fixture to measure the needed pressure to compress flexible structure samples to a certain percentage. I modified a drill press with a KY-040 rotary encoder to track the traveled distance and a DIY weight-sensitive stamp that reads the pressure (in gramm) with two loadcells and a HX711 Amplifier. So far so good.

The Problem:
I made two programs to read travel-distance and load. Individually compiled to an Arduino Uno they work fine and give me precise data. But now I want to merge them into one program and read the load corresponding to each step of the rotary encoder (giving that data out as a .csv via Processing). With the merged code I either get load readings or travel readings but cant figure out how to get both at the same time. I basically just want the load reading to run in background permanentely and Serial.print a load value for each traveled step.

The Question:
Am I doing a basic mistake as an arduino can’t really compute multiple functions simoultaneously? Or is there a simple solution? I feel like I just did some mistakes with the logic of the code…

my merged code

#include <Arduino.h>
#include <RotaryEncoder.h>
#include <HX711_ADC.h>

#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO_EVERY)
// Example for Arduino UNO with input signals on pin 2 and 3
#endif

//pins
const int HX711_dout = 8; //mcu > HX711 dout pin
const int HX711_sck = 9; //mcu > HX711 sck pin
const int PIN_IN1 = 2;
const int PIN_IN2 = 3;

unsigned long t = 0; // for the scale code

//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);


// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);


#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO_EVERY)
// This interrupt routine will be called on any change of one of the input signals


void checkPosition() {
  encoder.tick(); // just call tick() to check the state.
}

void getscaledata() {
  //scale code
  static boolean newDataReady = 0;
  const int serialPrintInterval = 10; //increase value to slow down serial print activity

  // check for new data/start next conversion:
  if (LoadCell.update()) newDataReady = true;

  // get smoothed value from the dataset:
  if (newDataReady) {
    if (millis() > t + serialPrintInterval) {
      float i = LoadCell.getData();
      
     Serial.println(i);
      newDataReady = 0;
      t = millis();
    }
  }
    // receive command from serial terminal, send 't' to initiate tare operation:
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay();
  }

  // check if last tare operation is complete:
  if (LoadCell.getTareStatus() == true) {
    // Serial.println("Tare complete"); comment, so it doesnt demage the list
  }
}

#elif defined(ESP8266)
/**
   @brief The interrupt service routine will be called on any change of one of the input signals.
*/
ICACHE_RAM_ATTR void checkPosition()
{
  encoder.tick(); // just call tick() to check the state.
}

#endif


int zerobutton = 5;
int zerocal = 0;
float traveled = 0;
int status = false;
int relpos = 0;
float i;

unsigned long previousMillis = 0;

const long interval = 50;


void setup() {

  Serial.begin(2000000);
  while (! Serial);


  attachInterrupt(PIN_IN1, checkPosition, CHANGE);
  attachInterrupt(PIN_IN2, checkPosition, CHANGE);

  LoadCell.begin();
  float calibrationValue; // calibration value (see example file "Calibration.ino")
  calibrationValue = -45, 23; // uncomment this if you want to set the calibration value in the sketch

  unsigned long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
  boolean _tare = true; //set this to false if you don't want tare to be performed in the next step
  LoadCell.start(stabilizingtime, _tare);
  if (LoadCell.getTareTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1);
  }
  else {
    LoadCell.setCalFactor(calibrationValue); // set calibration value (float)
  //  Serial.println("Startup is complete");
  }

}


// Read the current position of the encoder and print out when changed.
void loop() {

getscaledata();

  unsigned long currentMillis = millis();

  static int pos = 0;
  encoder.tick();

  int newPos = encoder.getPosition();
  if (pos != newPos) {

  


    Serial.print(newPos);
    Serial.print(",");
    Serial.print(relpos);
    Serial.print(",");
    Serial.println(i);
    pos = newPos;
    relpos = newPos + zerocal;

  }
  

  if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;

    if (digitalRead(zerobutton) == true) {
      status = !status;
      zerocal = -newPos;
    } while (digitalRead(zerobutton) == true);

  }


}

here are the single programs that work fine individually

loadcell reading

#include <HX711_ADC.h>
#if defined(ESP8266)|| defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif

//pins:
const int HX711_dout = 8; //mcu > HX711 dout pin
const int HX711_sck = 9; //mcu > HX711 sck pin

//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);

const int calVal_eepromAdress = 0;
unsigned long t = 0;

void setup() {
  Serial.begin(57600); delay(10);
  Serial.println();
  Serial.println("Starting...");

  LoadCell.begin();
  float calibrationValue; // calibration value (see example file "Calibration.ino")
  calibrationValue = -42, 55; // uncomment this if you want to set the calibration value in the sketch
#if defined(ESP8266)|| defined(ESP32)
  //EEPROM.begin(512); // uncomment this if you use ESP8266/ESP32 and want to fetch the calibration value from eeprom
#endif
  //EEPROM.get(calVal_eepromAdress, calibrationValue); // uncomment this if you want to fetch the calibration value from eeprom

  unsigned long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
  boolean _tare = true; //set this to false if you don't want tare to be performed in the next step
  LoadCell.start(stabilizingtime, _tare);
  if (LoadCell.getTareTimeoutFlag()) {
    Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
    while (1);
  }
  else {
    LoadCell.setCalFactor(calibrationValue); // set calibration value (float)
    Serial.println("Startup is complete");
  }
}

void loop() {
  static boolean newDataReady = 0;
  const int serialPrintInterval = 0; //increase value to slow down serial print activity

  // check for new data/start next conversion:
  if (LoadCell.update()) newDataReady = true;

  // get smoothed value from the dataset:
  if (newDataReady) {
    if (millis() > t + serialPrintInterval) {
      float i = LoadCell.getData();
      Serial.print("Load_cell output val: ");
      Serial.println(i);
      newDataReady = 0;
      t = millis();
    }
  }

  // receive command from serial terminal, send 't' to initiate tare operation:
  if (Serial.available() > 0) {
    char inByte = Serial.read();
    if (inByte == 't') LoadCell.tareNoDelay();
  }

  // check if last tare operation is complete:
  if (LoadCell.getTareStatus() == true) {
    Serial.println("Tare complete");
  }

travel distance reading

#include <Arduino.h>
#include <RotaryEncoder.h>

#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO_EVERY)
// Example for Arduino UNO with input signals on pin 2 and 3
#define PIN_IN1 2
#define PIN_IN2 3



#endif

RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);


#if defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_NANO_EVERY)
// This interrupt routine will be called on any change of one of the input signals


void checkPosition()
{
  encoder.tick(); // just call tick() to check the state.
}

#elif defined(ESP8266)
/**
   @brief The interrupt service routine will be called on any change of one of the input signals.
*/
ICACHE_RAM_ATTR void checkPosition()
{
  encoder.tick(); // just call tick() to check the state.
}

#endif


int zerobutton = 5;
int zerocal = 0;
float traveled = 0;
int status = false;
int relpos = 0;

unsigned long previousMillis = 0;
const long interval = 50;

void setup()
{
  Serial.begin(2000000);
  while (! Serial);


  attachInterrupt(PIN_IN1, checkPosition, CHANGE);
  attachInterrupt(PIN_IN2, checkPosition, CHANGE);
} // setup()


// Read the current position of the encoder and print out when changed.
void loop() {

  unsigned long currentMillis = millis();

  static int pos = 0;
  encoder.tick();

  int newPos = encoder.getPosition();
  if (pos != newPos) {

    Serial.print(newPos);
    Serial.print(",");
    Serial.println(relpos);


    pos = newPos;

    relpos = newPos + zerocal;


  }

  if (currentMillis - previousMillis >= interval) {

    previousMillis = currentMillis;

    if (digitalRead(zerobutton) == true) {
      status = !status;
      zerocal = -newPos;
    } while (digitalRead(zerobutton) == true);

  }
}

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