Технический форум по робототехнике.
CiSi » 23 янв 2012, 16:55
Есть 24 битный беззнаковый счетчик, считает он импульсы энкодера. проблемма в том что если значение счетчика 0 то при реверсе он считает не в отрицательную сторону, а вычитает из своего максимального значения. Собственно требуется получить на выходе знаковое значение.
сейчас у меня реализовано следующим образом:
- Код: Выделить всё • Развернуть
procedure ReadMoving(K: double; var Moving: double);
begin
if directionTop = 1 then //прибавляем
begin
Moving:=Moving+((Encoder-bufer)/K);
Bufer:= Encoder;
end;
if directionBottom = 1 then // вычитаем
begin
Moving:=Moving+((Bufer-(16777215-Encoder))/K);
Bufer:= 16777215-Encoder;
end;
end;
После каждой смены направления движения счетчик обнуляется (переменная Encoder).
Добавлено спустя 1 минуту 28 секунд:K это коэффициент для перевода импульсов в мм.
boez » 23 янв 2012, 18:40
Да вроде вот так можно:
- Код: Выделить всё • Развернуть
procedure ReadMoving(K: double; var Moving: double);
begin
if directionTop = 1 then //прибавляем
begin
Moving:=Moving+((Encoder-bufer)/K);
Bufer:= Encoder;
end;
if directionBottom = 1 then // вычитаем
begin
Moving:=Moving-((Encoder-Buffer)/K);
Bufer:= Encoder;
end;
end;
Кстати, в этом варианте вроде даже не надо обнулять Encoder и Buffer при реверсе. Еще возможно надо добавить обрезку до 24 бит, если реальные encoder и buffer 32-битные:
- Код: Выделить всё • Развернуть
Moving:=Moving+(((Encoder-bufer)&0xffffff)/K)
CiSi » 23 янв 2012, 19:10
Так не получилось
Добавлено спустя 5 минут 22 секунды:так как у меня сейчас реализованно конечно работает, но мне почемуто не нравится, считаю что какойто кривой код.
boez » 23 янв 2012, 19:11
Странно, а почему? Вроде должно. Вообще, сами переменные Encoder и bufer какого типа и разрядности?
CiSi » 23 янв 2012, 19:30
Encoder и bufer типа double
Добавлено спустя 2 минуты 54 секунды:
поменял на тип real с меньшей разрядностью, работает так же.
boez » 23 янв 2012, 19:57
Стоп, я кажись немного неправильно телепатировал что такое переменная Encoder
![Smile :)](http://roboforum.ru/images/smilies/smile.gif)
Это в твоей проге счетчик (тогда почему он именно 24-битный, сделай целым 32-битным и забудь про переполнения, они сами отрабатывать будут) или откуда-то число приходит, по каналу связи или еще как? Что делается с самой переменной encoder при вращении назад - она увеличивается или уменьшается?
Добавлено спустя 11 минут 13 секунд:Все, я присмотрелся внимательнее к твоей первой проге, похоже что encoder считает таки сразу с направлением (поправь, если не так). Тогда, если уж тебе надо чтоб он был именно 24-битным, то делай так:
- Код: Выделить всё • Развернуть
procedure ReadMoving(K: double; var Moving: double);
begin
Moving:=Moving+(((Encoder-Bufer)shl 8)shr 8)/K);
Bufer:= Encoder;
end;
Encoder и Bufer типа integer (машина 32-битная, я полагаю?), за синтаксические ошибки не пинать, я на паскале писал давно и неправду
![Smile :)](http://roboforum.ru/images/smilies/smile.gif)
CiSi » 23 янв 2012, 21:54
счетчик этот аппаратный он 24 битный, опрашивается при помощи процедуры и передает своё значение в переменную encoder. при реверсе значение уменьшается, но при переходе через ноль оно становится не отрицательным, а уменьшается от максимального значения (16777215)
dccharacter » 23 янв 2012, 23:22
Так что такое "отрицательное значение" по-твоему? Чем отличается, допустим, signed char и unsigned char? Каждый из них принимает значение от 0b00000000 до 0b11111111. Но чем они отличаются?
CiSi » 23 янв 2012, 23:57
Тип char может быть знаковым и беззнаковым. Обозначается, соответственно, как "signed char" (знаковый тип) и "unsigned char" (беззнаковый тип). Знаковый тип может хранить значения в диапазоне от -128 до +127. Беззнаковый - от 0 до 255.
dccharacter » 24 янв 2012, 00:11
Супер, а теперь сделай следующий шаг - переведи все числа, которые ты написал, в бинарный вид.
Michael_K » 24 янв 2012, 00:53
dccharacter, проблема в том, что
в си в паскале
![Smile :)](http://roboforum.ru/images/smilies/smile.gif)
нету натурального типа для 24-битных значений.
CiSi, вам можно попробовать расширять знак.
Если старший (23-й) бит счетчика равен единице, то нужно старший ("лишний") байт (с 24-го по 31-й бит) поставить во "все единицы". Тогда результат будет меняться от 8млн до -8млн (точно лень считать).
Паскаль не знаю.
Добавлено спустя 3 минуты 35 секунд:А boez хорошо написал - он вообще честно расширил счетчик. До полных значащих 32-х бит.
dccharacter » 24 янв 2012, 01:52
нету - так можно отдельную переменную для знака ввести
![Smile :-)](http://roboforum.ru/images/smilies/smile.gif)
В каком-то аппноуте от микрочипа (кажися про ПИД и маятник) используется то ли ниббл, то ли байт для обозначения знака.
Ну или я не догоняю в чем проблема.
А еще я бы не переводил все постоянно в миллиметры, а считал в попугаях.
Добавлено спустя 21 минуту 31 секунду:Вместо вот этого: "После каждой смены направления движения счетчик обнуляется (переменная Encoder)."
сделай вот это: "при прохождении нуля знак меняется на противоположный"
Добавлено спустя 8 минут 21 секунду:Или еще проще. Не обнуляй счетчик, а присваивай ему значение 0x100000. Соответственно твое знаковое будет (Encoder - 0x100000). Т.е. ноль у тебя - и не ноль вовсе
![Smile :-)](http://roboforum.ru/images/smilies/smile.gif)
boez » 24 янв 2012, 02:20
dccharacter писал(а):Или еще проще. Не обнуляй счетчик, а присваивай ему значение 0x100000. Соответственно твое знаковое будет (Encoder - 0x100000). Т.е. ноль у тебя - и не ноль вовсе
![Smile :-)](http://roboforum.ru/images/smilies/smile.gif)
Так прикол счетчика CiSi в том, что он не может ему ничего присвоить. Он его только читает - затем и введена переменная Bufer.
Короче, так как я написал должно работать, я вначале неправильно написал, потому что исходил из гипотезы, что энкодер считает всегда в плюс (не квадратурный, а одноканальный), а знак ему надо добавить вручную, исходя из неких флагов направления вращения. А раз энкодер честный - нужно именно сделать знаковое расширение разности (enc-buf) с 24 до 32 бит. 32 бита со знаком в обычном паскале для 32-разрядного x86 представлен типом integer. Это можно делать ручками через байты, как написал Michael_K, и паскаль даже позволяет такие манипуляции при помощи наложения памяти (absolute), но ИМХО сдвигами проще. Результат 100% идентичен - младшие 24 бита сохраняются полностью, а старшие (24-31) делаются все равны 23-му биту. В формате знакового целого это соответствует -0x00800000...0x007fffff, что и требовалось.
Добавлено спустя 3 минуты 20 секунд:А, стоп, вроде правда пишет что может обнулять. Но все равно вписывать 0x100000 не поможет - а если направление вращения не сменится? Через 0x100001 тиков вращения назад все равно перескочит с нуля на 0xffffff. Надо именно получить 24-битную разность со знаком - и тогда все будет ОК само, без никаких проверок.
CiSi » 24 янв 2012, 10:21
Наврал - переменная Encoder типа cardinal (беззнаковый). Прошу прошения.
Так как я получаю значение с аппаратного счетчика, то задать ему какоето значение нельзя, переменной конечно можно но не увидел в этом смысла. Счетчик можно только обнулить. Четкое отслеживание нуля то же не увенчалось успехом, после чего осталось значение счетчика привязать к направлению вращения энкодера. И при каждой смене направления (движение в ту или иную сторону) сначало обнуляю счетчик и он считает от нуля.
Michael_K, если я вас правильно понял, то в таком случае нулевое значение счетчика будет соответствовать -8388607 знаковой 24 битной пременной.
Romikgy » 24 янв 2012, 11:21
- Код: Выделить всё • Развернуть
if Bufer>$7fffff then
begin
Bufer:=-(Bufer-$7fffff);
end;
а так не проще?