audio instead of knob to control servo

I used this servo knob on public domain, but replaced the pot with audio through optocoupler PC817 hooked to input A0 through 10K pullup resistor. works good but the servo moves at every particle of audio high or low volume. I wish some advice to move it only at peak of words..help please. video here

here is the code i am using working good on Nano

/*
 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 then modified on Jan2019 by Goldenshuttle
 http://www.arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>

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

int potpin = 0;  // analog pin used to connect the potentiometer replaced with audio in thru optocoupler
int val = 0;    // variable to read the value from the analog pin
int val2 = 0; 
void setup() {
  pinMode(potpin, INPUT);
  pinMode(9, OUTPUT);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
Serial.begin(9600);
}

void loop() {
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val2 = map(val, 0, 1020, 30, 150);     // scale it to use it with the servo (value between 0 and 180
  myservo.write(val2); // sets the servo position according to the scaled value
 Serial.println(val);
 Serial.println(val2);
  delay(70);                           //give servo enough time to get there
}

How about applying a simple threshold to the incoming value? Then if val is less than the threshold, set it to zero.

So the last section of your code might look like this:

int threshold = 512;      // choose a value that works best

void loop() {
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)

  if (val < threshold) val = 0;       // set val to zero if less than threshold

  val2 = map(val, 0, 1020, 30, 150);     // scale it to use it with the servo (value between 0 and 180
  myservo.write(val2); // sets the servo position according to the scaled value
  Serial.println(val);
  Serial.println(val2);
  delay(70);                           //give servo enough time to get there
}

Thanks GypsumFantastic; this is interesting, i will load and see the result

@GypsumfFantastic yup it worked great. After some trail and error, Threshold 400 was good to give proper movement.
The next question is how do I get rid of the Delay function using Millis..I have seen the blink using millis, but how to incorporate here in my code ?

const int ledPin =  LED_BUILTIN;// the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change:
const long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

You only need to get rid of a delay if there is something you want the code to do that is being blocked by using delay.
I can’t see any point in doing this for your application.

:slight_smile: so I wrote this code for Digispark USB stump
It is I use int cliff = 500 which will move the servo only at certain peaks.
compiles but does not work. Any idea why ?

#include <SoftwareServo.h>

//audio 2 servo using USB arduino
// for servo stuff we include the servo library
SoftwareServo servo1;
int SensorPin = 5;
// creating a servo object
int audioVal = 0;
int cliff = 500;
void setup() {
  Serial.begin(9600);
  servo1.attach(1);
  pinMode(SensorPin, INPUT);  
}
void loop() {
 audioVal = analogRead(SensorPin);
 Serial.println(audioVal);
 if (audioVal <= cliff)
 {servo1.write(150);}
 else if (audioVal > cliff);
{servo1.write(30);}
 delay(50);
}

if (audioVal > cliff);oops

Thanks AWOL, I got the idea...now I changed the code as shown..but no movement:( :confused:

#include <SoftwareServo.h>

//audio 2 servo using USB arduino
// for servo stuff we include the servo library
SoftwareServo servo1;
int SensorPin = 5;
// creating a servo object
int audioVal = 0;
int cliff = 500;
void setup() {
  Serial.begin(9600);
  servo1.attach(1);
  pinMode(SensorPin, INPUT); 
}
void loop() {
 audioVal = analogRead(SensorPin);
 Serial.println(audioVal);
 if (audioVal > cliff)
 {servo1.write(150);}
 else if (audioVal <= cliff);
{servo1.write(30);}
 delay(50);
}

if (audioVal <= cliff);Oops

AWOL:
if (audioVal <= cliff);Oops

ًAWOL, the idea is above Cliff it goes 150 degree, and below Cliff it goes to 30 degree. I thought this will make servo work on peak well, unless something wrong ?? :o

It will always go to 30 degrees.

something wrong ?

Yup.

You've got a ';' placed after the if statement so the next block setting the servo to 30 degrees will always execute.

if (audioVal > cliff)
{
    servo1.write(150);
} 
else if (audioVal <= cliff); // <-- Here it is
{
    servo1.write(30);
}

Why not do if/else instead of if/else if? The second condition will always be true, if the first on is false so:

if (audioVal > cliff)
{
    servo1.write(150);
} 
else 
{
    servo1.write(30);
}

good point, live n learn...I will try it in the morning and see. thanks

did not function again..jesus.. here is the final code, compiles but nothing moves..please hint :frowning:

#include <SoftwareServo.h>

//audio 2 servo
// for servo stuff we include the servo library
SoftwareServo servo1;
int SensorPin = 5;
// creating a servo object
int audioVal = 0;
int cliff = 500;
void setup() {
  servo1.attach(1);
  pinMode(5, INPUT);  
  pinMode(0, OUTPUT); 
}
void loop() {
 audioVal = analogRead(5);
 if (audioVal < cliff)
 {servo1.write(150);}
 else
{servo1.write(30);}
 delay(50);
}

analogRead(5);

should it that be

analogRead(A5);

you are connected to one of the analog pins, right?

sherzaad:
analogRead(5);

should it that be

analogRead(A5);

you are connected to one of the analog pins, right?

The two statements are functionally identical.

AWOL:
The two statements are functionally identical.

Are you sure? This is from "pins_arduino.h" for the standard target:

#define PIN_A0   (14)
#define PIN_A1   (15)
#define PIN_A2   (16)
#define PIN_A3   (17)
#define PIN_A4   (18)
#define PIN_A5   (19)
#define PIN_A6   (20)
#define PIN_A7   (21)

static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;

Doesn't seem like they are the same. Or does the analogRead function internally maps any input to the available pins? E.g. analogRead(5) = analogRead(A0 + input)?

I didn't say that A5 == 5, I said that analogRead(5); is functionally identical to analogRead (A5);

Or does the analogRead function internally maps any input to the available pins?

You have the source; why don't you find out?

LightuC:
does the analogRead function internally maps any input to the available pins?

You have the code, take a look. But yes, it does help you out so that 5 and A5 will access the same analog pin in an analogRead.

wildbill:
You have the code, take a look. But yes, it does help you out so that 5 and A5 will access the same analog pin in an analogRead.

I only have the header files, the arduino core seems to be linked against the sketch at compile time. I only now thought of github, I'm gonna take a look at that.

AWOL:
I didn't say that A5 == 5, I said that analogRead(5); is functionally identical to analogRead (A5);

Glad to learn new things.