Modifying code to work with a different motor and driver board

 Hi, I am raking my brain on this. I am using an Inland Nano v3 board (a knock off Arduino Nano v3).  A 12v  bi-directional stepper motor I got at Micro Center (the $13.99 one with 4 wires). A DRV 8825 stepper driver board wired to D2 for the direction pin and D3 for the step pin. And an Inland R.E. sensor (a knock off KY040), wired to D7 for CLK, D8 for DT, and D9 for SW. 
 The original project calls for a una-directional, 12v stepper motor with a hall sensor built in and only has 3 wires for the motor and 5 for the hall sensor (3 for the sensor plus a power and a ground). The original driver board is the JYDQ 7v3. 
 I am using code from github provided by the uploader of the project on Thingiverse. I have made modifications for the DRV 8825 as provided for by the afore mentioned github repository. Where I run into problems is getting the reading from the KY040 to fit into the speed control portion of the code that is required for the DRV 8825 to run the motor.  I can interrupt the motor and reset it by pressing the button of the encoder. I can start the motor turning by turning the knob of the encoder. However, I want the motor speed to increase when I turn the knob further away from the start position and decrease when I move it back toward the start position. and this is not happening. I know which line will require a reading of the encoder, I just don't quite know how to go about it. 
 Here is the code I'm working with:
 #include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//#include <Fonts/FreeMono9pt7b.h>

#include <gfxfont.h>
#include <Arduino.h>
#include "A4988.h"
#include "TimerOne.h"

#define MOTOR_STEPS 200
#define DIR 2
#define STEP 3
A4988 stepper(MOTOR_STEPS, DIR, STEP);


const int GEAR_A = 17; //25
const int GEAR_B = 63; //30
const int SIGPR = 24;


#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);



#define DBG

#ifdef DBG
#define Serial_begin Serial.begin
#define Serial_println Serial.println
#define Serial_print Serial.print
#else
#define Serial_begin(x)
#define Serial_println(x)
#define Serial_print(x)
#endif

const int PinCLK = 7;                 // Used for generating interrupts using CLK signal
const int PinDT = 8;                  // Used for reading DT signal
const int PinSW = 9;                  // Used for the push button switch
bool bLastCLK = false;

const int PinSig = 4;

void setup() {
  Serial_begin(9600);
  Serial_println("Woolwinder");


  pinMode(PinSig, INPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);

  pinMode(LED_BUILTIN, OUTPUT);

  pinMode(PinCLK, INPUT);
  pinMode(PinDT, INPUT);
  pinMode(PinSW, INPUT_PULLUP);
  //attachInterrupt (1,isr,CHANGE);   // interrupt 1 is always connected to pin 3 on Arduino UNO
  bLastCLK = digitalRead(PinCLK);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3D); // initialize with the I2C addr 0x3D (for the 128x64)
  //display.setFont(&FreeMono9pt7b);

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 1);
  display.print("Woolwinder");
  display.display();
  delay(1000);

  Timer1.initialize(100);  // 10 us = 100 kHz
  Timer1.attachInterrupt(stepperAdvance);
  Serial_println("init.done");
  stepper.begin(150, 1); // This is required in the void setup. Here is where the sensor reading, conversion and output would need to go. as this tells the DRV 8825 how fast, and how much rotation the motor should take. 150 is a set speed, 1= full rotation as I understand the code. correct me if I'm wrong or missing some information.

}
unsigned int cnt = 0;
int iRPM = 0;
unsigned long iStepCount = 0;

/*void isr ()  {                    // Interrupt service routine is executed when a HIGH to LOW transition is detected on CLK
  bool bCLK=digitalRead(PinCLK);
  bool bDT=digitalRead(PinDT);

      Serial_print(bCLK);
      Serial_print(",");
      Serial_print(bDT);
      Serial_print("\n");

  bool up = bCLK == bDT;
  if(up) iRPM-=5; else iRPM+=5;
  if(iRPM<0) iRPM=0;
  if(iRPM>400) iRPM=400;}*/



void loop() {

  handleDisplay();
  cnt++;
  digitalWrite(LED_BUILTIN, ((cnt / 10) & 1) != 0);

  const int iMin = 30;
  analogWrite(2, iMin + (long(iRPM) * (255 - iMin) / 1000));

  if (iRPM < 1) return;
  stepper.rotate(360); //  This is required in the void loop to make the motor turn. As I understand the code again correct me if I'm wrong.

#ifdef DBG
  //*
  unsigned int iNM = millis();
  static unsigned int iLastLog = 0;
  if (iNM > iLastLog + 500) {
    iLastLog = iNM;

    const long iRot = (iStepCount * GEAR_A) / (GEAR_B * SIGPR);
    //const int iMSTEPS=(long(STEPS_PERREV*32)*GEAR_B)/GEAR_A;

    Serial_print(iRPM);
    Serial_print(",");
    Serial_print(iStepCount);
    Serial_print(",");
    Serial_print(iRot);
    Serial_print("\n");
    cnt = 0;
  }/**/
#endif

  //Serial.println("loop");
}

unsigned long iLastStep = 0;
bool bStepOn = false;
unsigned int iClick = 0;
bool bSig = false;

void stepperAdvance() {
  unsigned long iNow = micros();
  if (iNow < iLastStep) {
    iLastStep = iNow;
  }; //overflow

  bool bCLK = digitalRead(PinCLK);
  if (bLastCLK != bCLK) {
    bLastCLK = bCLK;
    bool bDT = digitalRead(PinDT);
    if (bDT != bCLK) {
      iRPM += 20;
      if (iRPM > 1000) iRPM = 1000;
    } else {
      iRPM -= 20;
      if (iRPM < 0) iRPM = 0;
    }
  }

  if (!(digitalRead(PinSW))) {
    //Serial_print(iClick);
    iClick++;
    if (iClick > 7000) {
      iStepCount = 0;
    };
    iRPM = 0;
  } else {
    iClick = 0;
  }


  bool bS = digitalRead(PinSig);
  if (bS != bSig) {
    iStepCount++;
    bSig = bS;
  };


  digitalWrite(3, iRPM > 0);



}

void handleDisplay() {
  String rpm = String(iRPM);
  const long iRot = (iStepCount * GEAR_A) / (GEAR_B * SIGPR);
  //iRot=iRevCount;
  String cnt = String(iRot);

  int iW = (long(iRPM) * 126) / 1000;

  display.clearDisplay();
  display.writeFastHLine(0, 0, 128, 1);
  display.writeFastVLine(0, 0, 16, 1);
  display.writeFastHLine(0, 15, 128, 1);
  display.writeFastVLine(127, 0, 16, 1);

  display.writeFillRect(1, 1, iW, 14, 1);

  //display.setTextSize(2);
  //display.setTextColor(WHITE);
  //display.setCursor(0,1);
  //display.print("RPM: ");
  //display.println(rpm);


  display.setTextSize(4);
  display.setCursor(0, 28);
  display.println(cnt);
  display.display();
}

Any advice is appreciated. Also if this problem has already been solve elsewhere please point it out to me. I just want to wind my yarn. :slight_smile: Preformatted text

Your post is very hard to read when posted like that. I posted it more properly:

Hi, I am raking my brain on this. I am using an Inland Nano v3 board (a knock off Arduino Nano v3). A 12v bi-directional stepper motor I got at Micro Center (the $13.99 one with 4 wires). A DRV 8825 stepper driver board wired to D2 for the direction pin and D3 for the step pin. And an Inland R.E. sensor (a knock off KY040), wired to D7 for CLK, D8 for DT, and D9 for SW.
The original project calls for a una-directional, 12v stepper motor with a hall sensor built in and only has 3 wires for the motor and 5 for the hall sensor (3 for the sensor plus a power and a ground). The original driver board is the JYDQ 7v3.
I am using code from github provided by the uploader of the project on Thingiverse. I have made modifications for the DRV 8825 as provided for by the afore mentioned github repository. Where I run into problems is getting the reading from the KY040 to fit into the speed control portion of the code that is required for the DRV 8825 to run the motor. I can interrupt the motor and reset it by pressing the button of the encoder. I can start the motor turning by turning the knob of the encoder. However, I want the motor speed to increase when I turn the knob further away from the start position and decrease when I move it back toward the start position. and this is not happening. I know which line will require a reading of the encoder, I just don't quite know how to go about it.
Here is the code I'm working with:

Thanks for doing that. It is my first post. Do I need to re-post my code?

The code is posted properly. Thanks for that.

Good to know. I wasn't sure.

"I want A to happen when I do B".

This is a common fallacy. There are two problems, not one. "I want A to happen" and "I want a variable to change when I do B".

So you should focus on if you can make the motor spin at different speeds. Change a variable. Compile and run. Did the motor rotate? Change the variable to something else. Compile and run. Did the motor rotate at different speed? If yes, you probably understand your A problem. If not, solve it. It has nothing to do with the KY040, which is your problem B, which you should treat as a separate thing.

I have done that, and it does change the motor speed. Unfortunately, I discovered that the library I am using will only accept two variables. The first being a number to represent motor speed and the other being a number representing how much rotation to complete. (e.g. 1 full turn, 1/2 turn etc.) Therefore I am actually going to have to find a different stepper library, if I want to use an equation to make the motor spin faster when the R.E turns more, and spin slower when I turn it back the other way. Thanks for your imput.

Can't you continuously send new commands to the stepper? If you command it to make 1 full turn, is it unresponsive during that turn? It seems the library that you use is meant for some very specific task. Like making a paper feeder perform its task in a printer. Try the first generic stepper motor library you can find.

The device I am modifying is a motorized yarn ball winding machine. The Arduino is only a Nano without wireless module. All user input comes through the R.E. and a power switch on the breadboard power supply.
At the moment, when I switch the machine on, the motor does not start until I turn the knob clockwise. If I turn it one click, the motor will start rotating fast enough for my needs. When I turn it one click counterclockwise It comes to a full stop all at once. Am I right in thinking that the motor having to start at, and stop from a high speed can damage it with continued use?
The original design used the R.E. knob as a speed control. For example one click equals slow rotation, the more clicks the faster the motor turns. I would use a potentiometer except, the push button acts as a break, stopping the motor immediately should the need arise. Here is a link to the Thingiverse thing I am working on. (Electric Wool Winder by ChPech - Thingiverse)

Are you relying on finding ready code for what you want to accomplish? It shouldn't be hard to write code of your own. Why do your motor run full speed after only one click on the rotary encoder? You won't harm the motor, but it creates an unpleasant user experience. If you can make the motor rotate after one click, you can make it rotate faster after two clicks, can't you?

I did not originate the design or the code. I am copying the project. The code was provided by the designer ChPech. (GitHub - ChristophPech/Woolwinder) I am only attempting to use a cheaper motor and the appropriate motor driver as suggested by C++ files found in the original gethub repository. This is the code as it comes from the repository (with no modifications). I am using this motor.(MCM Electronics Stepper motor - NEMA-17 size - 200 steps/rev, 12V 350mA - Micro Center) and one of these driver boards.(https://www.pololu.com/product/2133)

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//#include <Fonts/FreeMono9pt7b.h>

#include <gfxfont.h>
#include <Arduino.h>
#include "TimerOne.h"


const int GEAR_A = 17; //25
const int GEAR_B = 63; //30
const int SIGPR = 24;

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define DBG

#ifdef DBG
#define Serial_begin Serial.begin
#define Serial_println Serial.println
#define Serial_print Serial.print
#else
#define Serial_begin(x)
#define Serial_println(x)
#define Serial_print(x)
#endif

const int PinCLK = 7;                 // Used for generating interrupts using CLK signal
const int PinDT = 8;                  // Used for reading DT signal
const int PinSW = 9;                  // Used for the push button switch
bool bLastCLK = false;
const int PinSig = 4;

void setup() {
  Serial_begin(9600);
  Serial_println("Woolwinder");

  pinMode(PinSig, INPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);

  pinMode(LED_BUILTIN, OUTPUT);

  pinMode(PinCLK, INPUT);
  pinMode(PinDT, INPUT);
  pinMode(PinSW, INPUT_PULLUP);
  //attachInterrupt (1,isr,CHANGE);   // interrupt 1 is always connected to pin 3 on Arduino UNO
  bLastCLK = digitalRead(PinCLK);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
  //display.setFont(&FreeMono9pt7b);

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 1);
  display.print("Woolwinder");
  display.display();
  delay(1000);

  Timer1.initialize(100);  // 10 us = 100 kHz
  Timer1.attachInterrupt(stepperAdvance);
  Serial_println("init.done");
}

unsigned int cnt = 0;
int iRPM = 0;
unsigned long iStepCount = 0;

/*void isr ()  {                    // Interrupt service routine is executed when a HIGH to LOW transition is detected on CLK
  bool bCLK=digitalRead(PinCLK);
  bool bDT=digitalRead(PinDT);

      Serial_print(bCLK);
      Serial_print(",");
      Serial_print(bDT);
      Serial_print("\n");

  bool up = bCLK == bDT;
  if(up) iRPM-=5; else iRPM+=5;
  if(iRPM<0) iRPM=0;
  if(iRPM>400) iRPM=400;
  }*/

void loop() {
  handleDisplay();
  cnt++;
  digitalWrite(LED_BUILTIN, ((cnt / 10) & 1) != 0);

  const int iMin = 30;
  analogWrite(2, iMin + (long(iRPM) * (255 - iMin) / 1000));

  if (iRPM < 1) return;


#ifdef DBG
  //*
  unsigned int iNM = millis();
  static unsigned int iLastLog = 0;
  if (iNM > iLastLog + 500) {
    iLastLog = iNM;

    const long iRot = (iStepCount * GEAR_A) / (GEAR_B * SIGPR);
    //const int iMSTEPS=(long(STEPS_PERREV*32)*GEAR_B)/GEAR_A;

    Serial_print(iRPM);
    Serial_print(",");
    Serial_print(iStepCount);
    Serial_print(",");
    Serial_print(iRot);
    Serial_print("\n");
    cnt = 0;
  }/**/
#endif

  //Serial.println("loop");
}

unsigned long iLastStep = 0;
bool bStepOn = false;
unsigned int iClick = 0;
bool bSig = false;

void stepperAdvance() {
  unsigned long iNow = micros();
  if (iNow < iLastStep) {
    iLastStep = iNow;
  }; //overflow

  bool bCLK = digitalRead(PinCLK);
  if (bLastCLK != bCLK) {
    bLastCLK = bCLK;
    bool bDT = digitalRead(PinDT);
    if (bDT != bCLK) {
      iRPM += 20;
      if (iRPM > 1000) iRPM = 1000;
    } else {
      iRPM -= 20;
      if (iRPM < 0) iRPM = 0;
    }
  }

  if (!(digitalRead(PinSW))) {
    //Serial_print(iClick);
    iClick++;
    if (iClick > 7000) {
      iStepCount = 0;
    };
    iRPM = 0;
  } else {
    iClick = 0;
  }


  bool bS = digitalRead(PinSig);
  if (bS != bSig) {
    iStepCount++;
    bSig = bS;
  };


  digitalWrite(3, iRPM > 0);

}

void handleDisplay() {
  String rpm = String(iRPM);
  const long iRot = (iStepCount * GEAR_A) / (GEAR_B * SIGPR);
  //iRot=iRevCount;
  String cnt = String(iRot);

  int iW = (long(iRPM) * 126) / 1000;

  display.clearDisplay();
  display.writeFastHLine(0, 0, 128, 1);
  display.writeFastVLine(0, 0, 16, 1);
  display.writeFastHLine(0, 15, 128, 1);
  display.writeFastVLine(127, 0, 16, 1);

  display.writeFillRect(1, 1, iW, 14, 1);

  //display.setTextSize(2);
  //display.setTextColor(WHITE);
  //display.setCursor(0,1);
  //display.print("RPM: ");
  //display.println(rpm);

The multiple stepper libraries referenced in the C++ codes suggests to me that the designer may have considered other motor/driver combinations before choosing the Longs motor/JYDQ setup. I am simply pursuing one of these other option if possible.
I am new to C++ and coding all around so I may not be fully comprehending how the existing code should be adapted. Could you help me learn more about how the code works?

I have no problems understanding how to use libraries. They are written so that anyone can use them without having to deep into the functions and understand how they are coded.
But that is not the same as understanding code of whole projects. I don't use that kind of code. I prefer to write my own code. Exceptions are the very simple and usually well written examples that can be found in the Arduino IDE and any examples that come with any new library I install.
That's why I find it a bit hard to read through your posted code and understand it. And that's why I still recommend that you solve how to write code, which makes the motor rotate at a given speed and direction. Write a program, which makes the motor run at one speed and direction for 3 seconds, then stop for 2 seconds, then run at another speed and direction for 4 seconds, then stop, etc. The examples in the Arduino IDE might work very well for you. Then write another program, which prints the rotary encoder step variable in a serial monitor. After that, figure out how you combine these two things.
If you instead want to modify the program you found to work with your setup (switching the type of stepper motor and switching the type of stepper driver and whatnot), especially if you don't understand the code, well, that's a bit like having someone else write the code for you.

Ah. I understand. Please forgive my unintended transgression. I am self taught so your explanation is my first lesson in "programmer etiquette ". Thanks so much :sweat_smile:. I am, at this moment, taking your advice and going back to square one to write my very first lines of original code for the project. I guess this means I'm ready to leave the wading pool and venture into the deep end of programming, which is what I've wanted to do since I was a kid.

Good for you! Well, I wouldn't call it an etiquette. But I believe that's how most people like to help each other here. We guide each other. We don't carry each other.

The more the help requests lean towards the "carry me" end, the more people are guided to a section in this forum, where they can ask someone to code for money. The "guide me" type of requests, however, get a lot of attention.

I'm hoping to learn enough as I go along to someday be able to make money doing it. Sadly I grew up in the Middle of nowhere Missouri in the 1980's. I didn't get much exposure to electronics and computers until 1987 or so and then it was only one class a week on touch typing. Even in high school, we only got to use the computer lab for English assignments. All my programming was self taught at home on a Commodore 64. It was 1994 when I got an old 888 handed down to me. and 1997 when I finally built my first 386.
I am a firm believer in you're never too old to follow your dreams. So here I am taking step one on my thousand mile journey.

After further research, I've learned the limits of my little motor. It's top speed is the minimum speed I need for the project. As a shade tree mechanic, I know it is ill advised to run a motor at top speed for long periods of time. So I will be getting the parts to do this with the bigger, more powerful, motor soon. Thanks for all the guidance as I step from working on cars to electronics. See all of you out there soon.

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