Автоматическая фокусировка на Arduino и Digispark с датчиком расстояния VL53L0X и драйвером DRW8825.

Здравствуйте!

Представляю два варианта самодельного электро привода для автоматической фокусировки на базе Arduino UNO и Digispark

Первый вариант

Первый вариант привода, собран на базе одной платы Arduino UNO, он более простой, но имеет меньшую скорость настройки фокуса.

Автоматический привод для настройки фокуса на базе Arduino UNO,  драйвера шагового двигателя DRW8825, и  датчика расстояния VL53L0X

В данном проекте используется:

плата Arduino Uno

Датчик расстояния VL53L0X

Драйвер шагового двигателя DRW8825

Сопротивления с номиналом в пределах от 500 до 1000 ом

Макетная плата

Соединительные провода

И источники питания

Один источник питания для платы Arduino UNO, он не должен быть импульсным, и напряжение должно быть в пределах от 3.7 до 5 вольт, а второй источник питания для драйвера шагового двигателя, подойдет блок питания на пару ампер с напряжением от 9 до 35 вольт.

Прежде чем все собирать, необходимо загрузить скетч на плату Arduino UNO. О том как настроить скорость вращения шагового двигателя, подробно рассказывается в видео, которое найдете в конце этой статьи. Кроме настройки скорости вращения, можно еще изменять микро шаг шагового двигателя, об этом смотрите даташит того драйвера, который вы будете использовать в этом проекте.


//Начало скетча первого варианта

const int step_Pin = 5;   //контакт для подключения к пину Step
const int dir_Pin = 6;    //контакт для подключения к пину Dir
const int enable_Pin = 7; //контакт для подключения к пину Enable

int error_Plus  = 0;     //поправка цели на прибавление
int error_Minus = 0;      //поправка цели на убавление
int tsel = 100;           //переменная для хранения значения расстояния которое является целью для шагового двигателя
int speed_1 = 50;         //частота импульсов для 1 скости (для сигнала Step)
int speed_2 = 70;         //частота импульсов для 2 скости (для сигнала Step)
int speed_3 = 100;        //частота импульсов для 3 скости (для сигнала Step)


//Библиотеки для работы с VL53L0X.
//Это стандартные библиотеки, которые можно найти в менеджере библиотек, по запросу "VL53L0X"
#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor;

//----------------- Здесь все что касается функции scan_distans(); -------------------
//массив для функции scan_distans(); нужен для хранения 50 значений расстояния
int arr_mm [50];

 // переменные для функции scan_distans();
int black_mm = 0;   //переменная  для хранения первичного значения расстояния
int count = 0;      //переменная которая является счетчиком для изменения записываемой ячейки массива
int mm = 0;         //переменная  для хранения усредненного значение расстояния

void scan_distans(){                                 //функция для получения усредненного значения
  black_mm = sensor.readRangeContinuousMillimeters();//получаем первичные данные с датчика расстояния и помещаем их в переменную black_mm
  arr_mm [count] = black_mm;                         //здесь происходит запись первичных данных в массив arr_mm
  //в этой очень длинной строке складываются все значения массива arr_mm, и результат делится на количество ячеек массива, таким образом получаем среднее значение на основе последних 50 значений
  mm = (arr_mm [0] + arr_mm [1] + arr_mm [2] + arr_mm [3] + arr_mm [4] + arr_mm [5] + arr_mm [6] + arr_mm [7] + arr_mm [8] + arr_mm [9] + arr_mm [10] + arr_mm [11] + arr_mm [12] + arr_mm [13] + arr_mm [14] + arr_mm [15] + arr_mm [16] + arr_mm [17] + arr_mm [18] + arr_mm [19] + arr_mm [20] + arr_mm [21] + arr_mm [22] + arr_mm [23] + arr_mm [24] + arr_mm [25] + arr_mm [26] + arr_mm [27] + arr_mm [28] + arr_mm [29] + arr_mm [30] + arr_mm [31] + arr_mm [32] + arr_mm [33] + arr_mm [34] + arr_mm [35] + arr_mm [36] + arr_mm [37] + arr_mm [38] + arr_mm [39] + arr_mm [40] + arr_mm [41] + arr_mm [42] + arr_mm [43] + arr_mm [44] + arr_mm [45] + arr_mm [46] + arr_mm [47] + arr_mm [48] + arr_mm [49])/50;
  count++; if (count>49){count=0;}//здесь происходит прибавление к переменной count, и если на стала больше 49, то переменной count снова присваивается значение ноль
}
//----------------- Конец всего что касается функции scan_distans(); -------------------

void setup()
{
  Wire.begin();           //установка соединения с датчиком расстояния
  sensor.setTimeout(100); //пауза
  if (!sensor.init()){    //если связь с датчиком расстояния не установилась, то попадаем в бесконечный цикл
    while (1) {}
  }
  sensor.startContinuous();
  
while(count < 50){ //цикл для получения первых 50 значений расстояния и помещения их в массив
  black_mm = sensor.readRangeContinuousMillimeters();//получаем первичные данные с датчика расстояния и помещаем их в переменную black_mm
  arr_mm [count] = black_mm;                         //здесь происходит запись первичных данных в массив arr_mm
  //в этой очень длинной строке складываются все значения массива arr_mm и результат делится на количество ячеек массива, таким образом получаем среднее значение на основе последних 50 значений
  mm = (arr_mm [0] + arr_mm [1] + arr_mm [2] + arr_mm [3] + arr_mm [4] + arr_mm [5] + arr_mm [6] + arr_mm [7] + arr_mm [8] + arr_mm [9] + arr_mm [10] + arr_mm [11] + arr_mm [12] + arr_mm [13] + arr_mm [14] + arr_mm [15] + arr_mm [16] + arr_mm [17] + arr_mm [18] + arr_mm [19] + arr_mm [20] + arr_mm [21] + arr_mm [22] + arr_mm [23] + arr_mm [24] + arr_mm [25] + arr_mm [26] + arr_mm [27] + arr_mm [28] + arr_mm [29] + arr_mm [30] + arr_mm [31] + arr_mm [32] + arr_mm [33] + arr_mm [34] + arr_mm [35] + arr_mm [36] + arr_mm [37] + arr_mm [38] + arr_mm [39] + arr_mm [40] + arr_mm [41] + arr_mm [42] + arr_mm [43] + arr_mm [44] + arr_mm [45] + arr_mm [46] + arr_mm [47] + arr_mm [48] + arr_mm [49])/50;
  count++; //прибавляем единицу к переменной count
}
count = 0; //присваиваем ноль переменной count

  //назначаем пины как выходы, и задаем им состояния LOW или HIGH
  pinMode(step_Pin, OUTPUT);   digitalWrite(step_Pin, LOW);
  pinMode(dir_Pin, OUTPUT);    digitalWrite(dir_Pin, LOW);
  pinMode(enable_Pin, OUTPUT); digitalWrite(enable_Pin, HIGH);
  //для пина enable_Pin следует указать состояние HIGH, так как при LOW драйвер шагового двигателя будет активен

tsel = tsel + error_Plus - error_Minus;      //выражение для поправки цели
}

void loop()
{
scan_distans();                               //1 раз сканируем расстояние до объекта и получаем новое усредненное значение

if(mm == tsel){                               //если расстояние равно цели то выполняем следующее...
  noTone(step_Pin);
  digitalWrite(enable_Pin, HIGH);             //подаем высокий уровень на контакт Step чтобы отключить драйвер шагового двигателя
}else{digitalWrite(enable_Pin, LOW);}         //иначе включаем драйвер шагового двигателя и выполняем один из следующих блоков

if(mm - 1 > tsel){               //если расстояние больше цели - единица, то выполняем следующее...
                digitalWrite(dir_Pin, LOW);   //задаем направление вращения против часовой              
  //далее при помощи функции tone задаем частоту импульсов в зависимости от расстояния до объекта
  if(mm - 11 >= tsel) {tone(step_Pin, speed_3);} //если объект отклонился более чем на 10 мм. то сделать частоту 150 Гц для сигнала Step
  if(mm - 3 >= tsel && mm - 10 <= tsel){tone(step_Pin, speed_2);}//если расстояние в пределах от 3 мм. до 10 мм. то сделать частоту 80 Гц
  if(mm - 1 >= tsel && mm - 2 <= tsel){tone(step_Pin, speed_1);} //если расстояние в пределах от 1 мм. до 2 мм. то сделать частоту 50 Гц 
}

if(mm + 1  < tsel){               //если расстояние меньше цели + единица, то выполняем следующее...
                digitalWrite(dir_Pin, HIGH);  //задаем направление вращения по часовой
  //далее при помощи функции tone задаем частоту импульсов в зависимости от расстояния до объекта
  if(mm + 11 <= tsel) {tone(step_Pin, speed_3);} //если объект отклонился более чем на 10 мм то сделать частоту 150 Гц для сигнала Step
  if(mm + 3 <= tsel && mm + 10 >= tsel){tone(step_Pin, speed_2);}//если расстояние в пределах от 3 мм. до 10 мм. то сделать частоту 80 Гц
  if(mm + 1 <= tsel && mm + 2 >= tsel){tone(step_Pin, speed_1);} //если расстояние в пределах от 1 мм. до 2 мм. то сделать частоту 50 Гц
}
}

//Конец скетча первого варианта




После загрузки скетча на плату Arduino UNO, соберите все как показано на этой схеме

Схема для сборки автоматический привода для настройки фокуса, на базе Arduino UNO,  драйвера шагового двигателя DRW8825, и  датчика расстояния VL53L0X

После сборки убедитесь что все верно, и можно подключать питание.



Второй вариант

Второй вариант, состоит уже из платы Arduino Uno и платы Digispark.

Данный вариант отличается от предыдущего варианта, более высокой производительностью, в связи с тем, что формированием сигнала Step теперь занимается плата Digispark.

В этом случае скорость вращения шагового двигателя, ограничивается лишь параметрами самого шагового двигателя.

Такая связка представляет, подобие двух ядерного процессора, и позволяет максимально быстро получать значения расстояния, и в тоже время крутить шаговый двигатель с максимально допустимой скоростью.

Автоматический привод для настройки фокуса на базе Arduino UNO и Digispark,  а также драйвера шагового двигателя DRW8825, и  датчика расстояния VL53L0X

И в этой версии используется два скетча, которые вместе являются копией предыдущего варианта, с той лишь разницей, что между платами организована простейшая связь, по двум проводам.

Перед сборкой необходимо загрузить этот скетч в плату Arduino Uno.


//Начало скетча второго варианта для платы Arduino Uno

const int dir_Pin = 6;    //контакт для подключения к пину Dir
const int enable_Pin = 7; //контакт для подключения к пину Enable

const int kanal_A = 8;   //контакт для подключения канала А (для связи с платой Digispark)
const int kanal_B = 9;   //контакт для подключения канала В (для связи с платой Digispark)

int error_Plus  = 22;     //поправка цели на прибавление
int error_Minus = 0;      //поправка цели на убавление
int tsel = 100;           //переменная для хранения значения расстояния которое является целью для шагового двигателя

//Библиотеки для работы с VL53L0X.
//Это стандартные библиотеки, которые можно найти в менеджере библиотек, по запросу "VL53L0X"
#include <Wire.h>
#include <VL53L0X.h>

VL53L0X sensor;

//----------------- Здесь все что касается функции scan_distans(); -------------------
//массив для функции scan_distans(); нужен для хранения 30 значений расстояния
int arr_mm [30];

 // переменные для функции scan_distans();
int black_mm = 0;   //переменная  для хранения первичного значения расстояния
int count = 0;      //переменная которая является счетчиком для изменения записываемой ячейки массива
int mm = 0;         //переменная  для хранения усредненного значение расстояния

void scan_distans(){                                 //функция для получения усредненного значения
  black_mm = sensor.readRangeContinuousMillimeters();//получаем первичные данные с датчика расстояния и помещаем их в переменную black_mm
  arr_mm [count] = black_mm;                         //здесь происходит запись первичных данных в массив arr_mm
  //в этой очень длинной строке складываются все значения массива arr_mm, и результат делится на количество ячеек массива, таким образом получаем среднее значение на основе последних 30 значений
  mm = (arr_mm [0] + arr_mm [1] + arr_mm [2] + arr_mm [3] + arr_mm [4] + arr_mm [5] + arr_mm [6] + arr_mm [7] + arr_mm [8] + arr_mm [9] + arr_mm [10] + arr_mm [11] + arr_mm [12] + arr_mm [13] + arr_mm [14] + arr_mm [15] + arr_mm [16] + arr_mm [17] + arr_mm [18] + arr_mm [19] + arr_mm [20] + arr_mm [21] + arr_mm [22] + arr_mm [23] + arr_mm [24] + arr_mm [25] + arr_mm [26] + arr_mm [27] + arr_mm [28] + arr_mm [29])/30;
  count++; if (count>29){count=0;}//здесь происходит прибавление к переменной count, и если на стала больше 49, то переменной count снова присваивается значение ноль.
}
//----------------- Конец всего что касается функции scan_distans(); -------------------

void setup()
{
  Wire.begin();           //установка соединения с датчиком расстояния
  sensor.setTimeout(100); //пауза
  if (!sensor.init()){    //если связь с датчиком расстояния не установилась, то попадаем в бесконечный цикл
    while (1) {}
  }
  sensor.startContinuous();
  
while(count < 30){ //цикл для получения первых 30 значений расстояния и помещения их в массив
  black_mm = sensor.readRangeContinuousMillimeters();//получаем первичные данные с датчика расстояния и помещаем их в переменную black_mm
  arr_mm [count] = black_mm;                         //здесь происходит запись первичных данных в массив arr_mm
  //в этой очень длинной строке, складываются все значения массива arr_mm и результат делится на количество ячеек массива, таким образом получаем среднее значение на основе последних 30 значений
  mm = (arr_mm [0] + arr_mm [1] + arr_mm [2] + arr_mm [3] + arr_mm [4] + arr_mm [5] + arr_mm [6] + arr_mm [7] + arr_mm [8] + arr_mm [9] + arr_mm [10] + arr_mm [11] + arr_mm [12] + arr_mm [13] + arr_mm [14] + arr_mm [15] + arr_mm [16] + arr_mm [17] + arr_mm [18] + arr_mm [19] + arr_mm [20] + arr_mm [21] + arr_mm [22] + arr_mm [23] + arr_mm [24] + arr_mm [25] + arr_mm [26] + arr_mm [27] + arr_mm [28] + arr_mm [29])/30;
  count++; //прибавляем единицу к переменной count
}
count = 0; //присваиваем ноль переменной count

  //назначаем пины как входы или как выходы, и задаем им состояния LOW или HIGH
  pinMode(dir_Pin, OUTPUT);    digitalWrite(dir_Pin, LOW);
  pinMode(enable_Pin, OUTPUT); digitalWrite(enable_Pin, HIGH);
  //для пина enable_Pin следует указать состояние HIGH, так как при LOW драйвер шагового двигателя будет активен
  pinMode(kanal_A, OUTPUT);    //канал A для связи с платой Digispark
  digitalWrite(kanal_A, LOW);  //задаем низкий уровень, чтобы предотвратить вращение шагового двигателя если это не требуется
  pinMode(kanal_B, OUTPUT);    //канал B для связи с платой Digispark
  digitalWrite(kanal_B, LOW);  //задаем низкий уровень, чтобы предотвратить вращение шагового двигателя если это не требуется
  
tsel = tsel + error_Plus - error_Minus;      //выражение для поправки цели
}

void loop()
{
scan_distans();                               //1 раз сканируем расстояние до объекта и получаем новое усредненное значение

if(mm == tsel){                               //если расстояние равно цели то выполняем следующее...
  digitalWrite(enable_Pin, HIGH);             //подаем высокий уровень на контакт Step чтобы отключить драйвер шагового двигателя
  digitalWrite(kanal_A, LOW);
  digitalWrite(kanal_B, LOW);
}else{digitalWrite(enable_Pin, LOW);}         //иначе включаем драйвер шагового двигателя и выполняем один из следующих блоков

if(mm - 1 > tsel){               //если расстояние больше цели - единица, то выполняем следующее...
                digitalWrite(dir_Pin, LOW);   //задаем направление вращения против часовой              
  //далее при помощи функции tone задаем частоту импульсов в зависимости от расстояния до объекта
  if(mm - 1 >= tsel && mm - 2 <= tsel){  digitalWrite(kanal_A, HIGH); digitalWrite(kanal_B, LOW);}
  if(mm - 3 >= tsel && mm - 13 <= tsel){  digitalWrite(kanal_A, LOW); digitalWrite(kanal_B, HIGH);}  
  if(mm - 14 >= tsel) {  digitalWrite(kanal_A, HIGH); digitalWrite(kanal_B, HIGH);}


}

if(mm + 1  < tsel){               //если расстояние меньше цели + единица, то выполняем следующее...
                digitalWrite(dir_Pin, HIGH);  //задаем направление вращения по часовой
  //далее при помощи функции tone задаем частоту импульсов в зависимости от расстояния до объекта
  if(mm + 1 <= tsel && mm + 2 >= tsel){  digitalWrite(kanal_A, HIGH); digitalWrite(kanal_B, LOW);}
  if(mm + 3 <= tsel && mm + 13 >= tsel){  digitalWrite(kanal_A, LOW); digitalWrite(kanal_B, HIGH);}
  if(mm + 14 <= tsel) {  digitalWrite(kanal_A, HIGH); digitalWrite(kanal_B, HIGH);} 
}
}

//Конец скетча второго варианта для платы Arduino Uno




А этот скетч, а это скетч необходимо загрузить в плату Digispark.

В этом варианте проекта, скорости вращения шагового двигателя настраиваются в этом скетче, а не в скетче для платы Arduino Uno!


//Начало скетча второго варианта для платы Digispark

const int step_Pin = 1;  //контакт для подключения к пину Step


const int kanal_A = 0;   //контакт для подключения канала А
const int kanal_B = 2;   //контакт для подключения канала В
//В зависимость от используемого шагового двигателя, может понадобится настроить задержки в следующих трех строках!
int speed_1 = 8000;      //задержка для 1 скости (для сигнала Step)
int speed_2 = 4000;      //задержка для 2 скости (для сигнала Step)
int speed_3 = 1000;      //задержка для 3 скости (для сигнала Step)

void setup(){
  //назначаем пины как входы или как выходы, и задаем состояния LOW выходу step_Pin
  pinMode(step_Pin, OUTPUT);
  pinMode(kanal_A, INPUT_PULLUP);    //канал A для связи с платой Arduino Uno
  pinMode(kanal_B, INPUT_PULLUP);    //канал B для связи с платой Arduino Uno
}

void loop(){

if(digitalRead(kanal_A) == HIGH && digitalRead(kanal_B) == HIGH){ //если kanal_A = HIGH и kanal_B = HIGH
    delayMicroseconds(speed_3);
    digitalWrite(step_Pin, HIGH);
    delayMicroseconds(speed_3);
    digitalWrite(step_Pin, LOW);
    return;}

if(digitalRead(kanal_A) == LOW && digitalRead(kanal_B) == HIGH){//если kanal_A = LOW и kanal_B = HIGH
    delayMicroseconds(speed_2);
    digitalWrite(step_Pin, HIGH);
    delayMicroseconds(speed_2);
    digitalWrite(step_Pin, LOW);
    return;}

if(digitalRead(kanal_A) == HIGH && digitalRead(kanal_B) == LOW){//если kanal_A = HIGH и kanal_B = LOW
    delayMicroseconds(speed_1);
    digitalWrite(step_Pin, HIGH);
    delayMicroseconds(speed_1);
    digitalWrite(step_Pin, LOW);
    return;}

if(digitalRead(kanal_A) == LOW && digitalRead(kanal_B) == LOW){ //если kanal_A = LOW и kanal_B = LOW
    digitalWrite(step_Pin, LOW);}
}

//Конец скетча второго варианта для платы Digispark




После загрузки скетчей в плату Arduino Uno, и в плату Digispark, можно собирать все как показано на этой схеме

Схема для сборки автоматический привода для настройки фокуса, на базе Arduino UNO и Digispark, а также  драйвера шагового двигателя DRW8825, и  датчика расстояния VL53L0X

После сборки убедитесь что все верно, и можно подключать питание.


Подробное видео “Автоматическая фокусировка на Arduino и Digispark с датчиком расстояния VL53L0X и драйвером DRW8825”


Автоматическая фокусировка на Arduino и Digispark с датчиком расстояния VL53L0X и драйвером DRW8825