Multiple potentiometers and code

Evening all, beginner here. I followed a ocean wave model by a YouTube poster, who controls amplitude, frequency and pattern of the wave through three potentiometers, linked to a singular servo. I am struggling to source/generate a code which enables this to happen? Could any kind people provide a solution for this in terms of code please?

Thanks in advance!

Link to the YouTube video ?

@UKHeliBob no problem, here you go:

Actually, you supply the code and we can help when you encounter problems.
Your first task, before any code, is to determine the values of the three potentiometers you will be using. Then determine the servo you will be using.
All of the above is necessary BEFORE any code can be developed because you do not know what code will be necessary until then.
Paul

The only part not sufficiently described in the video is how the third knob controls the 'pattern' of the waves.

I would use four or six pots giving frequency and magnitude control over two or three separate waves. Turn the magnitude down to 0 for the waves you aren't using.

What range of frequencies would you like?

@Paul_KD7HB Hi Paul, this is the code I had prior. The 3 values are wavelength (the horizontal distance between two crests or two troughs), amplitude (the vertical distance between trough and crest), and velocity (the speed at which wave crests move across the water). The Units of measurement for each is meters for wavelength and amplitude and meters per second for velocity. The servo is already determined; it is a rotational servo motor I believe. Below is the code I have to date:

/* 
 Controlling a servo position using a potentiometer (variable resistor) 
 by Michal Rinott <http://people.interaction-ivrea.it/m.rinott> 

 modified on 8 Nov 2013
 by Scott Fitzgerald
 http://arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int potpin1 = 1;  // analog pin used to connect the potentiometer
int potpin2 = 2;  // analog pin used to connect the potentiometer
int potpin3 = 3;  // analog pin used to connect the potentiometer
int val1;    // variable to read the value from the analog pin
int val2;    // variable to read the value from the analog pin
int val3;    // variable to read the value from the analog pin
void setup()
{
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}


void loop() 
{ 
  val = analogRead(potpin1); // reads the value of the potentiometer (value between 0 and 1023) 
  val = analogRead(potpin1);
  val = map(val1, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180) 
  val = analogRead(potpin2); // reads the value of the potentiometer (value between 0 and 1023) 
  val = analogRead(potpin2);
  val = map(val2, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  val = analogRead(potpin3); // reads the value of the potentiometer (value between 0 and 1023) 
  val = analogRead(potpin3);
  val = map(val3, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value 
  delay(15);                           // waits for the servo to get there 
}

Thanks

Do you mean that it is a continuous rotation servo that you can't set the position of ?

I am a little out of my depth, but I am able to set the position, yes, turning 0-180.

Hi John, these values as I understand it are to control, in Oceanographers language, wavelength (the horizontal distance between two crests or two troughs), amplitude (the vertical distance between trough and crest), and velocity (the speed at which wave crests move across the water). The Units of measurement for each is meters for wavelength and amplitude and meters per second for velocity...So I think I would take the 3rd control to the first of these, the wavelength. Would this still work?

The servo pushes the waveboard which suggests three things you can change: How fast it pushes, how often and how far. I suppose that the first gives amplitude, the second frequency and the last, pattern although I'm a little unclear about what pattern means in practice.

That ties back to the three pots. I'd be inclined to ignore them initially and just have the device generate one wave type and live with the fact that you have to recompile to change anything while you test out the mechanics.

Did you try contacting the author of the video - he might share his code, if indeed he hasn't published it already.

I think the third knob is controlling the difference in frequency between alternating wavefronts. It looks like when you turn that knob up you get alternating fast and slow waves.

Here is a first pass at a sketch that will control a servo with three knobs.

#include <Servo.h>
Servo WaveServo;  // create servo object to control a servo

const long StepsPerQuarterWave = 100;

const byte FrequencyPotPin = A1;  // analog pin used to connect the potentiometer
const byte MagnitudePotPin = A2;  // analog pin used to connect the potentiometer
const byte DeltaPotPin = A3;  // analog pin used to connect the potentiometer
const byte WaveServoPin = 9;

unsigned long LastStepTime = 0;
boolean DoingF1 = true;  // Start with an f1 wave cycle
long StepNumber = 0;

void setup()
{
  Serial.begin(115200);
  delay(200);

  WaveServo.attach(WaveServoPin);  // attaches the servo on pin 9 to the servo object
}

void loop()
{
#if 1 // change to 0 for debug
  float f0 = 0.3 +  (analogRead(FrequencyPotPin) * 10.0) / 1024.0; // Cycles per second: 0.3 to 10.0 (in hundredths)
  int m0 = map(analogRead(MagnitudePotPin), 0, 1023, 0, 500); // microseconds from center
  float delta = (analogRead(DeltaPotPin) * 0.9) / 1024.0; // Percent difference in frequency between alternate waves
#else
  float f0 = 1.0;
  int m0 = 500;
  float delta = 0.3;
#endif

  float f1 = f0 - (f0 * delta);
  float f2 = f0 + (f0 * delta);

  unsigned long f1MicrosecondsPerStep = (1000000.0 / f1) / (StepsPerQuarterWave * 4);
  unsigned long f2MicrosecondsPerStep = (1000000.0 / f2) / (StepsPerQuarterWave * 4);

  if (DoingF1)
  {
    if (micros() - LastStepTime >= f1MicrosecondsPerStep)
    {
      LastStepTime = micros();
#if 1 // Change to 0 for debug
      WaveServo.writeMicroseconds(1500 + angleMicroseconds(StepNumber, m0));
#else
      Serial.println(1500 + angleMicroseconds(StepNumber, m0));
#endif
      StepNumber++;
      if (StepNumber >= StepsPerQuarterWave * 4)
      {
        StepNumber = 0;
        DoingF1 = false;
      }
    }
  }
  else
  {
    // Doing f2
    if (micros() - LastStepTime >= f2MicrosecondsPerStep)
    {
      LastStepTime = micros();
#if 1 // Change to 0 for debug
      WaveServo.writeMicroseconds(1500 + angleMicroseconds(StepNumber, m0));
#else
      Serial.println(1500 + angleMicroseconds(StepNumber, m0));
#endif
      StepNumber++;
      if (StepNumber >= StepsPerQuarterWave * 4)
      {
        StepNumber = 0;
        DoingF1 = true;
      }
    }
  }
}

int angleMicroseconds(int StepNumber, int microsecondFromCenter)
{
  if (StepNumber < StepsPerQuarterWave)
  {
    // Rising from 0 to StepsPerQuarterWave (0 to microsecondFromCenter)
    return ((long)StepNumber * microsecondFromCenter) / StepsPerQuarterWave;
  }
  else if  (StepNumber < (StepsPerQuarterWave * 3))
  {
    // Next two quarter cycles, falling from + StepsPerQuarterWave to -StepsPerQuarterWave (500 to -500)
    int step = (StepsPerQuarterWave * 2) - StepNumber;
    return ((long)step * microsecondFromCenter) / StepsPerQuarterWave;
  }
  else if (StepNumber < (StepsPerQuarterWave * 4))
  {
    // Fourth quarter, rising again to zero (-500 to 0)
    int step = StepNumber - (StepsPerQuarterWave * 4);
    return ((long)step * microsecondFromCenter) / StepsPerQuarterWave;
  }
  return 0;
}

Thanks John, Got this error from this code, probably means more to you?

Arduino: 1.8.16 (Mac OS X), Board: "Arduino Uno"

Sketch uses 4560 bytes (14%) of program storage space. Maximum is 32256 bytes.
Global variables use 235 bytes (11%) of dynamic memory, leaving 1813 bytes for local variables. Maximum is 2048 bytes.
An error occurred while uploading the sketch
avrdude: ser_open(): can't open device "/dev/cu.usbmodem14201": No such file or directory

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Hi @wildbill Thank you for the input. Ideally need to sim. a number of variables here, simultaneously. I did contact the original author, but at present on holiday.

Your upload problem is not related to the sketch. Something is going wrong with the serial communications. It uploaded fine for me.

It's not important now that John has given you some initial code, but I was suggesting that getting a minimal version going would be a nice way to start. You're way beyond that now :grinning:

@wildbill Oh no problem Bill, thank you for your kind imput anyhow! Alternative ideas and approaches always welcome!

@johnwasser Appreciated, I realised I had not copied the code in correctly. Error free now! I will test the code, make a copy and may make some tweaks, at the moment the servo is on a 360 rotation, just need this to be 180 across all three pots.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.