Smooth transition between new and old value.

Hi guys, I need your help! I’m making a art project with some leds and motors. The leds and motors behave in a sinus-like way. Sensor inputs from a sonar and a microphone change the properties of this behaviour, namely the period and the colour. Sometimes people move away from the sonar and the period changes much (few seconds), because of this the motors and leds don’t react smoothly to the change. Is there some way of letting te old value of the period smoothly transition into the new value, this would make it look way nicer. This part of the code is important for the period:

NewDistance = sonar.ping_result / US_ROUNDTRIP_CM;
DistanceDifference = abs(NewDistance - OldDistance);
 
if (DistanceDifference >= 2) {
if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
if (DistanceDifference >= 2) {
OldDistance = NewDistance;
if (sonar.ping_result / US_ROUNDTRIP_CM < 300){
  Period = 0.50000 + 3.50000 * ((sonar.ping_result / US_ROUNDTRIP_CM)/ 300.0000); 
  } 
else { 
Period = 4.00000;  
} } } }

Thanks!

Actually I think that the complete code is relevant.

sterretje: Actually I think that the complete code is relevant.

How can I do that when it's over 9000 characters ?

Attach it, see attachments and other options when you reply.

To output a value that transitions between “old” and “new” in steps, something like this will work:

  float old = (something);
  float new = (something else);
  float delta = (new - old)/intervals;
  for (int x=0; x<intervals; x++) {
  output = old + x*delta;
  delay(somemillis);  //note that using delay() is frowned upon
 }

Oke here is the code, I don’t have the microphone implemented yet

DVD_ResponsiveV1d.ino (41.5 KB)

jremington:
To output a value that transitions between “old” and “new” in steps, something like this will work:

  float old = (something);

float new = (something else);
 float delta = (new - old)/intervals;
 for (int x=0; x<intervals; x++) {
 output = old + x*delta;
 delay(somemillis);  //note that using delay() is frowned upon
}

Thanks for the response, I will try to implement it (without delays tho)

if (DistanceDifference >= 2) {
if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
if (DistanceDifference >= 2) {

Your code would be a lot easier to read if you put EVERY { on a line BY ITSELF and properly indented the code.

if (DistanceDifference >= 2)
{
   if (currentMillis - previousMillis >= interval)
   {
      previousMillis = currentMillis;
      if (DistanceDifference >= 2) 
      {

Now, perhaps you can explain why the last if statement in that snippet is necessary. The value in DistanceDifference can not change between the first test and the last test. The last text will only be performed, uselessly, if the first one succeeded.

PaulS:
Now, perhaps you can explain why the last if statement in that snippet is necessary. The value in DistanceDifference can not change between the first test and the last test. The last text will only be performed, uselessly, if the first one succeeded.

Thanks for your response!
You are right, it is useless, so I changed it.
I now have got this code: (also other changes besides that snippet)

// Period ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

NewDistance = sonar.ping_result / US_ROUNDTRIP_CM;
DistanceDifference = abs(NewDistance - OldDistance);
 
if (DistanceDifference > 2) 
{
  if (currentMillis - previousMillis >= interval) 
  {
    previousMillis = currentMillis;
    OldDistance = NewDistance;
    
    if (sonar.ping_result / US_ROUNDTRIP_CM < 300)
    {
      NewPeriod = 0.50000 + 3.50000 * ((sonar.ping_result / US_ROUNDTRIP_CM)/ 300.0000); 
      } 
    else { 
      NewPeriod = 4.00000;  
     } 
   }
 }


while(Period != NewPeriod) 
{
  
  DeltaPeriodChange = (NewPeriod - OldPeriod)/ StappenPeriodChange;
  
  if (currentMillis2 - previousMillis2 >= StapLengtePeriodChange)
  {
    previousMillis2 = currentMillis2;  
    
    for (int x=0; x < StappenPeriodChange; x++) 
    {
      Period = OldPeriod + x * DeltaPeriodChange;
    }
   
  if (x == StappenPeriodChange)
  {
    OldPeriod = Period;
    x = 0;
    }
    
  }
  
}

 
Serial.print("X-overgang: ");
Serial.println(x);

Serial.print ("Period: ");
Serial.print (Period);
Serial.println ("sec");

But sadly it doesn’t work…
The x stays 0 for some reason and I don’t know why, I haven’t worked a lot with increments yet.
Het is a part of the serial prints:

Ping: 125cm
X-overgang: 0
Period: 4.00sec
Ping: 127cm
X-overgang: 0
Period: 4.00sec
Ping: 124cm
X-overgang: 0
Period: 4.00sec
Ping: 124cm
X-overgang: 0
Period: 4.00sec
Ping: 127cm
X-overgang: 0
Period: 4.00sec
Ping: 129cm
X-overgang: 0
Period: 4.00sec
Ping: 114cm
X-overgang: 0
Period: 4.00sec

I hope that somebody knows what’s wrong :slight_smile:

The x stays 0 for some reason and I don't know why

We don't either, because some of the problems are in the code you failed to post.

jremington:
We don’t either, because some of the problems are in the code you failed to post.

Sorry, see the attachment for the full code.

DVD_ResponsiveV2.ino (44.6 KB)

Ok the application of the code may seem strange, so here is short video to demonstrate what it does.

https://imgur.com/a/pVrLK

So the problem now is that when the period changes this nice movement (as seen in the video) shutters, thats why I wanted to change the value of the period smoothly.

This code:

  DeltaPeriodChange = (NewPeriod - OldPeriod)/ StappenPeriodChange;
  ...

    for (int x=0; x < StappenPeriodChange; x++) 
    {
      Period = OldPeriod + x * DeltaPeriodChange;
     
     if (x == StappenPeriodChange - 1)
     {
    OldPeriod = Period;
    x = 0;
    }

will have exactly the same result as the following:

   Period = NewPeriod;
   OldPeriod = Period;
   x=0;

You have to do something with Period inside the for loop, in order to see its effects.

What is your thinking here?

jremington:
You have to do something with Period inside the for loop, in order to see its effects.

What is your thinking here?

Im trying to change the period of the DVD’s and Leds (See video and full code). So for example the “Period” is used here:

  //DVD5
  KaasSpeedDVD5 = 110 * cos( ((2.00000 * pi)/ Period)  *  (time / 1000000.0000 - ((5.00000 * Period) / 9.00000)));
  if (KaasSpeedDVD5 > 0) {
  motorDirectionDVD5 = 1;
  motorSpeedDVD5 = KaasSpeedDVD5 + 145; 
  }
  if (KaasSpeedDVD5 < 0) {
  motorDirectionDVD5 = 0;
  motorSpeedDVD5 = -1 * KaasSpeedDVD5 + 145;
  }
  if (motorDirectionDVD5 == 1) {
    digitalWrite(DVD5controlPin1, HIGH);
    digitalWrite(DVD5controlPin2, LOW);
  } else {
    digitalWrite(DVD5controlPin1, LOW);
    digitalWrite(DVD5controlPin2, HIGH);
  }
  if (motorEnabled == 1) {
    analogWrite(DVD5enablePin, motorSpeedDVD5);
  } else { 
    analogWrite(DVD5enablePin, 0);
  }

Sometimes the value of the period changes too much and this results in a shudder of the movement. So to make the process of this period change smoother, the Period changes from the OldPeriod to the NewPeriod in steps.
(This part)

  DeltaPeriodChange = (NewPeriod - OldPeriod)/ StappenPeriodChange;
  ...

    for (int x=0; x < StappenPeriodChange; x++) 
    {
      Period = OldPeriod + x * DeltaPeriodChange;
     
     if (x == StappenPeriodChange - 1)
     {
    OldPeriod = Period;
    x = 0;
    }

Well this is the idea, it’s not working yet.

You really need to factor your code using arrays. The result will be at least 10 times shorter and 100 times easier to maintain.

aarg: You really need to factor your code using arrays. The result will be at least 10 times shorter and 100 times easier to maintain.

Very true, I tried it, but I couldn't really figure out how, since they all are a bit different from each other. I have got a deadline for this project, so I did what I was able to do to finish it. Those parts of the code aren't great, but they do their job.

LuckyBuck: Very true, I tried it, but I couldn't really figure out how, since they all are a bit different from each other. I have got a deadline for this project, so I did what I was able to do to finish it. Those parts of the code aren't great, but they do their job.

Great that the program works. I guess we can all move on now.

aarg: Great that the program works. I guess we can all move on now.

No sorry, I think you misunderstood me. Those really long parts that should be done with arrays, which you were talking about, work. But not the smooth Period change part of the code. Which this topix is really about.

aarg: You really need to factor your code using arrays. The result will be at least 10 times shorter and 100 times easier to maintain.

Wow, the author has a shit-ton of patience to program like he/her has done.

(If you ever need to make an argument for Object Oriented programming, just point someone to this post.)

@LuckyBuck, it seems that you've quite lovingly put together a piece of code that is close to doing what you want... I applaud your brute-force approach, but you may want to take some time and learn OO programming.

I know when you get close to the finish line it seems a lot of work to "Start Over" in comparison, but if you ever want to do more with Arduino, it is worth learning. It may actually get you to completion on this project faster!

Stuttering in timing is usually caused by either hidden delays, or quantization in the variables that control it.