Servo Plus Potentiometer
I had to do one more of these before I took it apart.
Not too long ago I saw a link on Make: regarding using potentiometers and servos. To be honest, I never got around to watching the video. But after the last blog entry I made, adding in the potentiometer didn't seem all that hard.
The potentiometer takes 5v on one side, ground on the other. In the middle I hooked to one of the analog pins.
Analog read on the Arduino ranges from 0 to 1023. The servo however took a range of values from 375 to 2400. The leaves me needing to convert from 1023 to 2025. This is a fairly simple ratio, which I originally coded something like this:
pulse value = ((potentiometer value * 2025) / 1023) + 375
Using this formula introduced me to an interesting detail that I had not seen for a while. Not since a project I had done for the State of Minnesota. At the time I was working on a project for the Department of Education. I don't recall the specifics, but I had been doing some calculations with large numbers in Java. Every so often the numbers would turn negative. This is exactly what I started seeing here when multiplying the potentiometer value with 2025.
What's going on is something I learned about much further back in college. The type value I was using was too small for the value I was putting into it. Every bit of the value - or perhaps just one particular one - was overwriting the slot that holds the negative/positive indicator. Very annoying.
To solve the problem on the DOE project I ended up using a larger type. I tried a few different types with the Arduino (doubles, long ints, floats) but to no avail. Instead of digging into a solution further in that direction, a different solution occurred to me - change the calculation:
pulse value = ((2025 / 1023) * potentiometer value) + 375
This forces the division to occur first, which winds up with some value like 1.979 and so forth. This is a much smaller value that when multiplied by the pot value and added to 375 is still managable.
Anyway, here's the code:
/*
* Servo plus potentiometer - a match made in...
* well, a match made on an Arduion at least.
*/
int potPin = 1;
int potVal = 0;
int servoPin = 3;
int baseChar = 48;
int maxCycles = 40;
int minPulse = 375;
int maxPulse = 2400;
int maxAnalog = 1023;
int distance = maxPulse - minPulse;
int list[4] = {-1, -1, -1, -1};
int input = 0;
int pulse = minPulse;
int lastPulse = maxPulse;
void setup()
{
// setup serial schtuff
Serial.begin(9600);
pinMode(servoPin, OUTPUT);
// say hello
Serial.println("Servo with potentiometer control - start");
// get first potentiometer value
potVal = analogRead(potPin);
// calculate pulse from it
calcPulse();
// then go there
specific();
}
void loop()
{
// read from potentiometer
int tmpVal = analogRead(potPin);
// if this is a new value
if (tmpVal != potVal)
{
// keep it
potVal = tmpVal;
// calculate pulse from it
calcPulse();
// then go there
specific();
}
}
void calcPulse()
{
double ratio = distance / maxAnalog;
if (potVal == 0)
pulse = minPulse;
else if (potVal == maxAnalog)
pulse = maxPulse;
else
pulse = ratio * potVal + minPulse;
Serial.print("potVal: ");
Serial.print(potVal, DEC);
Serial.print(", ratio: ");
Serial.print(ratio, DEC);
Serial.print(", pulse: ");
Serial.println(pulse, DEC);
}
void specific()
{
if (pulse >= minPulse && pulse <= maxPulse)
{
//Serial.print("Last pulse ");
//Serial.println(lastPulse);
//Serial.print("Current pulse ");
//Serial.println(pulse);
int travel = max(lastPulse, pulse) - min(lastPulse, pulse);
//Serial.print("Travel ");
//Serial.println(travel);
//Serial.print("Distance ");
//Serial.println(distance);
float cut = (float)travel / (float)distance;
//Serial.print("Cut ");
//Serial.println(cut, DEC);
unsigned int cycles = (maxCycles * cut) + 1;
cycles = max(cycles, 5);
//Serial.print("Cycles ");
//Serial.println(cycles);
for (int i = 0; i <= cycles; i++)
{
digitalWrite(servoPin, HIGH);
delayMicroseconds(pulse);
digitalWrite(servoPin, LOW);
delay(20);
}
lastPulse = pulse;
}
else
{
Serial.print("Pulse given ");
Serial.print(pulse);
Serial.print(" is outside of range: ");
Serial.print(minPulse);
Serial.print("-");
Serial.println(maxPulse);
}
pulse = 0;
}
Comments
Post a Comment