Помогите. Часы на шаговом двигателе
- Войдите на сайт для отправки комментариев
Пт, 29/06/2018 - 19:51
Господа. Скетч взят из этой темы. https://www.thingiverse.com/thing:2381829
Мотор вращается в полшага со скоростью один оборот в минуту.
Мне нужно получить один оборот в 6 минут, то есть в 6 раз медленнее, но любые попытки сделать delay больше или меньше заставляют двигатель вращаться быстрее. Что я делаю не так? Вот скетч
#define OUT1 3 // Connect pin A1 of the Arduino to pin IN4 of the stepper board
#define OUT2 1 // Connect pin A2 of the Arduino to pin IN3 of the stepper board
#define OUT3 0 // Connect pin A3 of the Arduino to pin IN2 of the stepper board
#define OUT4 2 // Connect pin A4 of the Arduino to pin IN1 of the stepper board
int countStep = 0; // Initialize countStep
void setup() // Handle setup
{
pinMode(OUT1, OUTPUT); // Use A1 as a digital output
pinMode(OUT2, OUTPUT); // Use A2 as a digital output
pinMode(OUT3, OUTPUT); // Use A3 as a digital output
pinMode(OUT4, OUTPUT); // Use A4 as a digital output
}
void loop() // Handle loop
{
stepping(); // Call stepping
delayMicroseconds(30943); // Pause loop, use value of 30943 for timekeeping or 1000 for testing at high speed
}
void stepping() // Handle stepping
{
switch(countStep) // Handle each step of countStep
{
case 0:
digitalWrite(OUT1, LOW);
digitalWrite(OUT2, LOW);
digitalWrite(OUT3, HIGH);
digitalWrite(OUT4, HIGH);
break;
case 1:
digitalWrite(OUT1, LOW);
digitalWrite(OUT2, LOW);
digitalWrite(OUT3, HIGH);
digitalWrite(OUT4, LOW);
break;
case 2:
digitalWrite(OUT1, LOW);
digitalWrite(OUT2, HIGH);
digitalWrite(OUT3, HIGH);
digitalWrite(OUT4, LOW);
break;
case 3:
digitalWrite(OUT1, LOW);
digitalWrite(OUT2, HIGH);
digitalWrite(OUT3, LOW);
digitalWrite(OUT4, LOW);
break;
case 4:
digitalWrite(OUT1, HIGH);
digitalWrite(OUT2, HIGH);
digitalWrite(OUT3, LOW);
digitalWrite(OUT4, LOW);
break;
case 5:
digitalWrite(OUT1, HIGH);
digitalWrite(OUT2, LOW);
digitalWrite(OUT3, LOW);
digitalWrite(OUT4, LOW);
break;
case 6:
digitalWrite(OUT1, HIGH);
digitalWrite(OUT2, LOW);
digitalWrite(OUT3, LOW);
digitalWrite(OUT4, HIGH);
break;
case 7:
digitalWrite(OUT1, LOW);
digitalWrite(OUT2, LOW);
digitalWrite(OUT3, LOW);
digitalWrite(OUT4, HIGH);
break;
default:
digitalWrite(OUT1, LOW);
digitalWrite(OUT2, LOW);
digitalWrite(OUT3, LOW);
digitalWrite(OUT4, LOW);
break;
}
countStep=countStep+1; // After each cycle add 1 to countStep
if(countStep==8)
{countStep=0;} // Reset countStep on rollover
}
Может причина тут: delayMicroseconds()
"В данной версии Ардуино максимальная пауза воспроизводимая корректно — 16383. Возможно это будет изменено в следующих версиях Arduino. Для остановки выполнения программы более чем на несколько тысяч микросекунд рекомендуется использовать функцию delay()."
Ясно, но тогда пауза в миллисекундах получается 185.66. Точность потеряется
Ясно, спасибо
Вроде аргумент у неё типа unsigned int, может уже устаревшая цитата. Потестируйте.
Я думаю проще от делей отказаться и использовать таймер
Можно сделать что-то вроде этого:
... unsigned long timePrev; ... void setup(){ ... timePrev = micros(); ... } void loop(){ if (micros()-timePrev > 30943*6 || micros()-timePrev < 0) { stepping(); timePrev = micros(); } } ...Для часов в любом случае лучше таймер и прямая запись в порт состояний сразу всех выходов из массива.
А еще лучше взять драйвер степпера и из точного генератора в него пульсировать.
PS. Извините, не посмотрел, что мотор униполярный. Тогда в силе только первый абзац.
Да ладно? А кто мешает сначала delay(186), a потом delaymicrosecond(660)? И подобрать 660 поточнее?
Да по всякому можно. Вопрос только в том, насколько часто их подводить придется ))
Я за примерно такой вариант:
volatile uint8_t currentStep; volatile uint8_t motorStep[] = { B00000011, B00000110, B00001100, B00001001, ... }; ISR_...() { PORTB = motorStep[currentStep]; if (sizeof(motorStep) >= currentStep) { currentStep = 0; } else { currentStep++; } } ...пауза в миллисекундах получается 185.66. Точность потеряется
Мотор переделан в биполярный. Драйвер l293d
Пока тестирую с простым delay, а дальше буду тестить то, что вы мне посоветовали
С биполярным еще проще: мотор к A4988 и на каждом срабатывании таймера blink одним пином в STEP драйверу на 5мкс. Программа уменьшается втрое. В тиньку зашьете легко.