Combining Stepper Movement and Dial Indicator Readout

I have a function for the code to read the Dial Indicator (thanks sspence, Interfacing a Digital Micrometer to a Arduino & VGA Monitor : 7 Steps - Instructables). As well as another to control the direction and pulse of the stepper driver. Right now, I can only ever get one of the functions to run and not both (so either the stepper rotates or I get serial monitor output of the dial indicator). I suspect it has something to do with how things are looped (stepper function is for one step) but I can't seem to figure it out. Any advice would be greatly appreciated.

Board: Mega 2560
Stepper: 34HS31-6004S1 (StepperOnline)
Driver: DM860I (StepperOnline)


int pulse = 14;
int direction = 17;
int pulseDelay = 1;
//int StepperON = 1;

int req = 5; //mic REQ line goes to pin 5 through q1 (arduino high pulls request line low)
int dat = 2; //mic Data line goes to pin 2

int clk = 3; //mic Clock line goes to pin 3

int i = 0; int j = 0; int k = 0;

byte mydata[14];

float num;

void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);

  pinMode(pulse, OUTPUT);
  pinMode(direction, OUTPUT);


  pinMode(req, OUTPUT);

  pinMode(clk, INPUT_PULLUP);

  pinMode(dat, INPUT_PULLUP);

  digitalWrite(req,LOW); // set request at LOW
}

void DialIndicator() { // get data from mic
digitalWrite(req, HIGH); // generate set request

for(i = 0; i < 13; i++ ) {

k = 0;

for (j = 0; j < 4; j++) {

while( digitalRead(clk) == LOW) {// hold until clock is high

}

while( digitalRead(clk) == HIGH) {// hold until clock is low

}

bitWrite(k, j, (digitalRead(dat) & 0x1)); // read data bits, and reverse order )

}

// extract data

mydata[i] = k;

}
// sign = mydata[4];

// decimal = mydata[11];

// units = mydata[12];

// assemble measurement from bytes

char buf[7];

for(int lp=0;lp<6;lp++){

buf[lp]=mydata[lp+5]+'0';

buf[6]=0;

num=atol(buf); //assembled measurement, no decimal place added

Serial.println(num/100, 3); //add decimal
}
}

void Stepper() {

  digitalWrite(direction,HIGH);
  digitalWrite(pulse,HIGH);
  delayMicroseconds(pulseDelay);
  digitalWrite(pulse,LOW);
  delayMicroseconds(pulseDelay);

}
void loop() {
  // put your main code here, to run repeatedly:
  
  DialIndicator();
  delay(1);
  Stepper();
  Serial.println("Check");
  
}

Your sketch is doing exactly what you asked of it. You should search here on the four for blink without delay, and research stepper libraries that will allow you to issue one command for multiple steps.

any link?

why you print num 6 times ?

  num = 0;
  for (int lp = 0; lp < 6; lp++) num = num * 10 + mydata[lp + 5];
  Serial.println(num / 100, 3); 
const int pulse = 7; // ATTENTION pin  changed
const int direction = 17;

const int req = 5; //mic REQ line goes to pin 5 through q1 (arduino high pulls request line low)
const int dat = 2; //mic Data line goes to pin 2
const int clk = 3; //mic Clock line goes to pin 3
const int pulseDelay = 1;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(pulse, OUTPUT);
  pinMode(direction, OUTPUT);
  pinMode(req, OUTPUT);
  pinMode(clk, INPUT_PULLUP);
  pinMode(dat, INPUT_PULLUP);
  digitalWrite(req, LOW); // set request at LOW
  digitalWrite(direction, HIGH);
  analogWrite(pulse, 127);
}

void loop() {
  DialIndicator();
}

void DialIndicator() { // get data from mic
  static uint32_t oldMillis = 0;
  if (millis() - oldMillis < 50)return;
  oldMillis += 50;
  byte mydata[14];
  digitalWrite(req, HIGH); // generate set request
  for (byte i = 0; i < 13; i++ ) {
    byte k = 0;
    for (bytej = 0; j < 4; j++) {
      while ( digitalRead(clk) == LOW) ; // hold until clock is high
      while ( digitalRead(clk) == HIGH) ; // hold until clock is low
      bitWrite(k, j, digitalRead(dat) ); // read data bits, and reverse order )
    }

    mydata[i] = k;
  }
  digitalWrite(req, LOW); // you forgot to insert this line

  unsigned long num = 0;
  for (byte lp = 0; lp < 6; lp++) num = num * 10 + mydata[lp + 5];
  Serial.println(num / 100, 3);
}

I'm starting to get a better understanding of millis(). I've also used the AccelStepper library. This issue now is that the stepper is jerky or pauses. Is this because the Mega can't run actually run multiple processes and the stepper.runSpeed() is getting interrupted when the DialIndicator function is being ran? Would using setPosition be better (although I don't care about the actual position). What I'm trying to do is if the reading for the indicator is above a value lower the speed, if below increase.

#include <AccelStepper.h>


//int pulse = 14;
//int direction = 17;
//int pulseDelay = 1;
//int StepperON = 1;
AccelStepper stepper(1,14,17);
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long previousServoMillis = 0;
const long interval = 1000;

int servoInterval = 0;

int req = 5; //mic REQ line goes to pin 5 through q1 (arduino high pulls request line low)
int dat = 2; //mic Data line goes to pin 2

int clk = 3; //mic Clock line goes to pin 3

int i = 0; int j = 0; int k = 0;

byte mydata[14];

float num;

void setup() {
  // put your setup code here, to run once:
    Serial.begin(9600);

  stepper.setMaxSpeed(100000);
  //stepper.setAcceleration(20000);
  //stepper.moveTo(50000);
  stepper.setSpeed(10000);
  

  pinMode(req, OUTPUT);

  pinMode(clk, INPUT_PULLUP);

  pinMode(dat, INPUT_PULLUP);

  digitalWrite(req,LOW); // set request at LOW
}

void DialIndicator() { // get data from mic
if (currentMillis - previousMillis >= 1000) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
digitalWrite(req, HIGH); // generate set request

for(i = 0; i < 13; i++ ) {

k = 0;

for (j = 0; j < 4; j++) {

while( digitalRead(clk) == LOW) {// hold until clock is high

}

while( digitalRead(clk) == HIGH) {// hold until clock is low

}

bitWrite(k, j, (digitalRead(dat) & 0x1)); // read data bits, and reverse order )

}

// extract data

mydata[i] = k;

}
// sign = mydata[4];

// decimal = mydata[11];

// units = mydata[12];

// assemble measurement from bytes

char buf[7];

for(int lp=0;lp<6;lp++){

buf[lp]=mydata[lp+5]+'0';

buf[6]=0;

num=atol(buf); //assembled measurement, no decimal place added

Serial.println(num/100, 3); //add decimal

}
}


}


void loop() {
  // put your main code here, to run repeatedly
  currentMillis = millis();
  /*for (int p = 0; p < 13; p++ ){
  DialIndicator();
  } */
  //
  //stepper.runSpeed();
  DialIndicator();
  StepperSpeed();
  //stepper.runSpeed();
  //delay(10);
  //while(1){

  //}
  //delay(1);
  //stepper.runSpeed();
  //Stepper();
  //Serial.println("Check");
  
}

void StepperSpeed() {

  if (currentMillis - previousServoMillis >= servoInterval) {
        // its time for another move
    previousServoMillis += servoInterval;
    stepper.runSpeed();
} 
}

I am not knowledgeable in steppers, but my understanding from friends is it should run without jerkiness if you set it up right. After a quick look at your dialindicator code, it appears to be overkill, try slimming it down. The mega is more than capable of running this.

1 Like

It's that DialIndicator() routine:

void DialIndicator() { // get data from mic
  if (currentMillis - previousMillis >= 1000) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    digitalWrite(req, HIGH); // generate set request
    for (i = 0; i < 13; i++ ) {
      k = 0;
      for (j = 0; j < 4; j++) {
        while ( digitalRead(clk) == LOW) { // hold until clock is high
        }
        while ( digitalRead(clk) == HIGH) { // hold until clock is low
        }
        bitWrite(k, j, (digitalRead(dat) & 0x1)); // read data bits, and reverse order )
      }
      // extract data
      mydata[i] = k;
    }
    // sign = mydata[4];
    // decimal = mydata[11];
    // units = mydata[12];
    // assemble measurement from bytes
    char buf[7];
    for (int lp = 0; lp < 6; lp++) {
      buf[lp] = mydata[lp + 5] + '0';
      buf[6] = 0;
      num = atol(buf); //assembled measurement, no decimal place added
      Serial.println(num / 100, 3); //add decimal
    }
  }
}

The while ( digitalRead(clk)==LOW){} while ( digitalRead(clk)==HIGH){} lines stall your program until it can read ... 14x4=56 bits of data at whatever rate the device happens to be putting out.

I don't want to decode the protocol from this code, but it looks like it ought to be easier to decode than this... What is it? Binary coded decimal coded into 4 bits per character and you only care about 20(?) of the bits?

The datastream is probably slow enough that you could do something like Serial Input Basics - updated keyed on the individual bits on the falling edge of 'clk'.

2 Likes

Or a dirty way to hack it would be to put some stepper.runSpeed()s inside of those blocking whiles() so that the stepper can continue to move while waiting for clk to toggle.

2 Likes

@77katz77 Agreed, that is just terrible code. Check if there is another way to read the data, preferably as a 'record' or block of data vs 1 byte at a time.

Googling from this bit on the linked Instructables page:

Update: Igaging Origin Series use a Mitutoyo cable and output the Mitutoyo 52 bit datastream. The code and schematics below work with SPC Digimatic Calipers, Micrometers, Dial indicators, and Scales from both companies.

... I find:

with:

It looks like 10ms/bit. Plenty of time for an interrupt or some:

I'll look into that. The other alternative I thought of is to just use a nano to read the data stream then output the measurement to the mega for controlling the stepper?

This helped but I can feel the stepper is still jogging instead of running at a constant speed.

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