сделать/доделать скетч для слайдера видеокамеры
- Войдите на сайт для отправки комментариев
Здравствуйте господа,
Cобственно есть наполовину написанный скетч для слайдера с шаговым мотором NEMA17. Исполнитель не смог продолжить проект по личным обстоятельствам, поэтому мне надо довести его до конца или переделать.
Сам не разбираюсь совсем, знаний хватило собрать механическую часть самому и электроннику по схеме от исполнителя.
В наличии вот этот Кит Ардуино и Мотор.
Требования:
Включение/выключения движения длинным нажатием на энкодер. Смена направления коротким. Регулировка скорости вращением. Должно работать как до запуска так и на ходу, с отображением на дисплее направления движения, текущей скорости, ну и точного положения раз уж все равно шаги считаем.
Автоматическая смена направления при достижении конечных пунктов слайдера.
Как ручные, так и автоматические остановки/смены направления с плавным торможением-разгоном.
Конечные остановки без датчиков, высчитываются по количеству шагов мотора, что требует калибровку при старте.
алгоритм калибровки: при заранее измеренном количестве шагов, при старте системы дисплей выдает слово Calibration? и стрелку направления домой (в крайнее положение в сторону мотора). вручную сдвигаю каретку в домашнее положение, и нажимаю на энкодер, подтверждая что каретка находится в домашнем положении. режим движения автоматически переключается в обратное направление. При нажатии на старт едет заданное количество шагов, там останавливается и едет назад, до домашнего крайнего положения, и так далее.
Что имеем:
Первый вариант скетча, видимо без конечных остановок но с возможностью померять шаги залит в Ардуину, дисплей включается, показывает вольтаж, реагирует на нажатия энкодера на включение выключение, регулировка скорости не работает корректно, мотор щелкает но не включается.
собрано вот по такой схеме

Скетч:
/************************************
Проект: слайдер для видеокамеры
Заказчик: Денис Иванов
E-mail:
*************************************/
#include <U8glib.h>
#define pinE 10
#define pinRW 9
#define pinDI 8
U8GLIB_ST7920_128X64 u8g(pinE, pinRW, pinDI, U8G_PIN_NONE);
//U8GLIB_KS0108_128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 14, 15, 17, 16); // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs1=14, cs2=15,di=17,rw=16
/* Вывод, который будет измерять напряжение батареи. Напряжение на вывод подаётся
через резистивный делитель. Верхнее плечо - 510 кОм, нижнее плечо - 33 кОм.
Максимальное напряжение, подаваемое на делитель - 18.1В. При этом с делителя на
вход микроконтроллера будет поступать 1.1В, т.е. максимальное опорное. */
#define pinU A0
/* Номера выврдов, к которым подключен энкодер */
#define pinEncoderA 2
#define pinEncoderB 3
#define pinEncoderButton 12
/* Номера выводов, к которым подключен драйвер A4988 шагового двигателя NEMA17 */
#define pinStep 22
#define pinDirection 23
#include <AccelStepper.h>
AccelStepper mystepper(1, pinStep, pinDirection); // Инициализация ШД для управления внешним драйвером
/* Функция измерения напряжения батареи */
float getBattaryU(void) {
float U = 0.0;
uint16_t adc = 0;
for(uint8_t i=0; i<10; i++) adc += analogRead(pinU); // Считываем показания АЦП 10 раз для повышения точности
adc /= 10; // Вычисляем среднее значение АЦП
U = float(adc) * 18.1 / 1023.0; // Вычисляем реальное значение напряжения батареи
return U; // Возвращаем усреднённое значение напряжения
}
volatile int stepperSpeed = 10; // Скорость ШД
volatile long steps = 0;
volatile bool calibration = false;
void setup() {
analogReference(INTERNAL1V1); // Включаем внутренний ИОН на 1.1В
attachInterrupt(0, encoder, RISING); // Внешнее прерывание для обработки 1-го вывода энкодера
pinMode(pinEncoderB, INPUT_PULLUP); // Настройка на вход второго вывода энкодера
pinMode(pinEncoderButton, INPUT_PULLUP); // Настройка на вход вывода для кнопки энкодера
/* Настройка параметров ШД */
pinMode(pinStep, OUTPUT);
pinMode(pinDirection, OUTPUT);
mystepper.setMaxSpeed(400); // Максимальная скорость, шагов в секунду (для NEMA17 - 2 оборота в секунду)
mystepper.setAcceleration(10.0); // Ускорение ШД, шагов в секунду
mystepper.setSpeed(0); // Начальная скорость равна 0
// Настройка таймера Т2 для опроса кнопки энкодера в прерывании
TCCR2A = 0x00; TCCR2B = 0x07; TCNT2 = 0x00; TIMSK2 = 0x01;
sei();
Serial.begin(9600);
}
volatile uint8_t menuFlag = 0;
/* Прерывание для обработки вращения энкодера */
void encoder() {
if(digitalRead(pinEncoderB) == HIGH) {
stepperSpeed++;
if(stepperSpeed > 400) stepperSpeed = 0;
}
else {
stepperSpeed--;
if(stepperSpeed < 0) stepperSpeed = 400;
}
}
/* Функция обработки нажатия кнопки энкодера */
volatile bool flagPress = false;
volatile bool longPress = false;
volatile unsigned long timePress = 0;
volatile uint8_t button() {
/* Определение момента нажатия кнопки */
if((!flagPress) && (!longPress) && (digitalRead(pinEncoderButton) == LOW)) {
delay(50);
if(digitalRead(pinEncoderButton) == LOW) {
flagPress = true;
timePress = millis();
}
}
/* Определение момента удержания кнопки */
if((flagPress) && (!longPress) && (millis() - timePress > 1500)) {
longPress = true;
timePress = millis();
return 2;
}
/* Определение момента отпускания кнопки */
if((digitalRead(pinEncoderButton) == HIGH) && (flagPress)) {
delay(50);
if(digitalRead(pinEncoderButton) == HIGH) {
if(longPress) { flagPress = false; longPress = false; return 0; }
else if(!longPress) { flagPress = false; longPress = false; return 1; }
}
}
return 0;
}
volatile bool stepperDirection = false;
/* Прерывание для обработки нажатия кнопки энкодера */
ISR(TIMER2_OVF_vect) {
switch(button()) {
case 1:
stepperDirection = !stepperDirection;
// return;
break;
case 2:
calibration = !calibration;
// return;
break;
}
}
/* Функция отображения меню */
void menu() {
u8g.firstPage();
do
{
u8g.setFont(u8g_font_6x12);
// u8g.drawBox(0, 13, 128, 1);
u8g.setPrintPos(0, 12); u8g.print("U_battary="); u8g.print(getBattaryU()); u8g.print("V ");
u8g.setPrintPos(0, 24); u8g.print(stepperSpeed); u8g.print("step/s; "); u8g.print(float(stepperSpeed) / 200.0); u8g.print("turn/s");
if(!stepperDirection) {u8g.setPrintPos(0, 36); u8g.print("Direction: --->");}
else {u8g.setPrintPos(0, 36); u8g.print("Direction: <---");}
if(!calibration) {u8g.setPrintPos(0, 48); u8g.print("Push encoder to start");}
else {u8g.setPrintPos(0, 48); u8g.print("Push encoder to stop ");}
u8g.setPrintPos(0, 60); u8g.print("STEPS:"); u8g.print(steps);
switch(menuFlag) {
case 0:
break;
}
} while(u8g.nextPage());
}
int dir = 0; long CP=mystepper.currentPosition();
void loop() {
menu();
if(!stepperDirection) dir = 1;
else dir = -1;
if(calibration) {
mystepper.setSpeed(stepperSpeed);
mystepper.runSpeed();
steps = mystepper.currentPosition() - CP;
}
}