set PWM profile for motor speed control

Hi all,
I am using an Arduino Mega to control a Variable Frequency drive that drives a motor. The VFD accepts a 0-10V PWM signal to run the motor between 0 and 60Hz. I build a circuit to make a 0-10V PWM out of the 10V output voltage of the VFD, controlled by the Arduino PWM. Here’s the code I have so far:

void setup()
{
//initialize all timers except for 0, to save time keeping functions
// InitTimersSafe();


//if the pin frequency was set successfully, turn pin 13 on
pinMode(3, OUTPUT);
// digitalWrite(3, HIGH);
}
void loop()
{
//use this functions instead of analogWrite on ‘initialized’ pins
setSpeed(50);


delay(30);
}
void setSpeed(int freq)
{
float output = -5*freq+255;
if(output > 255)
output = 255;
else if(output < 0)
output = 0;
analogWrite(3, output);
}

So, I need to run the attached profile with it. What’s the easiest way to set a profile on the arduino? I couldn’t find anything in the whole WWW.

Profile ? please explain.
A profile for a certain rpm by a certain voltage.
Or a profile for a certain smooth change in rpm at a certain time.

You want to put the points in from the graph and get a function that gives you the line?

Hz = F(seconds);

Kind of thing?

-jim lee

Like this for example?

Mapping i : 0 value : 0.00
Mapping i : 1 value : 4.28
Mapping i : 2 value : 8.57
Mapping i : 3 value : 12.85
Mapping i : 4 value : 17.14
Mapping i : 5 value : 21.42
Mapping i : 6 value : 25.70
Mapping i : 7 value : 26.30
Mapping i : 8 value : 26.90
Mapping i : 9 value : 27.50
Mapping i : 10 value : 28.09
Mapping i : 11 value : 28.69
Mapping i : 12 value : 29.29
Mapping i : 13 value : 29.88
Mapping i : 14 value : 30.48
Mapping i : 15 value : 31.08
Mapping i : 16 value : 31.67
Mapping i : 17 value : 32.27
Mapping i : 18 value : 32.87
Mapping i : 19 value : 33.47
Mapping i : 20 value : 34.06
Mapping i : 21 value : 34.66
Mapping i : 22 value : 35.26
Mapping i : 23 value : 35.85
Mapping i : 24 value : 36.45
Mapping i : 25 value : 37.05
Mapping i : 26 value : 37.64
Mapping i : 27 value : 38.24
Mapping i : 28 value : 38.84
Mapping i : 29 value : 39.44
Mapping i : 30 value : 40.03
Mapping i : 31 value : 40.63
Mapping i : 32 value : 41.23
Mapping i : 33 value : 41.82
Mapping i : 34 value : 42.42
Mapping i : 35 value : 43.02
Mapping i : 36 value : 43.61
Mapping i : 37 value : 44.21
Mapping i : 38 value : 44.81
Mapping i : 39 value : 45.41
Mapping i : 40 value : 46.00
Mapping i : 41 value : 46.60
Mapping i : 42 value : 47.20
Mapping i : 43 value : 47.79
Mapping i : 44 value : 48.39
Mapping i : 45 value : 48.99
Mapping i : 46 value : 49.58
Mapping i : 47 value : 50.18
Mapping i : 48 value : 50.78
Mapping i : 49 value : 51.38
Mapping i : 50 value : 47.95
Mapping i : 51 value : 44.52
Mapping i : 52 value : 41.10
Mapping i : 53 value : 37.68
Mapping i : 54 value : 34.25
Mapping i : 55 value : 30.82
Mapping i : 56 value : 27.40
Mapping i : 57 value : 23.98
Mapping i : 58 value : 20.55
Mapping i : 59 value : 17.12
Mapping i : 60 value : 13.70
Mapping i : 61 value : 10.27
Mapping i : 62 value : 6.85
Mapping i : 63 value : 3.43
Mapping i : 64 value : 0.00
Mapping i : 65 value : 0.00
Mapping i : 66 value : 0.00
Mapping i : 67 value : 0.00

-jim lee

yeah, that looks right. So, I just need a function that sets it to the output now.

Well I can help with generating the output from a set of points, I'm thinking someone else will have to help you on the actual output bit.

-jim lee

The multimap is simple : http://playground.arduino.cc/Main/MultiMap
It interpolates between the points.

If you want a certain mathematical curve, you should first know what kind of curve. Some go through all the points and others don’t. But for now I suggest to start with the multimap.

So thanks for the answers so far. I tried some stuff and the following version works best so far:

 unsigned long currentMillis = millis();  
  
   
    if((currentMillis - previousMillis) < 6000) {
      setSpeed(4.28*(currentMillis - previousMillis)/1000);
    }
    
    if((currentMillis - previousMillis) > 6000 && (currentMillis - previousMillis) < 49000) {
      setSpeed(0.597*((currentMillis - previousMillis)-6000)/1000+25.7);
    }
    
  
    if((currentMillis - previousMillis) > 49000 && (currentMillis - previousMillis) < 64000) {
      setSpeed(-3.425*((currentMillis - previousMillis)-49000)/1000+51.375);
    }
    
    if((currentMillis - previousMillis) > 64000 && (currentMillis - previousMillis) < 67000) {
      setSpeed(0);
    }
    
  
    if((currentMillis - previousMillis) >= 67000) {// reset the timer and start again
      previousMillis = currentMillis; 
      cycles++;
    }

The problem is, that the rest of my code is very complex. I’ll attach it at the end of my post. My Arduino Mega has to deal with eight flow sensors, three thermocouples and a relay. I am not sure if I can use an interrupt for the speed control. Running it without an interrupt, the speedcontrol gives out setpoints not fast enough. Running just the speedcontrol skript is not smooth too, but acceptable.
What is your advice?

Here the full code

octopumper_compare_flow_profile_voltage.ino (22.5 KB)

That is linear interpolation ?
Those values should be in an array. And the multimap can get the value out of the array with linear interpolation.

Yes it is. I read the multimap explanation twice now, but it's hard for me to use it for my problem. All the examples use an analog input as one array. But I need a timer for that. Anyone has experiences with such a problem?

At the bottom is a FmultiMap for floats.
You could rewrite the ‘in’ array for unsigned long, or set the time in seconds in float, and convert the milliseconds to seconds in your sketch.
float t = (float) millis() / 1000.0;