|
Движение деревянного круга, налево и направо |
|
|
|
Sep 18 2008, 03:26
|
Группа: Новичок
Сообщений: 2
Регистрация: 21-04-08
Пользователь №: 36 974

|
Задача имеется такая  Есть круг, размеченный на секторы - от 0 до 15. Он крутится. Можно выбрать любой текущий ("для работы") сектор. Например, мы находимся сейчас на секторе номер пять и нам нужно перейти на сектор номер дестяь. Мы прокручиваем круг на пять секторов, допустим, вправо. Но если текущий сектор пять, а мы хотим перейти на третий, то если бы прокрутили в ту же сторону, то пришлось бы прокручивать всю остальную часть круга, прежде чем перейти на нужный - третий. Экономичнее было бы прокрутить круг налево - и очутится на номере три уже через два сектора. Но как я могу определить, в какую сторону мне экономичнее крутить - налево или направо? Если даны две данных - номер текущего сектора и номер сектора, на который следует перейти.
|
|
|
|
|
 |
Ответов
(1 - 5)
|
Sep 19 2008, 14:45
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(=GM= @ Sep 19 2008, 12:31)  Вычисляете разности (n-m) и (m-n) по модулю 16, сравниваете их и крутите по меньшему. Например, 1) (5-3)mod16=2, (3-5)mod16=-2+16=14, 2<14 - крутите влево. 2) (5-10)mod16=-5+16=11, (10-5)mod16=5, 11>5 - крутите вправо. А зачем вычислять вторую, она ведь жёстко связана с первой, новой информации не несёт. Достаточно сравнивать с половиной количества Код (5-3) mod 16 = 2 2 <= (16 div 2) истинно - крутите влево.
(5-10) mod 16 = -5+16 = 11 11 <= (16 div 2) - ложно - крутите вправо
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Sep 20 2008, 03:50
|
Группа: Новичок
Сообщений: 2
Регистрация: 21-04-08
Пользователь №: 36 974

|
Цитата(=GM= @ Sep 19 2008, 11:31)  Вычисляете разности (n-m) и (m-n) по модулю 16, сравниваете их и крутите по меньшему. Например,
1) (5-3)mod16=2, (3-5)mod16=-2+16=14, 2<14 - крутите влево. 2) (5-10)mod16=-5+16=11, (10-5)mod16=5, 11>5 - крутите вправо. Как я написал на Си: Код void set_motor1(signed char position) // аргумент - номер шприца, на который переход { signed char k = 0; signed char s1,s2 = 0; k = current_position(); // в к находится текущая позиция шприца PORTC.7 = 1; // ес spritze_to_set = position-1; //вводим в переменную номер, на какой переходим от 0 до 15 s1 = ((k - position) % 16); s2 = (position - k) % 16; if (s1 <= s2) motor_control(1,2); // мотор в одну сторону else motor_control(1,1); // мотор в другую сторону } В переходах между, например, 1 и 3 - нормально, а между 1 и 2 - уже крутит в неправильную сторону (тоесть прокручивает полностью круг, чтобы добраться до позиции). Что я делаю не так?
|
|
|
|
|
Sep 20 2008, 06:43
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(Andrei Aleksandrovich @ Sep 20 2008, 06:50)  В переходах между, например, 1 и 3 - нормально, а между 1 и 2 - уже крутит в неправильную сторону (тоесть прокручивает полностью круг, чтобы добраться до позиции). Что я делаю не так?  Вы не поняли, как считать расстояния, в одну из сторон они у Вас выходят отрицательными (и смещёнными). Надо так (len - длина всего круга, остальные переменные тоже с осмысленными именами): Код forward_dist = (to - current) % len; if(forward_dist < 0) forward_dist += len; backward_dist = (current - to) % len; if(backward_dist < 0) backward_dist += len;
if(forward_dist <= backward_dist) { ... Если учесть моё замечание про жёсткую связь между forward_dist и backward_dist, то Код forward_dist = (to - current) % len; if(forward_dist < 0) forward_dist += len; backward_dist = len - forward_dist;
if(forward_dist <= backward_dist) { ... Но тогда непонятно, зачем вообще вычислять backward_dist, если можно так, как я сразу сказал: Код half_len = len/2; // ну или константа, равная половине константы len ... forward_dist = (to - current) % len; if(forward_dist < 0) forward_dist += len; if(forward_dist <= half_len) { ... Собственно, если исходно есть гарантия, что и to и current находятся в диапазоне 0..(len-1), то вычисление остатка не нужно вообще: Код half_len = len/2; ... forward_dist = to - current; if(forward_ist < 0) forward_dist += len; if(forward_dist <= half_len) { ... А для конкретной фиксированной длины 16 (степень двойки) можно вообще так: Код #define LEN 16
#if LEN < 2 || ( LEN & (LEN-1) ) != 0 #error "LEN must be power of 2 and >= 2" #endif
#define HALF_LEN (LEN/2) #define MASK (LEN-1) ... forward_dist = (to - current) & MASK; // или ниже вообще if( !(forward_dist & HALF_LEN) ) { // так как HALF_LEN тоже степень двойки и есть маской старшего бита расстояния // только обозвать тогда тоже нужно вразумительнее, скажем, HALF_LEN_MASK if(forward_dist <= HALF_LEN) { // go forward } else { // go backward }
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Sep 22 2008, 05:30
|
Профессионал
   
Группа: Свой
Сообщений: 553
Регистрация: 17-02-05
Из: Свердловская обл.
Пользователь №: 2 712

|
Цитата(Andrei Aleksandrovich @ Sep 18 2008, 09:26)  Есть круг, размеченный на секторы - от 0 до 15. Он крутится. ... Экономичнее было бы прокрутить круг налево - и очутится на номере три уже через два сектора. Но как я могу определить, в какую сторону мне экономичнее крутить - налево или направо? О какой "экономичности" идет речь? Если круг "крутится", то однозначно - экономичнее не реверсировать движение (потери на останов/разгон), а сделать лишних n-шагов. Да и само устройство с реверсом вращения обойдется дороже, будет сложнее (как следствие - менее надежно), чем простой привод шагового поворота. ИМХО - вращать только в одну сторону. Много на 5-7 (даже на 15!) лишних шагах не потеряете. Тем более, что очевидна не высокая "скорострельность" устройства.
--------------------
Закономерность: Чем больше узнаю, тем меньше знаю... Любые мнения, даже ошибочные, имеют право на существование. Чем лучше узнаю людей, тем больше нравятся собаки...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|