Help With For Loops

I am very new to Arduino, and programming in general. First year electrical engineering student trying to get ahead of my class.

I am trying to incrementally speed up an electric motor then slow it down while having six leds indicate the speed. When the motor is stopped, zero leds are on; motor speed reaches stage one, led one comes on; stage two, leds one and two are both on; .... ; when it is at full speed (stage 6), all six leds are.

Here's the mess I came up with after researching/working for several hours. It works the way I want it to but I feel like I am missing something that would make this easier. Please excuse the noobishness. :blush:

//Define Pins
int motorPin = 3;
int ledPin1 = 12;
int ledPin2 = 11;
int ledPin3 = 10;
int ledPin4 = 9;
int ledPin5 = 8;
int ledPin6 = 7;

void setup()
{
 pinMode (motorPin, OUTPUT);
 pinMode (ledPin1, OUTPUT);
 pinMode (ledPin2, OUTPUT);
 pinMode (ledPin3, OUTPUT);
 pinMode (ledPin4, OUTPUT);
 pinMode (ledPin5, OUTPUT);
 pinMode (ledPin6, OUTPUT);
 
 }

void loop()
{
 //Stage 1
 for (int i=120; i<=140; i++)
 {
  analogWrite(motorPin, i);
  digitalWrite(ledPin1, HIGH);
  delay(100);
 }
 //Stage 2
 for (int i=140; i<=160; i++)
 {
   analogWrite(motorPin, i);
   digitalWrite(ledPin2, HIGH);
   delay(100);
 }
  //Stage 3
 for (int i=160; i<=180; i++)
 {
  analogWrite(motorPin, i);
  digitalWrite(ledPin3, HIGH);
  delay(100);
 }
  //Stage 4
  for (int i=180; i<=200; i++)
  {
    analogWrite(motorPin, i);
    digitalWrite(ledPin4, HIGH);
    delay(100);
  }
   //Stage 5
   for (int i=200; i<=220; i++)
   {
     analogWrite(motorPin, i);
     digitalWrite(ledPin5, HIGH);
     delay(100);
   }
   //Stage 6
   for (int i=240; i<=255; i++)
   {
     analogWrite(motorPin, i);
     digitalWrite(ledPin6, HIGH);
     //Hold at Max Speed
     delay(300);
   }

 //Decrese
 for (int i=255; i>=240; i--)
 {
  analogWrite(motorPin, i);
  digitalWrite(ledPin6, LOW);
 delay(100);
 }
 //Decrease to Stage 5
 for (int i=240; i>=220; i--)
 {
  analogWrite(motorPin, i);
  digitalWrite(ledPin5, LOW);
 delay(100);
 }
 //Decrease to Stage 4
 for (int i=220; i>=200; i--)
 {
  analogWrite(motorPin, i);
  digitalWrite(ledPin4, LOW);
 delay(100);
 }
  //Decrease to Stage 3
 for (int i=200; i>=180; i--)
 {
  analogWrite(motorPin, i);
  digitalWrite(ledPin3, LOW);
 delay(100);
 }
   //Decrease to Stage 2
 for (int i=180; i>=160; i--)
 {
  analogWrite(motorPin, i);
  digitalWrite(ledPin2, LOW);
 delay(100);
 }
 //Decrease to Stage 1
 for (int i=160; i>=120; i--)
 {
  analogWrite(motorPin, i);
  digitalWrite(ledPin2, LOW);
 delay(50);
 }
 digitalWrite(ledPin1, LOW);
 delay(500);
}

One thing that would make it neater straight away would be to write a function to do the increments then call it when required.

void speedUp(int start, int end, int ledPin)
{
  for (int i = start; i <= end; i++)
  {
    analogWrite(motorPin, i);
    digitalWrite(ledPin, HIGH);
    delay(100);
  }
}

Then call it like this

speedUp(120, 140, ledPin1)
speedUp(140, 160, ledPin2)

A second improvement would be to use arrays to hold values and to cycle through them using a for loop but get the function working first.

You could make the thing data-driven (always a thing to do where feasible).

Here that means putting the pin numbers and start and finish analogWrite values
into arrays, such as:

int led_pins [] = { 12, 11, 10, 9, 8, 7 } ;
int low_val [] = { 120, 140, 160, 180, 200, 240 } ;
int high_val [] = { 140, 160, 180, 200, 240, 255 } ;

Then the speed up and slow down loop can index those arrays at each stage:

  for (int i = 0 ; i < 6 ; i++)
  {
    digitalWrite (led_pins [i], HIGH) ;
    for (int val = low_val [i] ; val < high_val [i] ; i++)
    {
      analogWrite (motorPin, val) ;
      delay (100) ;
    }
  }

Slowing down would use a for loop like this:

  for (int i = 5 ; i >= 0 ; i--)

[ thus stepping through the arrays in the other direction ]

This scheme can be tinkered with and improved - low_val and high_val can
be a single array, but with 7 entries, consecutive entries being used for the
two end points for one segment.

You could make an array of delays so that different segments can go at different
rates, etc.

Wow! That is a ton shorter/neater. Thanks so much!

Here's what I came up with

int ledPins [] = { 12, 11, 10, 9, 8, 7 };
int lowVal [] = { 120, 140, 160, 180, 200, 255 };
int highVal [] = { 120, 140, 160, 180, 200, 255};
int motorPin = 3;

void setup()
{
  pinMode(motorPin, OUTPUT);
  
  for (int b = 7; b < 13; b++)
  {
    pinMode(ledPins [b], OUTPUT);
  }
}

void loop()
{
  for (int i = 0; i < 6; i++)
  {
    digitalWrite (ledPins [i], HIGH);
    for (int val = lowVal [i] ; val < highVal [i] ; i++)
    {
      analogWrite (motorPin, val);
      delay(100);
    }
  }
  for (int i = 6; i >= 0; i--)
  {
    digitalWrite (ledPins [i], LOW);
    for (int val = highVal [i] ; val < lowVal[i] ; i--)
    {
      analogWrite (motorPin, val) ;
      delay(100);
    }
  }
}

UKHeliBob and MarkT: an excellent example of helping someone discover a better solution.

Spilly: Great job in learning from your mentors...well done!

for (int b = 7; b < 13; b++)
  {
    pinMode(ledPins [b], OUTPUT);

BZZZZT.
No, sorry.
Look again.

AWOL:

for (int b = 7; b < 13; b++)

{
    pinMode(ledPins [b], OUTPUT);



BZZZZT.
No, sorry.
Look again.

I apologize if I'm missing something obvious but I don't follow? Is it not needed or is something incorrect.

I was attempting to use a for loop to initialize pins 7-12 as outputs.

Look at the index to the array, and the size of the array.

facepalm OHHHHH!!!!!

  for (int b = 1; b < 7; b++)
  {
    pinMode(ledPins [b], OUTPUT);
  }

Let's try that again...

  for (int b = 0; b < 6; b++)
  {
    pinMode(ledPins [b], OUTPUT);
  }

More generally

for (int b = 0; b < sizeof(ledPins) / sizeof(ledPins[0]); b++)
  {
    pinMode(ledPins [b], OUTPUT);
  }
int ledPins [] = { 12, 11, 10, 9, 8, 7 };
int lowVal [] = { 120, 140, 160, 180, 200, 255 };
int highVal [] = { 120, 140, 160, 180, 200, 255};
int motorPin = 3;
  for (int b = 7; b < 13; b++)
  for (int i = 0; i < 6; i++)
     for (int val = lowVal [i] ; val < highVal [i] ; i++)
  for (int i = 6; i >= 0; i--)
    for (int val = highVal [i] ; val < lowVal[i] ; i--)

How many of these variables NEED to be int?

I don't understand what you are doing with the nested for loops. It is unusual, to say the least, to diddle with the outer loop index in the inner loop. It looks to me like both of the nested for loops should have val++, not i++, as the last clause. (Or -- as appropriate).

Not sure what you mean by "what NEEDS to be an int". Forgive my tiny vocabulary in this language. I just want to have close to the same end result with the least amount of code and/or in the neatest way possible.

Due to something I am not comprehending, the motor is stopping (audible change) if I do not add a 7th (1-7) integer to the motor speeds. However, the led section seems to be working correctly with just 6 integers.

Here's what I'm using right now.

//Define Pins
int ledPins [] = { 12, 11, 10, 9, 8, 7 };
int upmotorSpeed [] = { 120, 150, 170, 190, 220, 255, 255};
int downmotorSpeed [] = { 100, 130, 150, 175, 200, 230, 255};
int motorPin = 3;

void setup()
//Assign Pin I/O
{
  pinMode(motorPin, OUTPUT);
  
  for (int b = 0; b < 6; b++)
  {
    pinMode(ledPins[b], OUTPUT);
  }
}

void loop()
{
  //Increase Motor Speed In Six Steps.
  //LEDs Light to Indicate "Step"
  for (int i = 0; i <=5; i++)
  {
    digitalWrite (ledPins [i], HIGH);
    analogWrite (motorPin, upmotorSpeed [i]);
    delay(1000);
  }
  
  //Decrease Motor Speed In Six Steps.
  //LEDs Light to Indicate "Step"
  for (int i = 5; i >= 0; i--)
  {
    digitalWrite (ledPins [i], LOW);
    analogWrite (motorPin, downmotorSpeed [i]) ;
    delay(1000);
  }
}
int ledPins [] = { 12, 11, 10, 9, 8, 7 };
int lowVal [] = { 120, 140, 160, 180, 200, 255 };
int highVal [] = { 120, 140, 160, 180, 200, 255};

They don't need to be "int"s.
Make them "byte"s and you'll halve your RAM usage for these structures.

Due to something I am not comprehending, the motor is stopping (audible change) if I do not add a 7th (1-7) integer to the motor speeds.

I can't see any reason for that behavior, either. But, then, I can't see or hear where your motor stops. Some Serial.print() statements would be good. Print i on each pass through each loop. Print the appropriate motor speed in each loop. Print a message before and after each loop.

When does the motor stop, and what kind of sounds does it make? Are you simply using a PWM value that is too low for the motor?