///////////////////////////////////////////////////////////
// Stepper Motor skecth for use with the EasyDriver v4.2 //
// JM mod to add for 16th mode 15 Mar 2023_1651
///////////////////////////////////////////////////////////
// Dan Thompson 2010
//
// Use this code at your own risk.
//
// For all the product details visit http://www.schmalzhaus.com/EasyDriver/
// For the full tutorial visit http://danthompsonsblog.blogspot.com/
// added Date function see https://www.softwaretestinghelp.com/date-and-time-in-cpp/
// #include <iostream>
// #include <ctime>
// using namespace std;
#include <Wire.h>
// #include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// JM mod 02 Mar 2023 taken from sketch OLEDfeathering.ino
#define WIRE Wire
////// ED_v4jm Step Mode Chart ////////////////
// WA42 0.9deg 400 for 1 rev //
// //
// MS1 MS2 MS3 Resolution(2 phase) Steps //
// L L Full step 400 //
// H L Half step 800 //
// L H Quarter step 1600 //
// H H Eighth step 3200 //
// H L L 16th step 6400 //
// //
////////////////////////////////////////////////
// #include <DrDuino_Explorer.h>
int DIR = 3; // PIN 3 = DIR
int STEP = 2; // PIN 2 = STEP
int MS1 = 4; // PIN 13 = MS
int MS2 = 5; // PIN 9 = MS2
int MS3 = 6;
int SLEEP = 12; // PIN 12 = SLP
int LED = 10; // enable when MS3 in operation
// ArdFrm Example 5 - Receive with start< and end> markers combined with parsing
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
char mtrType[numChars] = { "" };
int integerFromPC = 0;
float floatFromPC = 0.0;
boolean newData = false;
String prompt = "Set motor, mode (1,2,4,8,16) & required steps eg <2T15, 16, 3> ";
int user_input;
int no_of_steps = 0;
int reqSteps;
int i = 0;
int modeType;
String motorType, motor;
boolean mtrValid = false; //is the mType a valid value (T or F)
// JM mod 02 Mar 2023 taken from sketch OLEDfeathering.ino
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &WIRE);
//***************************************************************************
//void setup
//***************************************************************************
void setup() {
Serial.begin(9600); // open the serial connection at 9600bps
pinMode(DIR, OUTPUT); // set pin 3 to output
pinMode(STEP, OUTPUT); // set pin 2 to output
pinMode(MS1, OUTPUT); // set pin 13 to output
pinMode(MS2, OUTPUT); // set pin 9 to output
pinMode(MS3, OUTPUT); // set pin 6 to output
pinMode(SLEEP, OUTPUT); // set pin 12 to output
pinMode(LED, OUTPUT); // set pin 13 to output
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32
display.display();
delay(1000);
display.clearDisplay();
MitchSplashScreen();
// read taken from ArdForum afSerislRead.ino
// Serial.println("Set motor, mode (1,2,4,8,16) & required steps eg <2T15, 16, 3> ");
Serial.println(prompt);
Serial.println();
// recvWithStartEndMarkers();
}
//***************************************************************************
//void loop
//***************************************************************************
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
// showParsedData();
Serial.print(F("Motor is "));
Serial.println(mtrType);
Serial.print("modeType is ");
Serial.println(modeType);
Serial.print("No of steps are ");
Serial.println(reqSteps);
// no_of_steps = modeType * 200; // dt's original method
// no_of_steps = 400 * 16;
// int modeType = 1;
// no_of_steps = 5;
// select Motor type for options 1-6
motorType = String(mtrType);
selectMotor(motorType);
// returns motorType: string, updates mtrValid
if (mtrValid == false) {
Serial.print(F("Invalid motor: "));
Serial.println(motorType);
} else {
// motor type OK
Serial.print(F("Enabling Motor "));
Serial.println(motorType);
motor = "motor " + motor + ", mode " + modeType + ", steps " + reqSteps + "...";
// Serial.println(motor);
// send message to display
int mlen = motor.length() + 1;
// Serial.println(mlen);
char Msg[mlen];
motor.toCharArray(Msg, mlen);
DisplayMessage2User(Msg, 1);
// check if mode is one of Full to 1/16th;
// if near < number, select Next ie 6 > 8, else fail ie > 16!
// motor mode OK, check motor type
modeType = checkMotorMode(modeType);
// returns int:modeType
Serial.print("checkMode is ");
Serial.println(modeType);
if (modeType == 0) {
Serial.println(F("Invalid mode! "));
} else {
// enable the motor
digitalWrite(DIR, LOW); // Set the direction change LOW to HIGH to go in opposite direction
digitalWrite(MS1, MS1_MODE(modeType, reqSteps)); // Set state of MS1 based on the returned value from the MS1_MODE() switch statement.
digitalWrite(MS2, MS2_MODE(modeType)); // Set state of MS2 based on the returned value from the MS2_MODE() switch statement.
if (modeType == 16) {
digitalWrite(MS3, LOW);
digitalWrite(LED, HIGH);
}
digitalWrite(SLEEP, HIGH); // Set the Sleep mode to AWAKE.
// int i = 0; // Set the counter variable.
// JM mod 15 Mar 2023_1541
for (i = 0; i < reqSteps; i++) { //Loop the forward stepping enough times for motion to be visible
// while (0 < i < no_of_steps) {
// Iterate for 200, then 400, then 800, then 1600 steps.
// while (i < (400*16))
// Iterate for 400 steps at a full step WA42 0.9 deg = 400
// Serial.print("Step ");
// Serial.println(i);
// Then reset to 200 and start again.
digitalWrite(STEP, LOW); // This LOW to HIGH change is what creates the..
digitalWrite(STEP, HIGH); // .."Rising Edge" so the easydriver knows to when to step.
delayMicroseconds(2000); // This delay time determines the speed of the stepper motor.
// Delay shortens from 1600 to 800 to 400 to 200 then resets
// i++;
}
// modeType = modeType * 2; // Multiply the current modeType value by 2 and make the result the new value for modeType.
// // This will make the modeType variable count 1,2,4,8, 16 each time we pass though the while loop.
// delay(500);
// digitalWrite(SLEEP, LOW); // switch off the power to stepper
// digitalWrite(LED, LOW); // turn off MS3 LED
// Serial.print("SLEEPING..");
// delay(1000);
// Serial.print("z");
// delay(1000);
// Serial.print("z");
// delay(1000);
// Serial.print("z");
// delay(1000);
// Serial.println("");
}
}
digitalWrite(SLEEP, HIGH);
digitalWrite(LED, LOW); // turn off MS3 LED
Serial.println("AWAKE!!!"); // Switch on the power to stepper
delay(1000);
// re-initialise
newData = false;
}
delay(10000);
// read taken from ArdForum afSerislRead.ino
Serial.println("Set motor, mode (1,2,4,8,16) & steps eg <WA42, 16, 3> ");
Serial.println();
}
//***************************************************************************
// recvWithStartEndMarkers
//***************************************************************************
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
} else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//***************************************************************************
//parseData - note char & 2 ints (can be char, int or float)
//***************************************************************************
int parseData() { // split the data into its parts
char* strtokIndx; // this is used by strtok() as an index
// motor type
strtokIndx = strtok(tempChars, ","); // get the first part - the string
// Serial.println(strtokIndx);
strcpy(mtrType, strtokIndx); // copy it to messageFromPC
// mode
strtokIndx = strtok(NULL, ","); // get the second part - the integer
// Serial.println(strtokIndx);
modeType = atoi(strtokIndx); // convert this part to an integer
// reqSteps
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
// Serial.println(strtokIndx);
reqSteps = atoi(strtokIndx); // convert this part to an integer
// strtokIndx = strtok(NULL, ",");
// floatFromPC = atof(strtokIndx); // convert this part to a float
return mtrType, modeType, reqSteps;
}
//***************************************************************************
//showParsedData
//***************************************************************************
void showParsedData() {
Serial.print("Motor ");
Serial.println(mtrType);
Serial.print("modeType ");
Serial.println(modeType);
Serial.print("no_of_steps ");
Serial.println(reqSteps);
// Serial.print("Float ");
// Serial.println(floatFromPC);
}
//***************************************************************************
//MS1_MODE(int MS1_StepMode, int no_of_steps)
//***************************************************************************
int MS1_MODE(int MS1_StepMode, int no_of_steps) { // A function that returns a High or Low state number for MS1 pin
switch (MS1_StepMode) { // Switch statement for changing the MS1 pin state
// Different input states allowed are 1,2,4 or 8
case 1:
MS1_StepMode = 0;
Serial.print("Step Mode is Full... ");
Serial.println(no_of_steps);
break;
case 2:
MS1_StepMode = 1;
Serial.print("Step Mode is Half... ");
Serial.println(no_of_steps);
break;
case 4:
MS1_StepMode = 0;
Serial.print("Step Mode is Quarter... ");
Serial.println(no_of_steps);
break;
case 8:
MS1_StepMode = 1;
Serial.print("Step Mode is Eighth... ");
Serial.println(no_of_steps);
break;
case 16:
MS1_StepMode = 1;
Serial.print("Step Mode is 16th... ");
Serial.println(no_of_steps);
break;
}
return MS1_StepMode;
}
//***************************************************************************
// MS2_MODE(int MS2_StepMode)
//***************************************************************************
int MS2_MODE(int MS2_StepMode) { // A function that returns a High or Low state number for MS2 pin
switch (MS2_StepMode) { // Switch statement for changing the MS2 pin state
// Different input states allowed are 1,2,4 or 8
case 1:
MS2_StepMode = 0;
break;
case 2:
MS2_StepMode = 0;
break;
case 4:
MS2_StepMode = 1;
break;
case 8:
MS2_StepMode = 1;
break;
case 16:
MS2_StepMode = 0;
break;
}
return MS2_StepMode;
}
//***************************************************************************
//DisplayMessage2User
//***************************************************************************
void DisplayMessage2User(char advice[], int fontsize) {
// Serial.println(F("Entered 2User"));
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(fontsize);
display.println((advice));
display.display();
}
//***************************************************************************
//MitchSplashScreen
//***************************************************************************
void MitchSplashScreen() {
// Serial.println(F("Entered MitchSplashScreen"));
display.clearDisplay();
display.setTextSize(2); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(10, 0); // Start at top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
display.println(F("Mitch"));
display.setTextSize(1);
display.setCursor(10, 15); // Start at top-left corner
// get current date & time
// see NTP over ethernet solutions
display.println(F("20 Mar 2023"));
display.setCursor(35, 23); // Start at top-left corner
// display.println(( FwVersion));
display.display();
delay(100);
}
//***************************************************************************
//select Motor type
//***************************************************************************
String selectMotor(String motorType) {
// select from the available Motor types
// updated 15 Mar 2023_1244, uses mtrValid global
if (motorType == NULL) {
Serial.println(F("Enter type: 2T35, 2T15 or WA42"));
while (Serial.available() == 0) {} //wait for data available
motorType = Serial.readString(); //read until timeout
motorType.trim(); // remove any \r \n whitespace at the end of the String
}
char steppers[] = "2T35, 2T15, or WA42";
char* pch;
// convert motorType to a char Mtr
int slen = motorType.length() + 1;
char Mtr[slen];
// delay(1000);
motorType.toCharArray(Mtr, slen);
// Serial.print(F("slen is "));
// Serial.println(slen);
// Serial.println(Mtr);
pch = strstr(steppers, Mtr);
if (pch != NULL) {
// Serial.print(F("Selected motor type is "));
// Serial.println(Mtr);
mtrValid = true;
// get steps/revolution
no_of_steps = setAttributes(motorType);
motor = "Using " + motorType + ", steps " + no_of_steps + "...";
} else {
// Serial.println(F("Invalid motor type"));
mtrValid = false;
motor = "Invalid motor type " + motorType + "...";
// Serial.println(motor);
}
//***************************************************************************
// send message to display
int mlen = motor.length() + 1;
// Serial.println(mlen);
char Msg[mlen];
motor.toCharArray(Msg, mlen);
DisplayMessage2User(Msg, 1);
// return motorType;
}
//***************************************************************************
// set motor attributes
//***************************************************************************
int setAttributes(const String motorType) {
if (motorType == "2T35") {
// step = 3.75 deg
int no_of_steps = 360 / 3.75;
return no_of_steps;
} else if (motorType == "2T15") {
// step = 18 deg
int no_of_steps = 360 / 18;
return no_of_steps;
} else if (motorType == "WA42") {
// step = 0.9 deg
int no_of_steps = 360 / 0.9;
return no_of_steps;
}
// debug
Serial.println(no_of_steps);
Serial.println();
}
// //***************************************************************************
// //Reset Easy Driver pins to default states
// //***************************************************************************
// void resetBEDPins() {
// digitalWrite(stp, LOW);
// digitalWrite(dir, LOW);
// digitalWrite(MS1, LOW);
// digitalWrite(MS2, LOW);
// digitalWrite(MS3, LOW);
// digitalWrite(EN, HIGH);
// digitalWrite(LDd, LOW);
// }
//***************************************************************************
//chekcMotorMode
//***************************************************************************
// mod 21 Mar 2023_1722 - removed debug prints...
int checkMotorMode(int modeType) {
// mode (stepper) values (1,2,4,8,16)
int modeValues[] = { 1, 2, 4, 8, 16 };
int mtrMode;
for (int i = 0; i < 5; i++) {
mtrMode = modeValues[i];
// Serial.print(mtrMode);
if (modeType == modeValues[i]) {
Serial.print("chkMtr1Mode is ");
Serial.println(modeType);
// valid modeType;
// modeType = mtrMode;
return mtrMode;
break;
// } else if (modeType < modeValues[i]) {
} else if (modeType < mtrMode) {
Serial.print("chkMtr2Mode is ");
Serial.println(modeType);
Serial.print("chkmode3Type changed to ");
Serial.println(modeValues[i]); // correct the value, select mtrMode
// modeType = mtrMode;
return mtrMode;
break;
} else if (i == 4) {
// end of valid values - failed
// Serial.print("chkmode4Type is ");
// Serial.println(0);
// modeType = 0;
return 0;
}
}
}
I'm using a DrDuino Explorer with a BigEasyDriver board and Wantai 428YBHM809 motor