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.
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.
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'.
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.
@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'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?