Adding New functionality to my program

Hey there,

I have a piece of code that i have had plenty of help to develop as I am by far no expert in writing code.
I really need help to add in one extra function into my script but don't have the exact knowledge to do it all by myself.

What i have is a program that turns a small stepper motor (28BYJ-48) in one direction 10 full turns (with an acceleration phase) before stopping. at the same time Pin A0 is using the ADC to convert an input.

What i want to achieve is the ability to reverse the motor direction at the very beginning of the script for just one full rotation, before i tare A0 and start taking readings. So as soon as a start my script by means of pullup or serial command, the motor reverses one turn followed by completing a tare of A0 and then continuing reading of the A0 pin whilst rotating the motor 10 times.

Any help would be much appreciated.

Taylor

//Include Arduino Library
#include <Arduino.h>

////////////////////////////////////////////////////////////////
//Define Parameters and pins
#define MINRPM 10  // in tenths rpm, 10 = 1 rpm (This is the startup RPM)
#define MAXRPM 100 // in tenths rpm, 100 = 10 rpm (This is maximum RPM after acceleration)
#define STARTBUTTONPIN A2
#define potentiometerPin A0

//Define interval for timing  rpm calculation and analogRead
#define INTERVAL 25000L   //  25000 µs = 25 ms = execution time, frequency 40 per second

//Define variables for the motor pins on ULN2003/ULN2004 motor driver
#define MOTOR1 8    // Blue   - 28BYJ48 pin 1, driver IN1
#define MOTOR2 9    // Pink   - 28BYJ48 pin 2, driver IN2
#define MOTOR3 10   // Yellow - 28BYJ48 pin 3, driver IN3
#define MOTOR4 11   // Orange - 28BYJ48 pin 4, driver IN4
// Red    - 28BYJ48 pin 5 (VCC)

// Define Motor rotations per single shaft rotation (reduction)
const int countsperrev = 4075.7728395; //  (4076??) number of steps per full revolution of external shaft

// Define tareValue for Tare function
int tareValue = 0;

//////////////////////////////////////////////////
// Setup Script (Beginning of each test, "once off')
void setup()
{
  // Start Serial for debugging
  Serial.begin(9600);
  // Activate Internal Pullup Resistor for STARTBUTTONPIN
  pinMode(STARTBUTTONPIN, INPUT_PULLUP);
  // Set stepper pins as OUTPUT
  pinMode(MOTOR1, OUTPUT);
  pinMode(MOTOR2, OUTPUT);
  pinMode(MOTOR3, OUTPUT);
  pinMode(MOTOR4, OUTPUT);
}

/////////////////////////////////////////////////
// Loop script (Run once per cycle)
void loop()
{
  Serial.println("Happy with the Machine Setup? Type 'S' or press STARTBUTTON to start the Test");
  while (!startStop()) ; // do nothing until start/stop condition is true
  tareValue = analogRead(potentiometerPin);
  Serial.println("Test Started, this will take 60 seconds");
  Serial.print("Tare Value: "); Serial.println(tareValue);
  unsigned long time = micros();
  doOneCycle();
  Serial.print("Cycle Time [s]: ");
  Serial.println((micros() - time) / 1000000.0);
  Serial.println("Test Complete");
  Serial.println("Please Unplug DC Jack While Cleaning The Device");
  Serial.println("");
  delay(500); // half second pausing to prevent next start due to possible button bouncing
}

////////////////////////////////////////////////
// Display Begin
void displayBegin() {}

// Display Rotations
void displayRotations(unsigned int steps2go)
{ // round steps2go to full revolutions
  int rotationsLeft = (steps2go + countsperrev / 2 - 1) / countsperrev;
  //Serial.print("rotations: ");Serial.println(rotationsLeft);
}

// Display Results
void displayResults(int potival, int potiAvg)
{
  Serial.print("Final Value: "); Serial.println(potival);
  Serial.print("Average Value: "); Serial.println(potiAvg);
  Serial.print("Tare Value: "); Serial.println(tareValue);
}

//////////////////////////////////////////////////
// Calibration for Load Cell
long time = 0; //
int timeBetweenReadings = 400;

float loadA = 0;  // Calibration weight 1 (grams)
int analogvalA = 0;  // Change this for calibration

float loadB = 10000; // Calibration weight 2 (grams)
int analogvalB = 511;  // Change this for calibration

float analogValueAverage = 0;

//////////////////////////////////////////////////////
// MapFloat condition for Load Cell Calibration
float analogToLoad(float analogval)
{
  float load = mapfloat(analogval, analogvalA, analogvalB, loadA, loadB);
  return load;
}

float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

///////////////////////////////////////////////////
// Averaging Load cell values, Smoothing data
void potentiometerTask(int &load)
{
  //analogValueAverage = 9*analogValueAverage/10 + analogRead(potentiometerPin); // running average
  //analogValueAverage = (9 * analogValueAverage +  analogRead(potentiometerPin))/10; // running average
  analogValueAverage = 0.90 * analogValueAverage + 0.10 * analogRead(potentiometerPin); // running average
  if (millis() - time >= timeBetweenReadings)
  {
    load = analogToLoad(analogValueAverage - tareValue);
    Serial.print("load: "); Serial.println(load);
    //time = millis();
    long time = millis();
  }
}

/////////////////////////////////////////////////////////
// Initiating Serial Read Commands for Start/Stop
boolean startStop()
{ // handles start/stop by recognising button press or serial 's' received
  // returns 'true' if start/stop condition is detected
  static byte oldState = false;
  byte result = false;
  // first check serial for small letter 's'
  while (Serial.available())
  {
    if (Serial.read() == 's') result = true;
  }
  byte newState = !digitalRead(STARTBUTTONPIN);
  if (newState != oldState)
  {
    oldState = newState;
    if (newState) result = true;
  }
  return result;
}

/////////////////////////////////////////////////////////
// Motor Acceleration Parameters
void rpmTask(unsigned long time, int &rpm, int &steptime)
{ // input time in microseconds since cycle started
  // returns rpm and steptime in microseconds
#define ACCELLTIME 1000000L  // microseconds for accelleration from MINRPM to MAXRPM
  if (time >= ACCELLTIME) rpm = MAXRPM;
  else rpm = MINRPM + time * (MAXRPM - MINRPM) / ACCELLTIME;
  steptime = 60000000L * 10 / rpm / countsperrev;
}

/////////////////////////////////////////////////////////////////////////////
// Create Parameters for 'OneStep' of Motor
void doOneStep(int8_t motorDirection, int motorSpeed)
{ // step motor one single step into 'motorDirection' -1 or 1
  // if called in very short time, delay action up to desired 'motorSpeed'
  static int8_t currentstep = 0;
  static unsigned long lastSteptime;
  long now = micros();
  long diff = now - lastSteptime;
  if (diff < motorSpeed)
  {
    delayMicroseconds(motorSpeed - diff);
    lastSteptime += motorSpeed;
  }
  else lastSteptime = now;
  currentstep += motorDirection;
  if (currentstep >= 8) currentstep = 0;
  else if (currentstep < 0) currentstep = 7;
  byte stepperLookup[8] = {B00001, B00011, B00010, B00110, B00100, B01100, B01000, B01001};
  digitalWrite(MOTOR1, bitRead(stepperLookup[currentstep], 0));
  digitalWrite(MOTOR2, bitRead(stepperLookup[currentstep], 1));
  digitalWrite(MOTOR3, bitRead(stepperLookup[currentstep], 2));
  digitalWrite(MOTOR4, bitRead(stepperLookup[currentstep], 3));
}
///////////////////////////////////////////////////////
// Creating 'doOneStep' For Stepper Motor
void stepperTask(int stepTime)
{
  doOneStep(1, stepTime);
}
//////////////////////////////////////////////////
// Creating 'OneCycle' using all Parameters
void doOneCycle()
{
  unsigned int totalSteps = 10L * countsperrev; // total = 10 rotations to go
  int rpm = 0;
  int stepTime = 0;
  int potentiometerValue = 0;
  int potentiometerSamples = 0;
  long potentiometerValueSum = 0;
  boolean finished = false;
  unsigned long cycleTime = 0;
  unsigned long intervalTime = 0;
  int intervalCount = 0;
  rpmTask(0, rpm, stepTime); // initial calculation of rpm and stepTime
  displayBegin(); // initial output
  displayRotations(totalSteps); // initial output
  unsigned long lastTime = micros();
  while (!finished)
  {
    long now = micros();
    long diff = now - lastTime;
    lastTime = now;
    cycleTime += diff;
    intervalTime += diff;
    if (intervalTime >= INTERVAL)
    {
      intervalTime = 0;
      intervalCount++;
      if (intervalCount >= 20) // after 20 intervals, update display
      {
        intervalCount = 0;
        unsigned long tm = micros();
        displayRotations(totalSteps);
        //Serial.println(micros()-tm);  //Debugging Monitor (Duration of Each process in Arduino)
        //Serial.println(potentiometerValue);
      }
      else if (intervalCount % 4 == 1) rpmTask(cycleTime, rpm, stepTime);
      else if (intervalCount % 4 == 2 && startStop()) totalSteps = 1; // cancelled, prepare for final last step
      else // all other intervals
      {
        potentiometerTask(potentiometerValue); // measure value
        potentiometerValueSum += potentiometerValue; // add up values
        potentiometerSamples++; // increment number of samples
      }
    }
    stepperTask(stepTime); // step the stepper
    totalSteps--;
    if (totalSteps == 0) finished = true;
  }
  int average = potentiometerValueSum/potentiometerSamples;
  displayResults(potentiometerValue, average);
}

Taylor_woods:
What i want to achieve is the ability to reverse the motor direction at the very beginning of the script for just one full rotation

Put the code to do this in the setup() function.

How will it recognise when the start button has been pressed then?

If you literally want it to do nothing until a button is pressed you can add something like this in setup()

pinMode(buttonPin, INPUT_PULLUP);
while (digitalRead(buttonPin) == HIGH) {
}

This will stay in the WHILE loop until the button is pressed.
(Assumes the button connects the pin to GND when pressed)

...R

Robin2, Yes this is already in the setup script

// Setup Script (Beginning of each test, "once off')
void setup()
{
  // Start Serial for debugging
  Serial.begin(9600);
  // Activate Internal Pullup Resistor for STARTBUTTONPIN
  pinMode(STARTBUTTONPIN, INPUT_PULLUP);

What i want to know how to do is, once the button is pressed, make the motor turn backwards for one full rotation, before the rest of the script starts. Is this possible?

Taylor_woods:
What i want to know how to do is, once the button is pressed, make the motor turn backwards for one full rotation, before the rest of the script starts. Is this possible?

Post your complete code, not just a snippet.

Yes that is possible.

You say you have code that can make the motor go forwards. Use that as a basis for a piece of code that can make the motor go backwards. Put that piece of code in setup() and tell us what happens.

...R

Hi
Just to make sure, how are you driving the stepper and providing it power?

Tom.... :slight_smile:

Complete code is posted in the first comment :slight_smile: Yeah i understand that it needs to go in setup() thanks to Henry_Best, but i just do not know exactly what to write. Could you please assist Robin2?

TomGeorge, I am supplying the stepper motor power via an external 9v power source connected to gnd on the arduino and positive of the ULN2003 motor driver board. :slight_smile:

I knew I recognized that code but I had to search through this Thread and this Thread to find my earlier comment which I will repeat here because it is still valid.

However I have not been able to follow the logic through it. Maybe it's because there is a lot more going on than simply averaging some readings. Perhaps you can explain the flow.

Have you tried adding Serial.println(vvv) at various points to see what values the variables have at that stage in the process.

Splitting your project over 3 Threads just wastes our time.

...R

Sure, no problems.. but to me they are three different problems that deserved three separate threads. It doesn't matter what the code is, each issue requires different peoples knowledge and input.... nowhere does it state that one piece of code requires on thread!

I dont understand your comment, as it has no relevance whatsoever to the issue at hand. If you read through the three posts you'd see that others have helped with certain issues, and that this thread addresses a stepper motor development. Im assuming you know how to implement this as you are a moderator so, are you able to help me? Or are you just wasting my time aswell.

Taylor_woods:
If you read through the three posts you'd see that

Right there is the problem ...
I don't want to have to read three Threads.

But, because I did contribute to another Thread that remains in my mind and is confusing because you seem to have the same code here. Perhaps I will just leave this for others.

...R

They're three completely different questions... you make no sense. You read far more than three threads every day im sure, who cares if they're from one person.