Pages: [1] 2   Go Down
Author Topic: Using a mapped value which is then ramped analog output  (Read 1123 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am working on a project where I need to adjust a mapped value based on a switch position, but then I would like to ramp the the new analog data when I write it.

An example, lets say we want to make a button output different voltage (serial robot controller). From my knowledge it will look something like this:

Code:
if( adjenpos == 1) {
boostbtnout = map(boostbtnin, 0, 1023, 0, 51);
}
else if( adjenpos == 2) {
boostbtnout = map(boostbtnin, 0, 1023, 0, 102);
}
else if( adjenpos == 3) {
boostbtnout = map(boostbtnin, 0, 1023, 0, 153);
}
else if( adjenpos == 4) {
boostbtnout = map(boostbtnin, 0, 1023, 0, 204);
}
else if( adjenpos == 5) {
boostbtnout = map(boostbtnin, 0, 1023, 0, 255);
}
Now with option 3, taking a button which has an on/off value of 0 or 153, I want to ramp the value 0 to 153 over a prescribed rate, instead of just on or off.

My assumption is to do something similar to this inside the loop:

Code:
boostramp = 1
boostbtnvalue = analogRead(boostbtnout)
 analogWrite(boostbtn, boostbtnvalue);
 if ( boostpwr <= boostbtnout){
 boostpwr = boostpwr + boostramp;
I know this is not correct, but how do I inject the new mapped values into a rampped type of function?

Thanks!
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're using a lot of words like "inject" and "ramp" which don't make a lot of sense, so let's try to be clear: the map function takes several arguments, does some math, and returns a value.

Second, you're saying you want to make a button output a voltage, which doesn't make sense either -- buttons are inputs.

So what I think you mean:
You want to make a project that reads a button and outputs a voltage if the button is pressed (if it's not pressed, output 0 volts). The voltage depends on how long the button has been pressed; increasing as it has been held longer.

If that's so, you'll want to make it so that when the button was not pressed last time but was pressed this time, it resets a clock (or sets a variable to now). Then you want to map the elapsed time (now - the stored time) into a voltage that you feed to analogWrite.

now can be figured out using the millis() command. You can use a variable declared as static to keep a variable (such as the time when the button was first pressed) between iterations of a loop. The rest I think you know how to do.
Logged

Indiana, US
Offline Offline
Full Member
***
Karma: 12
Posts: 204
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi squd08,

It's hard to tell what you are trying to do from the code snippets you've included.  You really should comment your code and explain what the variables mean.

May I suggest you replace the cascading if, else-if statements with a simple switch statement?  

Code:
switch (adjenpos)
{
    case 1:  boostbtnout = map(boostbtnin, 0, 1023, 0, 51);  break;
    case 2:  boostbtnout = map(boostbtnin, 0, 1023, 0, 102);  break;
    Etc...
}

Or, even simpler, create an array of upper values that you index with adjenpos?

Code:
int switch_pos []= {51, 102, etc...};

...

boostbtnout = map(boostbtnin, 0, 1023, 0, switch_pos[adjenpos]);

// pardon my code if it doesn't compile, it's late for me and I'm a bit groggy :-/

I assume that what you are really wanting is a smooth transition between the current value and the new value based on switch position.  You should store the current value in a variable and loop to the desired value (which may be up or down from it!).  Use delays to ensure the transition is according to your 'prescribed' rate.
Logged

There are 10 types of people in the world, those that understand binary, and those that don't.

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're using a lot of words like "inject" and "ramp" which don't make a lot of sense, so let's try to be clear: the map function takes several arguments, does some math, and returns a value.

Second, you're saying you want to make a button output a voltage, which doesn't make sense either -- buttons are inputs.

So what I think you mean:
You want to make a project that reads a button and outputs a voltage if the button is pressed (if it's not pressed, output 0 volts). The voltage depends on how long the button has been pressed; increasing as it has been held longer.

If that's so, you'll want to make it so that when the button was not pressed last time but was pressed this time, it resets a clock (or sets a variable to now). Then you want to map the elapsed time (now - the stored time) into a voltage that you feed to analogWrite.

now can be figured out using the millis() command. You can use a variable declared as static to keep a variable (such as the time when the button was first pressed) between iterations of a loop. The rest I think you know how to do.

Sorry, it's hard to type as it makes sense in my head  smiley-lol
Ultimately I am sending signals to a robot controller and using a on/off switch to control a motor. I am using the adjustable map values to vary my maximum power and the "ramp" to have a smooth motor application. I know it sounds like a complicated effort, but its all for good reason.

so to sum up,
I want to make a project which reads a button digitally, and outputs a "progressive" voltage.
In order to output to analog we have to map it, so a button LOW = 0 HIGH = 255 (or whatever number I choose)
But instead of it being just 0 or 255, I would like it to climb from 0 to 255 over a set period of time or loops. You could call it ramp, fade, etc.

Is this any clearer? Sorry for the confusion.


Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi squd08,

It's hard to tell what you are trying to do from the code snippets you've included.  You really should comment your code and explain what the variables mean.

May I suggest you replace the cascading if, else-if statements with a simple switch statement?  

Code:
switch (adjenpos)
{
    case 1:  boostbtnout = map(boostbtnin, 0, 1023, 0, 51);  break;
    case 2:  boostbtnout = map(boostbtnin, 0, 1023, 0, 102);  break;
    Etc...
}

Or, even simpler, create an array of upper values that you index with adjenpos?

Code:
int switch_pos []= {51, 102, etc...};

...

boostbtnout = map(boostbtnin, 0, 1023, 0, switch_pos[adjenpos]);

// pardon my code if it doesn't compile, it's late for me and I'm a bit groggy :-/

I assume that what you are really wanting is a smooth transition between the current value and the new value based on switch position.  You should store the current value in a variable and loop to the desired value (which may be up or down from it!).  Use delays to ensure the transition is according to your 'prescribed' rate.


Thanks Pat!  I hope my last comment helps clear up any confusion.

I am a basic arduino user, but I like your suggestions on the if statements. I will revisit when I have a direction for my main issue. I appreciate it!
Logged

Indiana, US
Offline Offline
Full Member
***
Karma: 12
Posts: 204
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, things are getting clearer for me.

When you say you want to adjust the voltage to the motor, you really mean that you want to adjust the PWM values, right?  You can't actually change the voltage levels out of the Arduino.

Are you controlling 1 motor or several?  If several, are you controlling one at a time, or do you want the motors to ramp to their new speeds at the same time?
Logged

There are 10 types of people in the world, those that understand binary, and those that don't.

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're using a lot of words like "inject" and "ramp" which don't make a lot of sense, so let's try to be clear: the map function takes several arguments, does some math, and returns a value.

Second, you're saying you want to make a button output a voltage, which doesn't make sense either -- buttons are inputs.

So what I think you mean:
You want to make a project that reads a button and outputs a voltage if the button is pressed (if it's not pressed, output 0 volts). The voltage depends on how long the button has been pressed; increasing as it has been held longer.

If that's so, you'll want to make it so that when the button was not pressed last time but was pressed this time, it resets a clock (or sets a variable to now). Then you want to map the elapsed time (now - the stored time) into a voltage that you feed to analogWrite.

now can be figured out using the millis() command. You can use a variable declared as static to keep a variable (such as the time when the button was first pressed) between iterations of a loop. The rest I think you know how to do.

Sorry, it's hard to type as it makes sense in my head  smiley-lol
Ultimately I am sending signals to a robot controller and using a on/off switch to control a motor. I am using the adjustable map values to vary my maximum power and the "ramp" to have a smooth motor application. I know it sounds like a complicated effort, but its all for good reason.

so to sum up,
I want to make a project which reads a button digitally, and outputs a "progressive" voltage.
In order to output to analog we have to map it, so a button LOW = 0 HIGH = 255 (or whatever number I choose)
But instead of it being just 0 or 255, I would like it to climb from 0 to 255 over a set period of time or loops. You could call it ramp, fade, etc.

Is this any clearer? Sorry for the confusion.

That's about what I guessed. Try implementing what I described in the last two paragraphs of my post and come back with questions about how to do so
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


I have just learned that I can send a serial command to the robot controller to adjust the top power limit on the robot controller. This something which I did not think was possible without a reset.

That being said, the process is still the same, but I can essentially remove the "IF map statements

Yes, things are getting clearer for me.

When you say you want to adjust the voltage to the motor, you really mean that you want to adjust the PWM values, right?  You can't actually change the voltage levels out of the Arduino.

Are you controlling 1 motor or several?  If several, are you controlling one at a time, or do you want the motors to ramp to their new speeds at the same time?

Yes, adjust pwm. So instead of a pwm output of 0 or 255, its 0 to 255 over a set period of time. Just one motor.

Thanks!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're using a lot of words like "inject" and "ramp" which don't make a lot of sense, so let's try to be clear: the map function takes several arguments, does some math, and returns a value.

Second, you're saying you want to make a button output a voltage, which doesn't make sense either -- buttons are inputs.

So what I think you mean:
You want to make a project that reads a button and outputs a voltage if the button is pressed (if it's not pressed, output 0 volts). The voltage depends on how long the button has been pressed; increasing as it has been held longer.

If that's so, you'll want to make it so that when the button was not pressed last time but was pressed this time, it resets a clock (or sets a variable to now). Then you want to map the elapsed time (now - the stored time) into a voltage that you feed to analogWrite.

now can be figured out using the millis() command. You can use a variable declared as static to keep a variable (such as the time when the button was first pressed) between iterations of a loop. The rest I think you know how to do.

Sorry, it's hard to type as it makes sense in my head  smiley-lol
Ultimately I am sending signals to a robot controller and using a on/off switch to control a motor. I am using the adjustable map values to vary my maximum power and the "ramp" to have a smooth motor application. I know it sounds like a complicated effort, but its all for good reason.

so to sum up,
I want to make a project which reads a button digitally, and outputs a "progressive" voltage.
In order to output to analog we have to map it, so a button LOW = 0 HIGH = 255 (or whatever number I choose)
But instead of it being just 0 or 255, I would like it to climb from 0 to 255 over a set period of time or loops. You could call it ramp, fade, etc.

Is this any clearer? Sorry for the confusion.

That's about what I guessed. Try implementing what I described in the last two paragraphs of my post and come back with questions about how to do so

Yes your right. I realize now this morning that your approach is applicable. Is it more efficient to do it with a for loop count since we are talking about a 0.1 to 1 second "ramp" , or is still best to do as you suggest and use the internal clock? 
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


That's about what I guessed. Try implementing what I described in the last two paragraphs of my post and come back with questions about how to do so

This is my first attempt at the code.
How does it look?

Code:
void loop () {

if (button == HIGH && time <= millis() ){

int time = millis();

}

else if (button == HIGH && time > millis() ){

int buttontime = millis()-time;

ramp = map(buttontime, time, 1000, 0, 255);  // after 1 second give full pwm output

}

else if (button == LOW) {

time = 0;

}
Logged

California
Offline Offline
Faraday Member
**
Karma: 91
Posts: 3426
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How does it look?
Not indented.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


?
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


That's about what I guessed. Try implementing what I described in the last two paragraphs of my post and come back with questions about how to do so

This is my first attempt at the code.
How does it look?
That looks really good! Just a few tips and it should work great. I modified it a little
Code:
void loop () {
  static unsigned long startButtonPressTime;
  static byte lastButtonState = LOW;
  int pwr;
  byte buttonState = digitalRead(button);

  if (buttonState == HIGH) {
    if (lastButtonState = LOW) {
      startButtonPressTime = millis();
    }
    else {
      pwr = map(millis() - startButtonPressTime, 0, 1000, 0, 255);  // after 1 second give full pwm output
    }
  }
  analogWrite(3, pwr);

  lastButtonState = buttonState;
}
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


'Indenting' refers to laying out your code so that the structure can be seen and understood. It doesn't affect the logic, but does affect how easy it is for the programmer to understand the logic. The code you posted wasn't indented and as a result is very hard to follow. The Arduino IDE includes tools to indent your code for you.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


That's about what I guessed. Try implementing what I described in the last two paragraphs of my post and come back with questions about how to do so

This is my first attempt at the code.
How does it look?
That looks really good! Just a few tips and it should work great. I modified it a little
Code:
void loop () {
  static unsigned long startButtonPressTime;
  static byte lastButtonState = LOW;
  int pwr;
  byte buttonState = digitalRead(button);

  if (buttonState == HIGH) {
    if (lastButtonState = LOW) {
      startButtonPressTime = millis();
    }
    else {
      pwr = map(millis() - startButtonPressTime, 0, 1000, 0, 255);  // after 1 second give full pwm output
    }
  }
  analogWrite(3, pwr);

  lastButtonState = buttonState;
}

Thanks! I'm happy to have solved it mostly myself.

Can you explain the purpose of byte and unsigned long?
Logged

Pages: [1] 2   Go Up
Jump to: