Adapting working code to existing moving setup setup. Any advice/tips for me?

Hi,
New member, medium coding level. I don’t have a not a lot of experience on C but i have been hobbying electronics for at least 10 years.
I need to adapt this code to control big steppers with existing common anode d860mt drivers and PSUs.
In what I see as steps to be taken, I need to:

Essential

-code to use pul/dir instead of PWM
also adapt the code to the parameters of existing motors, include some way to use the pot or replace with an encoder/transducer.

Needed badly
-a way to include a library and to find a good one. Good ramp up is huge part of immersion.

If someone could look at the code to see if it’s doable. I’m keen to learn, but I would hate to waste a good part on something that cannot be done. I’ve written code lately but this is a whole new level for me.

Thank you,

SMC3.ino (59.6 KB)

What does "this code" do?

What is the project?

Adapting code to do something very different often takes more time than creating a new program from scratch.

...R

Your first problem is not the code, it's the hardware change. Big (powerful) stepper motors require adequate driver modules. Are you sure that the stepper motors can do what you want?

Have a look at the AccelStepper library.

Hi,
Welcome to the forum.

Please read the post at the start of any forum , entitled "How to use this Forum".
OR
http://forum.arduino.cc/index.php/topic,148850.0.html.
Then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom... :slight_smile:

Thank you for the answers

What does "this code" do?

What is the project?

Adapting code to do something very different often takes more time than creating a new program from scratch.

...R

Sorry for the "code" term. This sketch drives some DC motors via PWM output according to a serial formatted data stream from a PC that reads forcefeedback from different PC games.
Yes, this is why I started making small sketches and controlling 2 mini servo 2DOF platform. I only had adapted some code to be more precise, did some small sensor and stuff. I asked on the forums but the information is way too diverse for me.
Why the challenge? I had acquired an arcade game controlled by analog means but that could be "scketched'' to move by reading serial data.
Why asking here? I have the mental capacity to learn absolutely everything but i need to see if the information that is in focus is essential for this project or not. For example, I cannot find out what type of detailed information this this digital stepping driver expects. I learned what a motor shield expects but this driver is different. I'd like to "cheat" a little bit, like some "cheat" on PhD by having to spot on fractions of information for the thesis. if someone says: learn this part of this and this part of this, would rise this to doable status.

Your first problem is not the code, it's the hardware change. Big (powerful) stepper motors require adequate driver modules. Are you sure that the stepper motors can do what you want?

I only need to change the input from analog to digital.It's a 2dof platform moved by joystick controls. The setup has 2 arduinos for each axis driven by its own psu+driver+motor/gearbox 20 ratio. If I adapt or write my own sketch with parts from already shared and praised sketches, that's an issue. hardware side it's pretty solid.

the scheme is 34HS59-5004S MOTOR====>DM860T driver ===== S-350-60 PSU.

Hi,
Can you post links to the hardware you are using please?

What model Arduinos are you using?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom.. :slight_smile:

Arduino Uno

motors High Torque, D-cut Shaft Nema 34 - 86x86x150mm 1.8 deg. (200 ... with a 20:1 90 deg gearbox
motors have pots on them, thinking of changing them for rotary encoders.
Drivers Digital Stepper Driver 2.4-7.2A 18-80VAC or 36-110VDC for ...
PSU https://www.omc-stepperonline.com/350w-60v-59a-115230v-switching-power-supply-stepper-motor-cnc-router-kits-s-350-60.html

ewell:
I only need to change the input from analog to digital.

If you are proposing to replace a DC motor with a stepper motor isn't it the OUTPUT that needs to change.

Assuming that the existing software is designed for controlling a DC motor it will have some code that is functionally equivalent to analogWrite(motorControlPin, motorPwmValue). When you do that with a DC motor the motor driver will keep the motor working at that power value until it receives the next instruction.

Stepper motors don't work like that at all. The Arduino must produce a continuous stream of pulses at the frequency appropriate to the speed required from the motor. That means that the existing software would probably need a substantial change.

Another important difference is that changing the PWM value for a DC motor changes the force it can deliver. A stepper motor does not have any means to vary its force - it is always at "full power".

...R

Hi Robin,
I actually started in small steps to put the basic plan of the code. I have 3 stepper sketches to get inspiration from.

basically, i need to :

-find a stepper library that can be used properly. I’ve read that AccelStepper as library has a blocking function in it, basically it pauses the code until the stepper has finished moving before the code continues and if another block of data hits the serial port and the stepper is moving the data will be ignored. Can anyone give an opinion for an alternative option?
This code was useful for a raw 2 DOF platform I put up with small steppers, idk if I can/should use a buffer comand on it

#include <AccelStepper.h>


AccelStepper stepper1(1, 31, 30); // pin 3 = step, pin 6 = direction


int pos = 0;


enum TPortState { psReadActuator, psReadValue }; 
TPortState currentState = psReadActuator;
const int kActuatorCount = 1;


// the letters ("names") sent from Sim Tools to identify each actuator
// NB: the order of the letters here determines the order of the remaining constants kPins and kActuatorScale
const char kActuatorName[kActuatorCount] = {'L'};
const int kActuatorScale[kActuatorCount][2] = { {0, 100} };  //Scaling 
const char kEOL = '~';  // End of Line - the delimiter for our acutator values
const int kMaxCharCount = 3;  // some insurance...
int actuatorPosition[kActuatorCount] = {0};  // current Actuator positions, initialised to 90
int currentActuator;  // keep track of the current Actuator being read in from serial port
int valueCharCount = 0;  // how many value characters have we read (must be less than kMaxCharCount!!


void setup()
{ 
  stepper1.setMaxSpeed(2700);
  stepper1.setAcceleration(2500);
  Serial.begin(9600);
}


void loop()


{


  if (stepper1.distanceToGo() == 0)
  {
  stepper1.moveTo((pos * 50));
  }
  stepper1.run();
 
}


void serialEvent() {
  char tmpChar;
  int tmpValue;


  while (Serial.available()) {
  // if we're waiting for a Actuator name, grab it here
  if (currentState == psReadActuator) {
  tmpChar = Serial.read();
  // look for our actuator in the array of actuator names we set up


  for (int i = 0; i < kActuatorCount; i++) {
  if (tmpChar == kActuatorName[i]) {


  currentActuator = i;  // remember which actuator we found
  currentState = psReadValue;  // start looking for the Actuator position
  actuatorPosition[currentActuator] = 0;  // initialise the new position
  valueCharCount = 0;  // initialise number of value chars read in
  break;
  }
  }
  }


  // if we're ready to read in the current Actuator's position data
  if (currentState == psReadValue) {
  while ((valueCharCount < kMaxCharCount) && Serial.available()) {
  tmpValue = Serial.read();
  if (tmpValue != kEOL) {
  tmpValue = tmpValue - 48;
  if ((tmpValue < 0) || (tmpValue > 9)) tmpValue = 0;
  actuatorPosition[currentActuator] = actuatorPosition[currentActuator] * 10 + tmpValue;
  valueCharCount++;
  }
  else break;
  }


  // if we've read the value delimiter,

update the Actuator and start looking for the next Actuator name
if (tmpValue == kEOL || valueCharCount == kMaxCharCount) {

// scale the new position so the value is between 0 and 179
actuatorPosition[currentActuator] = map(actuatorPosition[currentActuator], 0, 255, kActuatorScale[currentActuator][0], kActuatorScale[currentActuator][1]);

updateActuator(currentActuator);
currentState = psReadActuator;
}
}
}
}

// write the current Actuator position to the passed in Actuator
void updateActuator(int thisActuator) {
if (pos =! actuatorPosition[thisActuator]);
pos = (actuatorPosition[thisActuator]);
}

[code/]
No, I am trying to say the code was written for DC motors. The whole platform is FUNCTIONAL by using two Unos and analog input

Robin2:
Assuming that the existing software is designed for controlling a DC motor it will have some code that is functionally equivalent to analogWrite(motorControlPin, motorPwmValue). When you do that with a DC motor the motor driver will keep the motor working at that power value until it receives the next instruction.

Stepper motors don’t work like that at all. The Arduino must produce a continuous stream of pulses at the frequency appropriate to the speed required from the motor. That means that the existing software would probably need a substantial change.

Another important difference is that changing the PWM value for a DC motor changes the force it can deliver. A stepper motor does not have any means to vary its force - it is always at “full power”.

…R

Thank you, aware of that. The driver has a microstepping function also.

why no https and why code doesn't display properly,do you guys have aws?

ewell:
I've read that AccelStepper as library has a blocking function in it, basically it pauses the code until the stepper has finished moving before the code continues

You seem to be only partly informed. The principal functionality of the AccelStepper library is that its run() and runSpeed() functions DO NOT block. It also has blocking functions.

Thank you, aware of that. The driver has a microstepping function also.

I am not sure what you are aware of as the piece you have quoted made 3 separate points. However, in case of doubt, micro-stepping has nothing to do with altering the torque of a stepper motor. Even if the in-between steps have less torque the full torque will be applied at every full step.

why code doesn't display properly,

Presumably because you did not correctly surround it with [code] and [/code] tags

...R

I was talking in overcoming the blocking . If you receive data on serial channel to move one axis to infinity, P255~ in our case, that will block the 3 dof pair to act on the motor. block the other channels, breaking hard and sudden in a car and hitting a small bump for example, the loop is still trying to achieve a limit while discarding data about same motor. I didn’t look further about cons in using this library. It was posted by a moderator. This is why I was advised against it. Still, I’ll take your advice and take this issue off the list. AccelStepper.h is here to stay.

I was only looking for alternatives and i remembered about this code used with closed loop drivers. it’s been tried and works ok. I could buy a pair of drivers and be done.

de:

// Stepper microstepping settings :  51200

int const StepPin1 = 2, DirPin1 = 3, StepPin2 = 4, DirPin2 = 5;  //Step or pulse pin, check how DirectionManager is written.
int commandbuffer[4] = {0};    // To stock the serial datas in the good order.
int nbrStep1 = 0, nbrStep2 = 0; // The number of pulse that each motor will receive. If the number is negative, it inverts the direction
unsigned int pitchTarget = 16384, rollTarget = 16384;  // The pitch and roll positions we want to reach
unsigned int  pitchPosition = 16384, rollPosition = 16384; // The actual positions
int c = 0;
int dir1 = 1, dir2 = 1;         //Will be used to set the motors direction
int pulseWidth = 10;            //From the HBS86h datasheet : For reliable response, pulse width should be longer than 10μs
bool LCDMode = false, InitializeMode = true;
int max = 0;
int x, y;
int btnPin = 13;

#include <LiquidCrystal.h> // includes the LiquidCrystal Library
LiquidCrystal lcd(6, 7, 8, 9, 10, 11); // Creates an LC object. Parameters: (rs, enable, d4, d5, d6, d7)

void setup() {
  delay(2000);    //safety delay to flash the code
  pinMode(StepPin1, OUTPUT);
  pinMode(DirPin1, OUTPUT);
  pinMode(StepPin2, OUTPUT);
  pinMode(DirPin2, OUTPUT);
    if (InitializeMode) {
      Initialize();
    }
  Serial.begin(115200);    //To communicate with Simtools
  if (LCDMode) {
    Start();
  }

}

void loop() {
  SerialReader();                             //Get the datas from Simtools
 // LimitManager();
  CommandWorker();                        //Convert the position targets to pulse number
  MoveSteppers(nbrStep1, nbrStep2);           //Set directions and send the pulses.
}

void MoveSteppers(int step1, int step2) {

  DirectionManager(step1, step2); //put the motors in the right directions
  pitchPosition = pitchTarget;
  rollPosition = rollTarget;
  x = abs(step1);
  y = abs(step2);
  for (int i = 0; i < min(x, y); i++) { //Common moves
    doublePulse(StepPin1, StepPin2);
  }

  if (max(x, y) == x) {          //Now only M1 will move
    for (int i = 0; i < x - y; i++) {
      monoPulse(StepPin1);
    }
  }
  else {                                                      //Now only M2 will move
    for (int i = 0; i < y - x; i++) {
      monoPulse(StepPin2);
    }
  }


}

void CommandWorker() {
  nbrStep1 = pitchTarget - pitchPosition - rollPosition + rollTarget;
  nbrStep2 = pitchTarget - pitchPosition + rollPosition - rollTarget;
  c++;
  if (c > 200) {
    if (LCDMode) {
      LCD();
      c = 0;
    }
  }
}

void Start() {
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Waiting for");
  lcd.setCursor(0, 1);
  lcd.print("datas...");
  while (!Serial.available()) {     // We wait for serial datas to really start
    delay(50);
  }
  lcd.setCursor(0, 0);
  lcd.print("Datas received !");
  lcd.setCursor(1, 0);
  lcd.print("Starting in :");
  delay(1000);
  lcd.clear();
  lcd.print("Get ready.");
  for (int i = 0; i < 1; i++) {
    lcd.setCursor(0, 0);
    lcd.clear();
    lcd.print("Get ready.");
    lcd.setCursor(1, 7);
    lcd.print(3 - i);
    for (int j = 0; j < 3; j++) {
      lcd.setCursor(6 - j, 1);
      lcd.print("*");
      lcd.setCursor(8 + j, 1);
      lcd.print("*");
      delay(333);
    }
    lcd.clear();
  }
}

void LCD() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("P ");
  lcd.print(pitchTarget);
  lcd.print("R ");
  lcd.print(rollTarget);
  lcd.setCursor(0, 1);
  lcd.print(max);
  // lcd.print(" M2 ");
  //  lcd.print(nbrStep2);
}

void monoPulse(int stepPin) {
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(pulseWidth);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(pulseWidth);
}

void doublePulse(int StepPin1, int StepPin2) {
  digitalWrite(StepPin1, HIGH);
  digitalWrite(StepPin2, HIGH);
  delayMicroseconds(pulseWidth);
  digitalWrite(StepPin1, LOW);
  digitalWrite(StepPin2, LOW);
  delayMicroseconds(pulseWidth);
}

void SerialReader() {       // This function is the work of Sirnoname
  // Simtools output : P<Axis1a><Axis2a>, Data bits : 15 bits, Parity : None, stop bits : 1
  int buffer           =  0 ;    // It takes the value of the serial data
  int buffercount      = -1 ;    // To count where we are in the serial datas

  while (Serial.available())
  {
    if (buffercount == -1)
    {
      buffer = Serial.read();
      if (buffer != 'P') {
        buffercount = -1; // "P" is the marquer. If we read P, the next data is pitch
      } else {
        buffercount = 0;
      }
    }
    else   //  if(buffercount>=0)
    {
      buffer = Serial.read();
      commandbuffer[buffercount] = buffer; // The first value next to "P" is saved in commandbuffer in the place "buffercount"
      buffercount++;
      if (buffercount > 3)
      {
        pitchTarget = (commandbuffer[0]) * 256 + commandbuffer[1];
        rollTarget = (commandbuffer[2]) * 256 + commandbuffer[3];
        buffercount = -1; // Re-initialize buffercount.
        break;
      }
    }
  }
}

void DirectionManager(int step1, int step2) {
  if (step1 < 0) {                //dirPin1 = 3
  digitalWrite(DirPin1, LOW);
   // PORTD &= B11110111;        // This code is faster than ;
    dir1 = -1;
  }
  else {
    digitalWrite(DirPin1, HIGH); //
   // PORTD |= B00001000;
    dir1 = 1;
  }

  if (step2 < 0) {
    digitalWrite(DirPin2, LOW);
    dir2 = -1;
  }
  else {
    digitalWrite(DirPin2, HIGH);
    dir2 = 1;
  }
  delayMicroseconds(5);
}

void LimitManager() {

  if (pitchTarget < 1000  || pitchTarget > 27000) {
    pitchTarget = pitchPosition;
  }
  if (rollTarget < 1000  || rollTarget > 27000 ) {
    rollTarget = rollPosition;
  }
}

void Initialize() {   // Use this function to move the rig at the right place at start up.
  MoveSteppers(-100, 100);
  delay(1000);
  MoveSteppers(100, -100);
    delay(1000);
  while(analogRead(btnPin)==HIGH){
    MoveSteppers(-100, -100);
  //  delay(1);         //Change the delay to tune speed
  }
  pitchPosition = 16384;
  rollPosition = 16384;
  delay(1000);

  }

I am considering making it open loop and make a spi positioning system.

I am not sure what you are aware of as the piece you have quoted made 3 separate points. However, in case of doubt, micro-stepping has nothing to do with altering the torque of a stepper motor. Even if the in-between steps have less torque the full torque will be applied at every full step.

this is why I asked this on this corner. Would I have needed this kind of beacon, I call my dad. he designed plotters late 70s. I understand the attitude, I know you guys here look at this weird question staring down a pyramid of knowledge. I came here for someone who has the spare time to look for a way for me to make it simpler to arrive at a defined point inside that pyramid. I do it all the time inside my pyramid for other humans.

ewell:
this is why I asked this on this corner. Would I have needed this kind of beacon, I call my dad. he designed plotters late 70s. I understand the attitude, I know you guys here look at this weird question staring down a pyramid of knowledge. I came here for someone who has the spare time to look for a way for me to make it simpler to arrive at a defined point inside that pyramid. I do it all the time inside my pyramid for other humans.

I can’t make sense of that. When you write you seem to assume that the reader knows as much about the project as you do whereas we know nothing about the project apart from what you tell us.

Take this, for example “this is why I asked this on this corner” - what does the first “this” refer to? What is it that you asked? The 2nd comment I wrote in Reply #10 does not refer to a question that you asked.

I’m not an Egyptologist so I don’t know anything about pyramids, but my programming projects work.

…R

When I wrote here I was expecting someone with way more experience in this field.
I'm sorry you don't know how the knowledge is build, it has a virtual pyramidal form. These kind of answers that you gave come mostly from arian people, too bad I ain't one.

ewell:
I'm sorry you don't know how the knowledge is build,

All I can say in response is that my programs work.

...R

ewell:
When I wrote here I was expecting someone with way more experience in this field.

Much more experience, sure, but which part of that experience of which field do you need?

Have you ever tried to explain your problem to e.g. your mother or brother, until they at least understood your problem? As long as you cannot communicate your problem, you are left alone with yourself.

With your concerns about blocking, if you can’t find the code resources you need to meet your exact requirements, there’s a high chance you may have to write your own stepper library, or multiplex the stepper control at a higher level in your code.

Only you can make that decision, because - only you have the requirements and specifications of the project in your head.

If you want third party assistance, I suggest initially developing those two documents as a project within themselves, with the participation of all stakeholders in the end result.

On.y then can you explore the tools and parts needed to realise those requirements & spec. It sounds like starting from where you are, and where you’re going might cost some money & time to define the problem before you actually build anything.