Очень быстрый умножитель импульсов (умножитель частоты)
- Войдите на сайт для отправки комментариев
Чт, 05/06/2014 - 21:32
Коллеги - требуется очень быстро (вход макс частота ~10кГц, ширина имульса ~5мкс) увеличить частоту импульсов на выходе, и посколько это импульсы шагов для ШД, то требуется произвести умножение очень пропорционально, при этом частота входящих импульсов категорически нелинейна.
Получившийся у меня код выполняется не очень быстро и может пропустить импульс, кроме того на длинных разгонах склонен к переполнению.
Прошу помощи зала в ускорении кода и поиске ошибок, я как мог подробно прокомментировал код, но если что непонятно - постараюсь объяснить в комментариях.
#define LED 17 #define DIV 4 // Кол-во микроимпульсов #define INP PINC // Порт входящих импульсов #define OUT PORTF // Порт исходящих импульсов #define MAX 12000 // Максимальное время ожидания импульса void setup(){ /* Инициализация портов */ DDRF = B11111111; PORTF = B11111111; DDRC = B10111111; /* Таймер1 для подсчета временных интервалов между входящими импульсами */ TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B |= (1 << CS10); TCCR1B |= (1 << CS11); TCCR1B |= (0 << CS12); /* Таймер3 для исходящих импульсов */ TCCR3A = 0; TCCR3B = 0; TCNT3 = 0; TCCR3B |= (1 << CS10); TCCR3B |= (1 << CS11); TCCR3B |= (0 << CS12); Serial.begin(9600); } void loop(){ uint8_t inpValPre = 0b11111111; // Для хранения текущего состояние порта uint8_t inpValCur = 0b11111111; // Для хранения предыдущего состояние порта uint8_t inpRun = false; // Индикатор состояния серии импульсов uint8_t inpBufCnt = 0; // Входящий индекс буфера uint16_t inpBuf[256] = {0}; // Буфер для хранения временни импульсов uint8_t outRun = 0; // Индикатор состояния выхода uint8_t outDiv = 0; // Счетчик выполненных дроблений uint8_t outCnt = 0; // Исходящий индекс буфера uint8_t ovrCnt = 0; // Счетчик переполнения буфера /* Для ровного хода импульсов прерывания лучше выключить, однако теперь плата будет доступна только в момент загрузчика, сразу после загрузчика контроллер уйдетт в автономку и в этом состояниии его по юсб не прошить, т.е. придется ловить загрузчик */ //noInterrupts(); /* Лучше из loop не выходить, большие накладные расходы */ run: //PORTD = 0b00000000; // Для оценки времени исполнения по осцилу /* Считываем состояние входа, если пришел первый импульс - обнуляем таймер1 и продолжаем, если пришел следующий импульс - делим полученное время таймера1 и сохраняем значение в буфер Я пробовал реализовать этот кусок на прерываниях но это ничего по времени не дает */ inpValCur = INP; if(inpValCur == 0b00000000 && inpValPre == 0b01000000){ if(inpRun){ inpBuf[inpBufCnt++] = TCNT1 / DIV; // Используем переполнения для организации циклического буфера TCNT1 = 0; if(ovrCnt++ == 255) goto dbg; // Увеличим счетчик переполнения и если перепонение достигнуто - выпадем в дебаг // if(ovrCnt++ == 255) goto rst; // или сбросим счетчики и продолжим }else{ TCNT1 = 0; inpRun = true; } } inpValPre = inpValCur; /* Проверяем закончилась ли серия импульсов, если время импульса превышено - записываем значение в буфер, если нет - продолжаем */ if(inpRun){ if(TCNT1 >= MAX){ inpBuf[inpBufCnt++] = MAX / DIV; if(ovrCnt++ == 255) goto dbg; // goto rst; inpBuf[inpBufCnt] = 0; // Обнуляем значение следующего элемента inpRun = false; } } /* Формируем начало импульса, если в буфере не нулевое значение - устанаваливаем уровень на выходе, обнуляем таймер и устанаваливаем признак импульса */ if(inpBuf[outCnt]){ /* Если имеется признак импульса - устанавливаем уровень на выходе, и если время импульса истекло - формируем окончание импульса */ if(outRun){ //if(TCNT3 >= 2) OUT = 0b11111111; // Pulse width ~10us OUT = 0b11111111; if(TCNT3 >= inpBuf[outCnt]){ if(outDiv == DIV){ outDiv = 0; outCnt++; ovrCnt--; // Уменьшаем счетчик переполнения }else{ outDiv++; } outRun = false; } }else{ OUT = 0b00000000; TCNT3 = 0; outRun = true; } } //PORTD = 0b11111111; goto run; rst: outCnt = inpBufCnt; outDiv = 0; goto run; dbg: Serial.println("DBG"); Serial.print("Inp count: "); Serial.println(inpBufCnt, DEC); Serial.print("Out count: "); Serial.println(outCnt, DEC); Serial.print("Ovr count: "); Serial.println(ovrCnt, DEC); for(byte b = 0; b < 255; b++){ Serial.print(b, DEC); Serial.print("\t"); Serial.println(inpBuf[b], DEC); } while(1){ digitalWrite(LED, HIGH); delay(250); digitalWrite(LED, LOW); delay(250); }; }
по моемому соосно с шаговиком енкодер от мышки одевали где-то в принтерах - это подешевле
то есть ты хочешь знать точное положение руки робота?
да от шаговика импульсы не ровно валят он же индуктвиность черт ее побери
может не стоит бороться с ней
черт с ней
а соосно устройтсво проверренных импульсов одевать?
в мышках шарик проскальзывал и его заменили на енкодеры и мы все успокоились
art100, импульсы идут с компа на драйвер ШД, соответственно это управляющие импульсы step (не импульсы с энкодера).
Поскольку обычный комп не может нормально генерировать импульсы быстрее 65кГц (да что там, он и >25кГц генерирует кое-как), а я бы хотел 5000мм\мин при 5000шаг\об, получилась такая идея - увеличить частоту ардуинкой. Но что-то с алгоритмом не выходит никак.
интересно интересно 5000 шагов на оборот
а если по тупому отладить вылизать код на родных 16мгц а потом по тупому выдирать кварци допустим ровно в два раза 32 втыкать
может атмел теперь процы подразогнал по чуток
я так на мегах 8 делал только они больше 20 уже не хотели трястись
кнопку турбо никто не отменял
но на шаговиках нужно четко ровно кратно это делать
этож сколько механики не надо делать будет
вствки в кажды мотор по 20$ и станок в два раза шустрей детали выдает - мечта
Lisec это делает механикой за ооочень большие деньги
Ну вот если на 16МГц ничего не придумается, буду на дуе на 84 пробовать.
У Геко есть такие умножители по 35$, только они на плиске или на фпга, возможно там какой-то вариант фапч реализован.
Ну вот если на 16МГц ничего не придумается, буду на дуе на 84 пробовать.
У Геко есть такие умножители по 35$, только они на плиске или на фпга, возможно там какой-то вариант фапч реализован.
а сылочку можно
я совсем не в теме
Gecko G901X
Вот еще отечественный вариант на 4 оси на двух кортексах
И мне не столько скорость важна, хотя ее хотелось бы не потерять, а именно большой микрошаг, т.е. громкость и плавность перемещения.
а у тебя C:\Mach3\ ?
Mach3 да и linuxcnc тоже
Mach3 да и linuxcnc тоже
я его так и не попробовал
дальше светодиодов за 2 месяца не прошел так и светят под столом
меня что-то на g-code торкнуло
а mach3 какой-нибудь g-code поинмает или у него свое что-то
о открыл понимает
Мач3 - да, ж-код понимает. Может даже на 100кГц импульсы выдавать, если железо позволит (у меня на >65 рандомно вешается)
тебе заказали или для себя умножители
а за 24$ подходят?
Она работает путем синтеза полным шагом, половиной шага, 5-microstep или 10-microstep пульс на основе перемычки; это означает, что диск подключен еще microstep плавность, с возможностью выбора разрешения.
переводы веселые
Gecko G213V вампир Шаговым приводом
а вот и енкоды
а вот и то что искал
Mach3 Licence File
Retail Price: US$149.90
Для себя. Геко скорее всего подойдет, тут я только по их описанию предположить могу. Но это только на одну ось, а нужно 4, ну и готовый моушн-контроллер у меня в пути уже, а интереснее свое написать.
интересно
у меня два станка
деталь обьемом со спичечный коробок это 2 часа времени
контроллеры на них g-code разжовывают эти
софта в принципе гиги
но ближе всего мне этот оказался D:\Printrun\
понимаю это совсем другая религия
но твои умножители думаю тоже вполне могут разогнать так сказать аппаратным решением но без механики
станки по 1500$ и 1300$
вкинуть 80$ чудо-коробченок чтобы чтобы чуток пошустрей были вполне реально
собственно только по этому здесь тусуюсь
щас глянул ужастнулся под теметику станка ЧПУ за 100 гигабайт информации
жуть
нашел чудо которое реально g-code понимает
смотри кино у меня только два дрйвера свободных оказалось
щас кино со стола сделаю и ссылку слеплю на кино
твои девайсы как милые туда тоже применимы
В железе (помню без подробностей) работало ГУН, счетчик-делитель и ФД.
Первоначально я этот вариант отбросил как слишком накладный, но видимо ошибался. Вот такой вариант работает гораздо стабильнее - расчитать и записать умноженные шаги сразу в буфер, это значительно увеличивает размер буфера, однако на скорости алгоритма практически не отражается - 555кГц на холостом ходу и 333кГц при входящем сигнале, что впринципе укладывается в ширину импульса 5мкс и пропусков быть не должно.
Тестовый прогон на 10 метров в дебаг не выпал и генерировал шаги довольно ровно. Блин, не может быть что все так просто, может я где ошибку не вижу?