Mech Eng student need help with programming for thesis. PLEASE

Hi there,

My aim is to create a code that controls a stepper motors speed and duration while simultaneously reading a potentiometers' value through an LCD display.

I currently have access to an IIC/I2C Serial 2.5" LCD 1602 Display Module, A Load cell amplifier of which I made myself to simulate a potentiometer on the output side, a BYJ48 stepper motor and ULN2004 motor driver.

What I really want to add is a functionality for the motor to build initially from 7rpm to 35rpm over 5 seconds, displaying this on the lcd.

Then for the motor to do a certain amount of turns, lets say 10 and I want the LCD to count down from 10 to 0 as it progresses.

I then want to use the second line of my LCD display to show feedback from my 'potentiometer' in a form of units such as Volts.

Finally once the motor has stopped I want the Arduino to average the feedback from the 'potentiometer' during the course of the test and then display this average on the LCD display.

I am getting there, but I really do not have the knowledge to complete it.
I have the mechanical and electrical know-how but no idea on the programming front.

PLEASSSEEE HELPPPP.

Lubrication_Machine_Program_V2.ino (4.91 KB)

/*
Connect the LCD:
VCC -> 5V,
GND -> GND,
SDA -> A4,
SCL -> A5

Connect the 24BYJ-48 Stepper motor:
IN1 -> D8
IN2 -> D9
IN3 -> D10
IN4 -> D11
VCC ... 5V Prefer to use external 5V Source
   Gnd
   
Connect the load cell amplifier as if it is a potentiometer:
5V -> 5V
GND -> GND
OUT -> A0
*/
////////////////////////////////////////////////////////////////////////////////
// Include Libraries
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

////////////////////////////////////////////////////////////////////////////////

// Declare variables for the motor pins
int IN1 = 8;	// Blue   - 28BYJ48 pin 1
int IN2 = 9;	// Pink   - 28BYJ48 pin 2
int IN3 = 10;	// Yellow - 28BYJ48 pin 3
int IN4 = 11;	// Orange - 28BYJ48 pin 4
// Red    - 28BYJ48 pin 5 (VCC)

int Steps = 0;
boolean Direction = true;
unsigned long last_time;
unsigned long currentMillis ;
int steps_left = 4096;
long time;

// Declare variables for LCD display
#define I2C_ADDR 0x27
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin, BACKLIGHT_PIN, POSITIVE);
LCD *myLCD = &lcd;

// Declare variables for load cell amplifier
int SENSOR_PIN = 0;               // center pin of the potentiometer



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  // Declare the motor pins as outputs
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  Serial.begin(9600);

  // Begin LCD display, welcome and dispaly speed and rotation

  lcd.begin(16, 2);               // initialize the lcd
  lcd.home ();                    // go home
  lcd.print("Welcome to the Back-to-Back Capstan Test Machine");

  lcd.home();                     // Clear screen
  lcd.print("speed:");            // Display speed

  lcd.setCursor(10, 0);           // Go to end of line 1
  lcd.print("n/min");             // Display rotations per minute

  delay(1000);

  lcd.home();                     // Clear screen
  lcd.setCursor(0, 0);            // Go to beginning again
  lcd.print("turns left:");        // Remaining test time count down
}
////////////////////////////////////////////////////////////////////////////////
void loop()
{
  while (steps_left > 0) {
    currentMillis = micros();
    if (currentMillis - last_time >= 1000) {
      stepper(1);
      time = time + micros() - last_time;
      last_time = micros();
      steps_left--;
    }
  }
  Serial.println(time);
  Serial.println("Wait...!");
  delay(2000);
  Direction = !Direction;
  steps_left = 4096;
}
///////////////////////////////////////////////////////////////////////////////
// Set pins to ULN2003 high in sequence from 1 to 4

void stepper(int xw) {
  for (int x = 0; x < xw; x++) {
    switch (Steps) {
      case 0:
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
        break;
      case 1:
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, HIGH);
        break;
      case 2:
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
        break;
      case 3:
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
        break;
      case 4:
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
        break;
      case 5:
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
        break;
      case 6:
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
        break;
      case 7:
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
        break;
      default:
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
        break;
    }

    ////////////////////////////////////////////////////////////////////////////////
    // Display Load cell value

    int sensorValue = analogRead(SENSOR_PIN);
    // set cursor to second row, first column
    lcd.setCursor(0, 1);
    float voltage = sensorValue * (5.0 / 1023.0);
    lcd.print(voltage);
    lcd.print("        ");
    delay (100);

    ////////////////////////////////////////////////////////////////////////////////
    SetDirection();
  }
}
void SetDirection() {
  if (Direction == 1) {
    Steps++;
  }
  if (Direction == 0) {
    Steps--;
  }
  if (Steps > 7) {
    Steps = 0;
  }
  if (Steps < 0) {
    Steps = 7;
  }

}

And DO NOT CROSS-POST, CROSS-POSTING WASTES TIME.

Duplicate deleted.

You didn't change anything!

Who said anything about change?
I just posted it so people on phones and tablets could see the code.

Oh ok. well thank you
Are you able to help.. Please?? :slight_smile:

What does it do that you don't want it to?
What doesn't it do that you do want it to?
What do our debug prints tell you it is doing?

Hi,
How is the load cell feedback, from what.
A diagram or picture of your project would help heaps.
What is the application, if any, usually these projects are proof of concept.

Tom..... :slight_smile:

So basically i am designing a back to back capstan machine to compare two lubricants against each other. It will look something like what you see in the image attached. What i need to do is develop an all in one program that allows me to press a button, the motor starts at a certain rpm (7rpm), accelerates over a period of time (5 seconds) to another rpm (35rpm) and then completes 10 full rotations. Meanwhile the top lime of the LCD will display this information giving feedback of speed and also rotations left. The load cell will flex with regards to slip from a wire wrapped around a shaft connected to the motor. what I want the load cell to do is send feedback to the arduino via a circuit i have developed (this circuit looks like a potentiometer to the arduino and therefore code will be exactly like a potentiometer), the only difference is that i want the LCD second line to display the value as the motor runs, and then once complete i want the arduino to calculate the average of all the potentiometer values and display this on the LCD as a summary. Hope this makes sense, if not ill try again. haha.

I was thinking I could use something like this code for the stepper motor end instead?
What i don't know how to do AWOL is make sure both codes are working at the same time, along with enabling the LCD interface properly and finally i don't know have to make it all automated to a single switch for on/ off (in emergency)

#include <CustomStepper.h>

//Full constructor, just the first 4 parameters are necessary, they are the pins connected to the motor,
//the others are optional, and default to the following below
//the 5th paramater is the steps sequence, where the 1st element of the array is the number of steps
//it can have a maximum of 8 steps
//the 6th parameter is the SPR (Steps Per Rotation)
//the 7th parameter is the RPM
//the 8th parameter is the rotation orientation
CustomStepper stepper(2, 3, 4, 5, (byte[]){8, B1000, B1100, B0100, B0110, B0010, B0011, B0001, B1001}, 4075.7728395, 12, CW);
boolean rotate1 = false;
boolean rotatedeg = false;
boolean crotate = false;

void setup()
{
//sets the RPM
stepper.setRPM(35);
//sets the Steps Per Rotation, in this case it is 64 * the 283712/4455 annoying ger ratio
//for my motor (it works with float to be able to deal with these non-integer gear ratios)
stepper.setSPR(4075.7728395);
}

void loop()
{
//when a command is finished it the isDone will return true, it is important to notice that
//you can't give one command just after another since they don't block the execution,
//which allows the program to control multiple motors
if (stepper.isDone() && rotate1 == false)
{
//this method sets the direction of rotation, has 3 allowed values (CW, CCW, and STOP)
//clockwise and counterclockwise for the first 2
stepper.setDirection(CW);
//this method sets the motor to rotate a given number of times, if you don't specify it,
//the motor will rotate untilyou send another command or set the direction to STOP
stepper.rotate(2);
rotate1 = true;
}
if (stepper.isDone() && rotate1 == true && rotatedeg == false)
//this is very important and must be placed in your loop, it is this that makes the motor steps
//when necessary
stepper.run();
}

If this is really a Mechanical Engineering thesis I wonder why you did not choose bipolar stepper motors and specialized stepper motor drivers such as a Pololu A4988. Programming would be very much easier. See stepper motor basics.

...R

I completely understand where you are coming from, and believe me I have looked around for months trying to find the right motor with the right characteristics.

The answer to your question comes in two parts; Size restrictions and RPM restrictions. Firstly, the size of my device has to fit within 150mm^3 confines including all mechanical and electrical components. Secondly, the RPM i need is a maximum of 35RPM, to be honest even lower is better, something more like 10-15 is probably ideal. So in order to find a motor that is small, and can deliver an RPM this low with reasonable torque is quite hard to find. I am obviously very open to suggestions but this is my reasoning. Thank you for that link to your document though, i will have a look through this now!

Regards

Taylor_woods:
a BYJ48 stepper motor and ULN2004 motor driver.

What I really want to add is a functionality for the motor to build initially from 7rpm to 35rpm over 5 seconds, displaying this on the lcd.

That's one of those cheap China made toy steppers with a 1:64 tin punched gear to reduce speed into the slow, isn't it?

The loop() function of the posted code looks like a stepper demo and if you didn't do a single thing to achieve what you want.

First thing you'd have to do is thinking about a non-blocking program design that can handle "different tasks at the same time" that strictly avoids every usage of the "delay()" function.

Next perhaps would be creating a formula/function which represents the relation of "rpm" and "step time". So you'd have to know how many steps is one revolution at the gears end. You then can calculate different times between the motor steps instead of a fixed 1000 microseconds like in the stepper demo.

What's your problem?
Programming knowledge of Arduino sketches = zero?

Did you learn some basic programming?
If yes: What computer language? What system?

Yeah it sure is, don't forget this is just a prototype at this stage so the actual mechanical feedback of the system is not of greatest importance. Its more just a proof of concept.

You're on the money with knowledge of sketches = 0. For this project i am going above and beyond what is needed and therefore i need a little assistance with the programming of the system.

Cheers

Taylor_woods:
You're on the money with knowledge of sketches = 0.

That's not good.

If you don't have any other basic programming skills (even not in a different computer language) about variable types, if-conditions, loops, functions, parameters 'by value' and parameters 'by reference', arrays, user defined data structures, string handling and other basic stuff, it's even worse.

On the other side: As the task seems not too complicated while using that China made toy stepper, perhaps something is possible to work out, if you can describe all details.

As far as I have understood, your device has to handle a few tasks at nearly the same time:

  • do potentiometer readings and calculate voltage from that
  • calculate rpm speed and stepper timings
  • do actual motor steps
  • show some visual output

In general you can write one function for each task and do round-robin-scheduling in the loop function, such like:

void loop()
{
  potentiometerTask();
  rpmTask();
  stepperTask();
  visualOutputTask();
}

Write the four functions, ready you are!

Should be all straight forward, perhaps stepper timing is a bit time critical.

Each task must know how often it has to be executed. Perhaps rpm changes 10 times per second, so rpmTask(); should actually run 10 times per second. Visual output on LCD perhaps only needs update 1 or 2 times per second, or the human eye cannot follow any changes. Motor stepper needs perhaps stepping many hundreds of times per second. And the potentiometer? Any thoughts about how many potentiometer readings you want to take? Is 10 readings per second enough?

And what about cycles and repeated actions? Is it a one time action? If you press the "Reset Button" on the Arduino board another cycle starts? Is the whole cycle to be repeated in regularly intervals, let's say once each hour? Or is there any other input signal that should start the cycle?

Yes that is all on point.

With regards to the potentiometer reading, id say thats perfect. If its easier to have less readings per second, then we can do that also.

There are no repeated actions, all that i want to be able to do is activate the whole system with the push of a button, preferably separate to the Arduino, So a 'Normally Open' button attached to an analog input?

Then once the whole cycle is finished you just press the button and the cycle starts again.

Thankyou so much for your help. It is very much appreciated!

Taylor_woods:
I completely understand where you are coming from, and believe me I have looked around for months trying to find the right motor with the right characteristics.

The answer to your question comes in two parts; Size restrictions and RPM restrictions. Firstly, the size of my device has to fit within 150mm^3 confines including all mechanical and electrical components. Secondly, the RPM i need is a maximum of 35RPM, to be honest even lower is better, something more like 10-15 is probably ideal. So in order to find a motor that is small, and can deliver an RPM this low with reasonable torque is quite hard to find. I am obviously very open to suggestions but this is my reasoning. Thank you for that link to your document though, i will have a look through this now!

Regards

HAS to be a gear motor. could be a stepper.
but you will find tiny gear motors, even servos that could work. steppers, not so much.

Taylor_woods:
There are no repeated actions, all that i want to be able to do is activate the whole system with the push of a button, preferably separate to the Arduino, So a 'Normally Open' button attached to an analog input?

Then once the whole cycle is finished you just press the button and the cycle starts again.

So the whole cycle starts each time a button is pressed.
The cycle then will be non-interruptable after it has been started by pressing the button, OK?
After the cycle is finished, the board will sit and wait for the button to be pressed again.

I think I will pull out a BYJ48 from my tinker box and copy together some code.

Any ideas what the displayed output will be when outside a cycle?
The last calculated potentiometer average and some time counting "time since last cycle finished" or so?

Taylor_woods:
There are no repeated actions

This seems to imply that you can write down a description of the problem

step
by
step

with no need for any step to be repeated.

That can only be true (I think) if each motor does its complete movement separately from the movement of every other motor.

It is certainly possible that that is what you need.

You may find some useful ideas in several things at a time and planning and implementing a program.

...R

Taylor_woods:
Secondly, the RPM i need is a maximum of 35RPM, to be honest even lower is better, something more like 10-15 is probably ideal.

Did you already do some speed tests on your BYJ48 stepper motor and ULN2004?

I cannot achieve 35 RPM using mine. That's too fast! Mine must run slower than that.

Maximum speed I can run it is about 22 RPM, but then the motor must run torque-free without pulling any load.

If the motor has to provide some torque, I cannot use more than max. 15 RPM with the tin-geared BYJ48 stepper.

Is that enough?

jurs:
with the tin-geared BYJ48 stepper

Tin is an expensive and soft metal quite unsuited to gears, especially cheap ones.

...R