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