В этом примере мы продемонстрируем, как использовать Arduino для считывания сигнала от привода стержня обратной связи Фирджелли и преобразования его в измерение расстояния, показывающего, насколько стержень был выдвинут. Это руководство основано на принципах, обсуждаемых в руководстве «Управление скоростью драйвера двигателя с помощью Arduino», Мы рекомендуем просмотреть это руководство перед продолжением.
Примечание. Это руководство предполагает наличие предварительных знаний об основных электронных принципах, аппаратном и программном обеспечении Arduino. Если вы впервые используете Arduino, мы предлагаем изучить основы одного из многих замечательных руководств для начинающих, доступных через поиск в Google и на YouTube. Имейте в виду, что у нас нет ресурсов для оказания технической поддержки для пользовательских приложений, и мы не будем отлаживать, редактировать, предоставлять код или схемы соединений за пределами этих общедоступных руководств.
Компоненты
- Линейный привод со стержнем обратной связи
- Блок питания 12 В
- Ардуино
- Драйвер двигателя
- Внешний потенциометр (для второй части этого руководства)
- Электрические провода для подключения и обжимного инструмента или паяльника
Проводка
Обзор аппаратного и программного обеспечения для чтения позиции
Соберите схему, как указано выше, и загрузите приведенный ниже код. Вам нужно будет изменить строку 16 кода на вашу конкретную длину хода, в настоящее время она установлена для 6-дюймового привода штока обратной связи.
Эта программа сначала выдвигает и полностью втягивает привод, чтобы найти минимальное и максимальное показание аналогового датчика от потенциометра (строки 27 и 28 кода). Это необходимо, потому что, несмотря на то, что диапазон показаний потенциометра составляет [0, 1023], на практике этот диапазон может быть уменьшен из-за передаточного числа внутри привода, не позволяющего потенциометру полностью вращаться до его предела.
После этой начальной последовательности калибровки привод будет непрерывно выдвигаться и втягиваться, выводя поток данных, отображающих текущую увеличенную длину линейного привода (в дюймах).
Код
https://gist.github.com/Will-Firgelli/8c78092ca850aa8a50ae36842b97150f/* Firgelli Automations
* Limited or no support: we do not have the resources for Arduino code support
*
* Program enables momentary direction control of actuator using push button
*/
#include <elapsedMillis.h>
elapsedMillis timeElapsed;
int RPWM = 10;
int LPWM = 11;
int sensorPin = A0;
int sensorVal;
int Speed=255;
float strokeLength = 6.0; //customize to your specific stroke length
float extensionLength;
int maxAnalogReading;
int minAnalogReading;
void setup() {
pinMode(RPWM, OUTPUT);
pinMode(LPWM, OUTPUT);
pinMode(sensorPin, INPUT);
Serial.begin(9600);
maxAnalogReading = moveToLimit(1);
minAnalogReading = moveToLimit(-1);
}
void loop(){
Serial.println("Extending...");
sensorVal = analogRead(sensorPin);
while(sensorVal < maxAnalogReading){
driveActuator(1, Speed);
displayOutput();
delay(20);
}
driveActuator(0, Speed);
delay(1000);
Serial.println("Retracting...");
sensorVal = analogRead(sensorPin);
while(sensorVal > minAnalogReading){
driveActuator(-1, Speed);
displayOutput();
delay(20);
}
driveActuator(0, Speed);
delay(1000);
}
int moveToLimit(int Direction){
int prevReading=0;
int currReading=0;
do{
prevReading = currReading;
driveActuator(Direction, Speed);
timeElapsed = 0;
while(timeElapsed < 200){ delay(1);} //keep moving until analog reading remains the same for 200ms
currReading = analogRead(sensorPin);
}while(prevReading != currReading);
return currReading;
}
float mapfloat(float x, float inputMin, float inputMax, float outputMin, float outputMax){
return (x-inputMin)*(outputMax - outputMin)/(inputMax - inputMin)+outputMin;
}
void displayOutput(){
sensorVal = analogRead(sensorPin);
extensionLength = mapfloat(sensorVal, float(minAnalogReading), float(maxAnalogReading), 0.0, strokeLength);
Serial.print("Analog Reading: ");
Serial.print(sensorVal);
Serial.print("\tActuator extension length: ");
Serial.print(extensionLength);
Serial.println(" inches");
}
void driveActuator(int Direction, int Speed){
switch(Direction){
case 1: //extension
analogWrite(RPWM, Speed);
analogWrite(LPWM, 0);
break;
case 0: //stopping
analogWrite(RPWM, 0);
analogWrite(LPWM, 0);
break;
case -1: //retraction
analogWrite(RPWM, 0);
analogWrite(LPWM, Speed);
break;
}
}
Использование внешнего потенциометра для контроля положения
Приведенный выше пример продемонстрировал, как можно снимать показания с привода штока обратной связи, но, допустим, мы хотим переместить привод в определенное положение, как мы это делаем? В следующем разделе рассматривается такая ситуация с использованием внешнего потенциометра в качестве пользовательского ввода для желаемого заданного положения привода. На практике вы можете изменить этот пример, чтобы вводить данные пользователя из любой желаемой формы.
Проводка
Обзор аппаратного и программного обеспечения для управления положением
Схема подключения почти такая же, как и в первой части этого руководства, только теперь внешний потенциометр был подключен к аналоговому выводу A1.
Программа, представленная ниже, перемещается в положение, установленное пользователем с помощью внешнего потенциометра. В строке 18 кода задается буферная переменная, которая используется позже в строках 36 и 39. Возможный буфер дает диапазон вокруг желаемого заданного положения, в котором привод остановится, это требуется, поскольку два потенциометра имеют склонность к флатату на +/- 2 единицы. Таким образом, если бы буфер не был включен, приводы будут сильно вибрировать вокруг заданного положения. Чтобы увидеть это в действии, установите буфер в строке 18 на ноль (не позволяйте исполнительным механизмам долго вибрировать, так как это может привести к повреждению).
Код
https://gist.github.com/Will-Firgelli/41ec87433f0aaa1abc33e79168076b3b/* Firgelli Automations
* Limited or no support: we do not have the resources for Arduino code support
*
* Program enables momentary direction control of actuator using push button
*/
#include <elapsedMillis.h>
elapsedMillis timeElapsed;
int RPWM = 10;
int LPWM = 11;
int sensorPin = A0;
int potPin = A1;
int potVal;
int sensorVal;
int Speed = 255;
int Buffer = 4;
int maxAnalogReading;
int minAnalogReading;
void setup() {
pinMode(RPWM, OUTPUT);
pinMode(LPWM, OUTPUT);
pinMode(sensorPin, INPUT);
pinMode(potPin, INPUT);
Serial.begin(9600);
maxAnalogReading = moveToLimit(1);
minAnalogReading = moveToLimit(-1);
}
void loop(){
potVal = map(analogRead(potPin), 0, 1023, minAnalogReading, maxAnalogReading);
sensorVal = analogRead(sensorPin);
if(potVal > (sensorVal+Buffer)){ //addition gives buffer to prevent actuator from rapidly vibrating due to noisy data inputs
driveActuator(1, Speed);
}
else if(potVal < (sensorVal-Buffer)){
driveActuator(-1, Speed);
}
else{
driveActuator(0, Speed);
}
Serial.print("Potentiometer Reading: ");
Serial.print(potVal);
Serial.print("\tActuator reading: ");
Serial.println(sensorVal);
delay(10);
}
int moveToLimit(int Direction){
int prevReading=0;
int currReading=0;
do{
prevReading = currReading;
driveActuator(Direction, Speed);
timeElapsed = 0;
while(timeElapsed < 200){ delay(1);} //keep moving until analog reading remains the same for 200ms
currReading = analogRead(sensorPin);
}while(prevReading != currReading);
return currReading;
}
void driveActuator(int Direction, int Speed){
switch(Direction){
case 1: //extension
analogWrite(RPWM, Speed);
analogWrite(LPWM, 0);
break;
case 0: //stopping
analogWrite(RPWM, 0);
analogWrite(LPWM, 0);
break;
case -1: //retraction
analogWrite(RPWM, 0);
analogWrite(LPWM, Speed);
break;
}
}