Go Down

Topic: audio instead of knob to control servo (Read 442 times) previous topic - next topic

Goldenshuttle

Jan 18, 2019, 06:35 am Last Edit: Jan 18, 2019, 08:11 am by Goldenshuttle
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
https://www.youtube.com/watch?v=k6TeBKtsZvs
here is the code i am using working good on Nano
Code: [Select]
/*
 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
}
Live to learn & make

GypsumFantastic

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:

Code: [Select]
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
}

Goldenshuttle

Thanks GypsumFantastic; this is interesting,  i will load and see the result
Live to learn & make

Goldenshuttle

@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 ?
Code: [Select]
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);
  }
}
Live to learn & make

Grumpy_Mike

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.

Goldenshuttle

 :)  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 ?

Code: [Select]
#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);
}
Live to learn & make

AWOL

"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Goldenshuttle

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

Code: [Select]
#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);
}
Live to learn & make

AWOL

"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Goldenshuttle

Code: [Select]
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   
Live to learn & make

AWOL

It will always go to 30 degrees.
Quote
something wrong ?
Yup.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

LightuC

You've got a ';' placed after the if statement so the next block setting the servo to 30 degrees will always execute.
Code: [Select]
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:
Code: [Select]
if (audioVal > cliff)
{
    servo1.write(150);
}
else
{
    servo1.write(30);
}

Goldenshuttle

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

Goldenshuttle

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

Code: [Select]
#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);
}
Live to learn & make

sherzaad



analogRead(5);

should it that be

analogRead(A5);

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

Go Up