Команда смены инструмента как в фануке.

Обсуждение установки, настройки и использования LinuxCNC. Вопросы по Gкоду.
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Команда смены инструмента как в фануке.

Сообщение Lexxa »

в примерах конфигов есть axis-fanuchy
Типа смена инструмента как в фануке. Работает криво. Задался целью исправить.
An example of combining the G43.2 compound offset idea with remapping to create
a toolchange similar to Fanuc.

T1 = select and load tool 1, and apply the base offset for tool 1
T0101 = select and load tool 1 and apply offsets 1 and 10001
T0201 = select and load tool 1 and apply offsets 1 and 10002

This might not exactly match Fanuc, but the behaviour is easy to change
by editing toolchange.ngc
Должно работать так:
T0101 - первый инструмент, первый корректор,
T0102 - первый инструмент, второй корректор,
T0308 - третий инструмент, восьмой корректор.

На сколько я понимаю все делается в куске кода

Код: Выделить всё

O<toolchange> sub
(debug, Tool requested = #<tool>)
#<wear> = [10000 + FIX[ #<tool>  / 100]]
#<tool> = [#<tool> MOD 100]
M6 T#<tool>
G43 H#<tool>
O100 IF [#<wear> GT 10000]
    G43.2 H#<wear>
O100 ENDIF
#<pocket> = #<tool>
(debug, tool = #<tool> wear = #<wear>)
O<toolchange> endsub [0]
Пока только разбираюсь, но уже есть вопросы.
Переделал указанный код на такой:

Код: Выделить всё

O<toolchange> sub
#<wear> = [#<tool>  MOD 100]
#<tool> = [#<tool> / 100]
#<tool-n> = FIX[#<tool>]
(debug, Tool requested = #<tool-n> Wear requested = #<wear>)
T#<tool-n>
M6
G43 H#<wear>
#<pocket> = #<tool>
(debug, Tool=#5400  OffsetX=#5401 OffsetZ=#5402 ToolDiameter=#5410 Orient = #5413)
O<toolchange> endsub [0]
Результат. Корректоры вроде как применяются правильно, но не применяется диаметр инструмента, передний и задний угол и ориентация.
Эти параметры меняются только если менять инструмент на другой, т.е.
при отработке
Т0101
Т0201
Оффсеты поменяются правильно, а вот ориентация, диаметр и углы - нет.

Как починить косяк с углами?
:bender:
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение nkp »

Lexxa писал(а):axis-fanuchy
где это найти??
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Lexxa »

в выборе конфигов.
Вложения
lathe-fanucy.zip
(10.93 КБ) 503 скачивания
:bender:
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение nkp »

ты куски кода в первом посте наверно перепутал местами?
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Lexxa »

nkp писал(а):
ты куски кода в первом посте наверно перепутал местами?
нет.
почему ты так решил? я скинул уже правленный
:bender:
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение nkp »

Lexxa писал(а):я скинул уже правленный
ну вот это меня и сбило с толку...
просто у меня нет такого конфига (хоть и несколько сборок стоят 2.7.)
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Lexxa »

хочется вылечить косячек)
:bender:
Аватара пользователя
PKM
Почётный участник
Почётный участник
Сообщения: 4263
Зарегистрирован: 31 мар 2011, 18:11
Репутация: 705
Настоящее имя: Андрей
Откуда: Украина
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение PKM »

А что делает #<pocket>?
Аватара пользователя
PKM
Почётный участник
Почётный участник
Сообщения: 4263
Зарегистрирован: 31 мар 2011, 18:11
Репутация: 705
Настоящее имя: Андрей
Откуда: Украина
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение PKM »

nkp писал(а):просто у меня нет такого конфига (хоть и несколько сборок стоят 2.7.)
sim/axis/lathe.fanucy

У меня вообще не запускается, то ошибки хал, то еще что...
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение nkp »

PKM писал(а):А что делает #<pocket>?
наверно это отсюда:
(для просмотра содержимого нажмите на ссылку)

Код: Выделить всё

# stdglue - canned prolog and epilog functions for the remappable builtin codes (T,M6,M61,S,F)
#
# we dont use argspec to avoid the generic error message of the argspec prolog and give more
# concise ones here


# cycle_prolog,cycle_epilog: generic code-independent support glue for oword sub cycles
#
# these are provided as starting point - for more concise error message you would better
# write a prolog specific for the code
#
# Usage:
#REMAP=G84.3  modalgroup=1 argspec=xyzqp prolog=cycle_prolog ngc=g843 epilog=cycle_epilog


import emccanon 
from interpreter import *
throw_exceptions = 1

# REMAP=S   prolog=setspeed_prolog  ngc=setspeed epilog=setspeed_epilog
# exposed parameter: #<speed>

def setspeed_prolog(self,**words):
    try:
        c = self.blocks[self.remap_level]
        if not c.s_flag:
            self.set_errormsg("S requires a value") 
            return INTERP_ERROR
        self.params["speed"] = c.s_number
    except Exception,e:
        self.set_errormsg("S/setspeed_prolog: %s)" % (e))
        return INTERP_ERROR
    return INTERP_OK

def setspeed_epilog(self,**words):
    try:
        if not self.value_returned:
            r = self.blocks[self.remap_level].executing_remap
            self.set_errormsg("the %s remap procedure %s did not return a value"
                             % (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
            return INTERP_ERROR
        if self.return_value < -TOLERANCE_EQUAL: # 'less than 0 within interp's precision'
            self.set_errormsg("S: remap procedure returned %f" % (self.return_value)) 
            return INTERP_ERROR
        if self.blocks[self.remap_level].builtin_used:
            pass
            #print "---------- S builtin recursion, nothing to do"
        else:
            self.speed = self.params["speed"]
            emccanon.enqueue_SET_SPINDLE_SPEED(self.speed)
        return INTERP_OK
    except Exception,e:
        self.set_errormsg("S/setspeed_epilog: %s)" % (e))
        return INTERP_ERROR
    return INTERP_OK    

# REMAP=F   prolog=setfeed_prolog  ngc=setfeed epilog=setfeed_epilog
# exposed parameter: #<feed>

def setfeed_prolog(self,**words):
    try:
        c = self.blocks[self.remap_level]
        if not c.f_flag:
            self.set_errormsg("F requires a value") 
            return INTERP_ERROR
        self.params["feed"] = c.f_number
    except Exception,e:
        self.set_errormsg("F/setfeed_prolog: %s)" % (e))
        return INTERP_ERROR
    return INTERP_OK    

def setfeed_epilog(self,**words):
    try:
        if not self.value_returned:
            r = self.blocks[self.remap_level].executing_remap
            self.set_errormsg("the %s remap procedure %s did not return a value"
                             % (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
            return INTERP_ERROR
        if self.blocks[self.remap_level].builtin_used:
            pass
            #print "---------- F builtin recursion, nothing to do"
        else:
            self.feed_rate = self.params["feed"]
            emccanon.enqueue_SET_FEED_RATE(self.feed_rate)
        return INTERP_OK
    except Exception,e:
        self.set_errormsg("F/setfeed_epilog: %s)" % (e))
        return INTERP_ERROR
    return INTERP_OK    


# REMAP=T   prolog=prepare_prolog ngc=prepare epilog=prepare_epilog
# exposed parameters: #<tool> #<pocket>

def prepare_prolog(self,**words):
    try:
        cblock = self.blocks[self.remap_level]
        if not cblock.t_flag:
            self.set_errormsg("T requires a tool number")
            return INTERP_ERROR
        tool  = cblock.t_number
        if tool:
            (status, pocket) = self.find_tool_pocket(tool)
            if status != INTERP_OK:
                self.set_errormsg("T%d: pocket not found" % (tool))
                return status
        else:
            pocket = -1 # this is a T0 - tool unload
        self.params["tool"] = tool
        self.params["pocket"] = pocket
        return INTERP_OK
    except Exception, e:
        self.set_errormsg("T%d/prepare_prolog: %s" % (int(words['t']), e))
        return INTERP_ERROR

def prepare_epilog(self, **words):
    try:
        if not self.value_returned:
            r = self.blocks[self.remap_level].executing_remap
            self.set_errormsg("the %s remap procedure %s did not return a value"
                             % (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
            return INTERP_ERROR
        if self.blocks[self.remap_level].builtin_used:
            #print "---------- T builtin recursion, nothing to do"
            return INTERP_OK
        else:
            if self.return_value > 0:
                self.selected_tool = int(self.params["tool"])
                self.selected_pocket = int(self.params["pocket"])
                emccanon.SELECT_POCKET(self.selected_pocket, self.selected_tool)
                return INTERP_OK
            else:
                self.set_errormsg("T%d: aborted (return code %.1f)" % (int(self.params["tool"]),self.return_value))
                return INTERP_ERROR
    except Exception, e:
        self.set_errormsg("T%d/prepare_epilog: %s" % (tool,e))
        return INTERP_ERROR       

# REMAP=M6  modalgroup=6 prolog=change_prolog ngc=change epilog=change_epilog
# exposed parameters:
#    #<tool_in_spindle>
#    #<selected_tool>
#    #<current_pocket>
#    #<selected_pocket>

def change_prolog(self, **words):
    try:
        # this is relevant only when using iocontrol-v2.
        if self.params[5600] > 0.0:
            if self.params[5601] < 0.0:
                self.set_errormsg("Toolchanger hard fault %d" % (int(self.params[5601])))
                return INTERP_ERROR
            print "change_prolog: Toolchanger soft fault %d" % int(self.params[5601])
            
	if self.selected_pocket < 0:
            self.set_errormsg("M6: no tool prepared")
            return INTERP_ERROR
	if self.cutter_comp_side:
            self.set_errormsg("Cannot change tools with cutter radius compensation on")
            return INTERP_ERROR
	self.params["tool_in_spindle"] = self.current_tool
	self.params["selected_tool"] = self.selected_tool
	self.params["current_pocket"] = self.current_pocket # this is probably nonsense
        self.params["selected_pocket"] = self.selected_pocket
        return INTERP_OK
    except Exception, e:
        self.set_errormsg("M6/change_prolog: %s" % (e))
        return INTERP_ERROR
    
def change_epilog(self, **words):
    try:
        if not self.value_returned:
            r = self.blocks[self.remap_level].executing_remap
            self.set_errormsg("the %s remap procedure %s did not return a value"
                             % (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
            return INTERP_ERROR
        # this is relevant only when using iocontrol-v2.
        if self.params[5600] > 0.0:
            if self.params[5601] < 0.0:
                self.set_errormsg("Toolchanger hard fault %d" % (int(self.params[5601])))
                return INTERP_ERROR
            print "change_epilog: Toolchanger soft fault %d" % int(self.params[5601])

        if self.blocks[self.remap_level].builtin_used:
            #print "---------- M6 builtin recursion, nothing to do"
            return INTERP_OK
        else:
            if self.return_value > 0.0:
                # commit change
                self.selected_pocket =  int(self.params["selected_pocket"])
                emccanon.CHANGE_TOOL(self.selected_pocket)
                self.current_pocket = self.selected_pocket
                self.selected_pocket = -1
                self.selected_tool = -1
                # cause a sync()
                self.set_tool_parameters()
                self.toolchange_flag = True
                return INTERP_EXECUTE_FINISH
            else:
                self.set_errormsg("M6 aborted (return code %.1f)" % (self.return_value))
                return INTERP_ERROR
    except Exception, e:
        self.set_errormsg("M6/change_epilog: %s" % (e))
        return INTERP_ERROR

# REMAP=M61  modalgroup=6 prolog=settool_prolog ngc=settool epilog=settool_epilog
# exposed parameters: #<tool> #<pocket>

def settool_prolog(self,**words):
    try:
        c = self.blocks[self.remap_level]
        if not c.q_flag:
            self.set_errormsg("M61 requires a Q parameter") 
            return INTERP_ERROR
        tool = int(c.q_number)
        if tool < -TOLERANCE_EQUAL: # 'less than 0 within interp's precision'
            self.set_errormsg("M61: Q value < 0") 
            return INTERP_ERROR
        (status,pocket) = self.find_tool_pocket(tool)
        if status != INTERP_OK:
            self.set_errormsg("M61 failed: requested tool %d not in table" % (tool))
            return status
        self.params["tool"] = tool
        self.params["pocket"] = pocket
        return INTERP_OK
    except Exception,e:
        self.set_errormsg("M61/settool_prolog: %s)" % (e))
        return INTERP_ERROR

def settool_epilog(self,**words):
    try:
        if not self.value_returned:
            r = self.blocks[self.remap_level].executing_remap
            self.set_errormsg("the %s remap procedure %s did not return a value"
                             % (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
            return INTERP_ERROR

        if self.blocks[self.remap_level].builtin_used:
            #print "---------- M61 builtin recursion, nothing to do"
            return INTERP_OK
        else:
            if self.return_value > 0.0:
                self.current_tool = int(self.params["tool"])
                self.current_pocket = int(self.params["pocket"])
                emccanon.CHANGE_TOOL_NUMBER(self.current_pocket)
                # cause a sync()
                self.tool_change_flag = True
                self.set_tool_parameters()
            else:
                self.set_errormsg("M61 aborted (return code %.1f)" % (self.return_value))
                return INTERP_ERROR
    except Exception,e:
        self.set_errormsg("M61/settool_epilog: %s)" % (e))
        return INTERP_ERROR

# educational alternative: M61 remapped to an all-Python handler
# demo - this really does the same thing as the builtin (non-remapped) M61
#
# REMAP=M61 modalgroup=6 python=set_tool_number

def set_tool_number(self, **words):
    try:
        c = self.blocks[self.remap_level]
        if c.q_flag:
            toolno = int(c.q_number)
        else:
            self.set_errormsg("M61 requires a Q parameter")
            return status 
	(status,pocket) = self.find_tool_pocket(toolno)
	if status != INTERP_OK:
            self.set_errormsg("M61 failed: requested tool %d not in table" % (toolno))
            return status
	if words['q'] > -TOLERANCE_EQUAL: # 'greater equal 0 within interp's precision'
            self.current_pocket = pocket
            self.current_tool = toolno
            emccanon.CHANGE_TOOL_NUMBER(pocket)
            # cause a sync()
            self.tool_change_flag = True
            self.set_tool_parameters()
            return INTERP_OK
	else:
            self.set_errormsg("M61 failed: Q=%4" % (toolno))
            return INTERP_ERROR
    except Exception, e:
        self.set_errormsg("M61/set_tool_number: %s" % (e))
        return INTERP_ERROR


_uvw = ("u","v","w","a","b","c")
_xyz = ("x","y","z","a","b","c")
# given a plane, return  sticky words, incompatible axis words and plane name
# sticky[0] is also the movement axis
_compat = {
    emccanon.CANON_PLANE_XY : (("z","r"),_uvw,"XY"),
    emccanon.CANON_PLANE_YZ : (("x","r"),_uvw,"YZ"),
    emccanon.CANON_PLANE_XZ : (("y","r"),_uvw,"XZ"),
    emccanon.CANON_PLANE_UV : (("w","r"),_xyz,"UV"),
    emccanon.CANON_PLANE_VW : (("u","r"),_xyz,"VW"),
    emccanon.CANON_PLANE_UW : (("v","r"),_xyz,"UW")}           

# extract and pass parameters from current block, merged with extra paramters on a continuation line
# keep tjose parameters across invocations
# export the parameters into the oword procedure
def cycle_prolog(self,**words):
    # self.sticky_params is assumed to have been initialized by the
    # init_stgdlue() method below
    global _compat
    try:    
        # determine whether this is the first or a subsequent call
        c = self.blocks[self.remap_level]
        r = c.executing_remap
        if c.g_modes[1] == r.motion_code:
            # first call - clear the sticky dict
            self.sticky_params[r.name] = dict()

        self.params["motion_code"] = c.g_modes[1]
        
        (sw,incompat,plane_name) =_compat[self.plane]
        for (word,value) in words.items():
            # inject current parameters
            self.params[word] = value
            # record sticky words
            if word in sw:
                if self.debugmask & 0x00080000: print "%s: record sticky %s = %.4f" % (r.name,word,value)
                self.sticky_params[r.name][word] = value
            if word in incompat:
                return "%s: Cannot put a %s in a canned cycle in the %s plane" % (r.name, word.upper(), plane_name)

        # inject sticky parameters which were not in words:
        for (key,value) in self.sticky_params[r.name].items():
            if not key in words:
                if self.debugmask & 0x00080000: print "%s: inject sticky %s = %.4f" % (r.name,key,value)
                self.params[key] = value

        if not "r" in self.sticky_params[r.name]:
            return "%s: cycle requires R word" % (r.name)
        else:
            if self.sticky_params[r.name] <= 0.0:
                return "%s: R word must be > 0 if used (%.4f)" % (r.name, words["r"])

        if "l" in words:
            # checked in interpreter during block parsing
            # if l <= 0 or l not near an int
            self.params["l"] = words["l"]
            
        if "p" in words:
            p = words["p"]
            if p < 0.0:
                return "%s: P word must be >= 0 if used (%.4f)" % (r.name, p)
            self.params["p"] = p

        if self.feed_rate == 0.0:
            return "%s: feed rate must be > 0" % (r.name)
        if self.feed_mode == INVERSE_TIME:
            return "%s: Cannot use inverse time feed with canned cycles" % (r.name)
        if self.cutter_comp_side:
            return "%s: Cannot use canned cycles with cutter compensation on" % (r.name)
        return INTERP_OK
    
    except Exception, e:
        raise
        return "cycle_prolog failed: %s" % (e)

# make sure the next line has the same motion code, unless overriden by a
# new G code
def cycle_epilog(self,**words):
    try:
        c = self.blocks[self.remap_level]
        self.motion_mode = c.executing_remap.motion_code # retain the current motion mode
        return INTERP_OK
    except Exception, e:
        return "cycle_epilog failed: %s" % (e)


# this should be called from TOPLEVEL __init__()
def init_stdglue(self):
    self.sticky_params = dict()
Аватара пользователя
PKM
Почётный участник
Почётный участник
Сообщения: 4263
Зарегистрирован: 31 мар 2011, 18:11
Репутация: 705
Настоящее имя: Андрей
Откуда: Украина
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение PKM »

Мда... дело темное. Скорее всего проблема именно здесь
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение nkp »

Lexxa писал(а):а вот ориентация, диаметр и углы - нет.
а так разве не правильно работает:
Выделение_066.png (6653 просмотра) <a class='original' href='./download/file.php?id=36262&mode=view' target=_blank>Загрузить оригинал (162.73 КБ)</a>
Выделение_067.png (6653 просмотра) <a class='original' href='./download/file.php?id=36263&mode=view' target=_blank>Загрузить оригинал (132.56 КБ)</a>
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Lexxa »

nkp, то что вылезает в сообщениях, там вообще бред.
Посмотри, какого хрена offsetZ= офсету Y из таблицы. вто время, как на самом деле офсеты прикручиваются правильно.
Сделай три оддинаковых инструмента, но с разной ориентацией и выполни
Т0101
Т0102
Т0103
В гремлине поставь галку смотреть офстеты и посмотри на расположене резца - не поменяется оно относительно крестка. Мало тогоесли делать разные углы и углы не поменяются.
А вот если выполнить
Т0101
Т0202
Т0303, то все будет меняться.
Поэтому работает неправильно.
:bender:
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение nkp »

у нас в принципе три активные команды:

Код: Выделить всё

T#<tool-n>
M6
G43 H#<wear>
с T#<tool-n> и М6 все ясно...
остается G43:
она применяет к выбраному инструменту соответственный оффсет по Z и X
и больше ничего вроде бы...
почему должна меняться ориентация ??
имхо - никаких косяков нет ...

===========
Аватара пользователя
Nick
Мастер
Сообщения: 22776
Зарегистрирован: 23 ноя 2009, 16:45
Репутация: 1735
Заслуга: Developer
Откуда: Gatchina, Saint-Petersburg distr., Russia
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Nick »

Lexxa писал(а):В гремлине поставь галку смотреть офстеты и посмотри на расположене резца - не поменяется оно относительно крестка. Мало тогоесли делать разные углы и углы не поменяются.
А елси сдеать перемещение? Может они не меняются до первгого перемещения? Как с радиусом?
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Lexxa »

nkp писал(а):почему должна меняться ориентация ??
потому что она меняется когда первый раз применяешь
:bender:
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Lexxa »

так.
В файле emccanon.cc
имеются нужные вкусные функции:

Код: Выделить всё

/* Tool Functions */

/* this is called with distances in external (machine) units */
void SET_TOOL_TABLE_ENTRY(int pocket, int toolno, EmcPose offset, double diameter,
                          double frontangle, double backangle, int orientation) {
    EMC_TOOL_SET_OFFSET o;
    flush_segments();
    o.pocket = pocket;
    o.toolno = toolno;
    o.offset = offset;
    o.diameter = diameter;
    o.frontangle = frontangle;
    o.backangle = backangle;
    o.orientation = orientation;
    interp_list.append(o);
}
А вот и G43 (для просмотра содержимого нажмите на ссылку)

Код: Выделить всё

int Interp::convert_tool_length_offset(int g_code,       //!< g_code being executed (must be G_43 or G_49)
                                      block_pointer block,      //!< pointer to a block of RS274/NGC instructions
                                      setup_pointer settings)   //!< pointer to machine settings                 
{
  int pocket_number;
  EmcPose tool_offset;
  ZERO_EMC_POSE(tool_offset);

  CHKS((settings->cutter_comp_side),
       (_("Cannot change tool offset with cutter radius compensation on")));
  if (g_code == G_49) {
    pocket_number = 0;
  } else if (g_code == G_43) {
      logDebug("convert_tool_length_offset h_flag=%d h_number=%d toolchange_flag=%d current_pocket=%d\n",
	      block->h_flag,block->h_number,settings->toolchange_flag,settings->current_pocket);
      if(block->h_flag) {
        CHP((find_tool_pocket(settings, block->h_number, &pocket_number)));
    } else if (settings->toolchange_flag) {
        // Tool change is in progress, so the "current tool" is in its
        // original pocket still.
        pocket_number = settings->current_pocket;
    } else {
        // Tool change is done so the current tool is in pocket 0 (aka the
        // spindle).
        pocket_number = 0;
    }
    logDebug("convert_tool_length_offset: using index=%d spindle_toolno=%d pocket_toolno=%d",
	     pocket_number, settings->tool_table[0].toolno,settings->tool_table[settings->current_pocket].toolno);

    tool_offset.tran.x = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.x);
    tool_offset.tran.y = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.y);
    tool_offset.tran.z = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.z);
    tool_offset.a = USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.a);
    tool_offset.b = USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.b);
    tool_offset.c = USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.c);
    tool_offset.u = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.u);
    tool_offset.v = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.v);
    tool_offset.w = USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.w);
  } else if (g_code == G_43_1) {
    tool_offset = settings->tool_offset;
    pocket_number = -1;
    if(block->x_flag) tool_offset.tran.x = block->x_number;
    if(block->y_flag) tool_offset.tran.y = block->y_number;
    if(block->z_flag) tool_offset.tran.z = block->z_number;
    if(block->a_flag) tool_offset.a = block->a_number;
    if(block->b_flag) tool_offset.b = block->b_number;
    if(block->c_flag) tool_offset.c = block->c_number;
    if(block->u_flag) tool_offset.u = block->u_number;
    if(block->v_flag) tool_offset.v = block->v_number;
    if(block->w_flag) tool_offset.w = block->w_number;
  } else if (g_code == G_43_2) {
    CHKS((!block->h_flag), (_("G43.2: H-word missing")));
    CHP((find_tool_pocket(settings, block->h_number, &pocket_number)));
    tool_offset = settings->tool_offset;
    tool_offset.tran.x += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.x);
    tool_offset.tran.y += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.y);
    tool_offset.tran.z += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.tran.z);
    tool_offset.a += USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.a);
    tool_offset.b += USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.b);
    tool_offset.c += USER_TO_PROGRAM_ANG(settings->tool_table[pocket_number].offset.c);
    tool_offset.u += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.u);
    tool_offset.v += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.v);
    tool_offset.w += USER_TO_PROGRAM_LEN(settings->tool_table[pocket_number].offset.w);
  } else {
    ERS("BUG: Code not G43, G43.1, G43.2, or G49");
  }
  USE_TOOL_LENGTH_OFFSET(tool_offset);

  double dx, dy;

  dx = settings->tool_offset.tran.x - tool_offset.tran.x;
  dy = settings->tool_offset.tran.y - tool_offset.tran.y;

  rotate(&dx, &dy, -settings->rotation_xy);

  settings->current_x += dx;
  settings->current_y += dy;
  settings->current_z += settings->tool_offset.tran.z - tool_offset.tran.z;
  settings->AA_current += settings->tool_offset.a - tool_offset.a;
  settings->BB_current += settings->tool_offset.b - tool_offset.b;
  settings->CC_current += settings->tool_offset.c - tool_offset.c;
  settings->u_current += settings->tool_offset.u - tool_offset.u;
  settings->v_current += settings->tool_offset.v - tool_offset.v;
  settings->w_current += settings->tool_offset.w - tool_offset.w;

  settings->tool_offset = tool_offset;
  return INTERP_OK;
}

/****************************************************************************/
Видно, что G43 не изменяет углы и ориентацию, а меняет только сами офсеты, что, собственно говоря, правильно.

А вот почти смена инструмента (для просмотра содержимого нажмите на ссылку)

Код: Выделить всё

/****************************************************************************/

/*! convert_tool_change

Returned Value: int (INTERP_OK)

Side effects:
   This makes function calls to canonical machining functions, and sets
   the machine model as described below.

Called by: convert_m

This function carries out an M6 command, which changes the tool.
If M61 is called, the toolnumber gets changed (without causing an actual toolchange).

When the CHANGE_TOOL call completes, the specified tool should be
loaded.  What this means varies by machine.  According to configuration,
the interpreter may also issue commands to do one or more of the
following things before calling CHANGE_TOOL:

1. stop the spindle
2. move the quill up (Z to machine zero, like G0 G53 Z0)
3. move the axes to reference point #2 (like G30)

Further, the interpreter makes no assumptions about the axis positions
after the tool change completes.  This state is queried and the internal
model is resynched before the program continues.  This means CHANGE_TOOL
itself can also issue motion (and it currently may, according to
configuration).

This implements the "Next tool in T word" approach to tool selection.
The tool is selected when the T word is read (and the carousel may
move at that time) but is changed when M6 is read.

Note that if a different tool is put into the spindle, the current_z
location setting will be incorrect. It is assumed the program will
contain an appropriate USE_TOOL_LENGTH_OFFSET (G43) command before any
subsequent motion.  It is also assumed that the program will restart the
spindle and make new entry moves if necessary.

*/

int Interp::convert_tool_change(setup_pointer settings)  //!< pointer to machine settings
{

  if (settings->selected_pocket < 0) {
    ERS(NCE_TXX_MISSING_FOR_M6);
  }

  CHKS((settings->cutter_comp_side),
       (_("Cannot change tools with cutter radius compensation on")));

  START_CHANGE(); // indicate start of change operation
  if (!settings->tool_change_with_spindle_on) {
      STOP_SPINDLE_TURNING();
      settings->spindle_turning = CANON_STOPPED;
  }

  if (settings->tool_change_quill_up) {
      double up_z;
      double discard;
      find_relative(0., 0., 0., 0., 0., 0., 0., 0., 0., 
                    &discard, &discard, &up_z,
                    &discard, &discard, &discard, 
                    &discard, &discard, &discard,
                    settings);
      COMMENT("AXIS,hide");
      STRAIGHT_TRAVERSE(-1, settings->current_x, settings->current_y, up_z,
                        settings->AA_current, settings->BB_current, settings->CC_current,
                        settings->u_current, settings->v_current, settings->w_current);
      COMMENT("AXIS,show");
      settings->current_z = up_z;
  }

  if (settings->tool_change_at_g30) {
      double end_x;
      double end_y;
      double end_z;
      double AA_end;
      double BB_end;
      double CC_end;
      double u_end;
      double v_end;
      double w_end;

      find_relative(USER_TO_PROGRAM_LEN(settings->parameters[5181]),
                    USER_TO_PROGRAM_LEN(settings->parameters[5182]),
                    USER_TO_PROGRAM_LEN(settings->parameters[5183]),
                    USER_TO_PROGRAM_ANG(settings->parameters[5184]),
                    USER_TO_PROGRAM_ANG(settings->parameters[5185]),
                    USER_TO_PROGRAM_ANG(settings->parameters[5186]),
                    USER_TO_PROGRAM_LEN(settings->parameters[5187]),
                    USER_TO_PROGRAM_LEN(settings->parameters[5188]),
                    USER_TO_PROGRAM_LEN(settings->parameters[5189]),
                    &end_x, &end_y, &end_z,
                    &AA_end, &BB_end, &CC_end, 
                    &u_end, &v_end, &w_end, settings);
      COMMENT("AXIS,hide");

      // move indexers first, one at a time
      if (AA_end != settings->AA_current && settings->a_indexer)
          issue_straight_index(3, AA_end, -1, settings);
      if (BB_end != settings->BB_current && settings->b_indexer)
          issue_straight_index(4, BB_end, -1, settings);
      if (CC_end != settings->CC_current && settings->c_indexer)
          issue_straight_index(5, CC_end, -1, settings);

      STRAIGHT_TRAVERSE(-1, end_x, end_y, end_z,
                        AA_end, BB_end, CC_end,
                        u_end, v_end, w_end);
      COMMENT("AXIS,show");
      settings->current_x = end_x;
      settings->current_y = end_y;
      settings->current_z = end_z;
      settings->AA_current = AA_end;
      settings->BB_current = BB_end;
      settings->CC_current = CC_end;
      settings->u_current = u_end;
      settings->v_current = v_end;
      settings->w_current = w_end;
  }

  CHANGE_TOOL(settings->selected_pocket);

  settings->current_pocket = settings->selected_pocket;
  // tool change can move the controlled point.  reread it:
  settings->toolchange_flag = true; 
  set_tool_parameters();
  return INTERP_OK;
}
Не силен я в программировании, но чуйка мне подсказывает, что
CHANGE_TOOL(settings->selected_pocket) производит саму смену, а
set_tool_parameters(); как раз и устанавливает углы и ориентацию.

Так где же сама проверка на то, что бы не запускать смену если инструмент текущий совпадает с запрашиваемым?
:bender:
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Lexxa »

Ошибка (для нас она ошибка) заключается в том, что функция, которая обновляет инструмент использует нулевую строку из таблицы инструментов. По всем правилам этой строкой является инструмент в шпинделе.
Нужно чтобы эта функция в качестве параметра использовала не нулевую строку таблицы инструмента, а запрошенную ячейку.
Функция с ошибкой (для просмотра содержимого нажмите на ссылку)

Код: Выделить всё

int Interp::set_tool_parameters()
{
  // invoke to set tool parameters for current tool (pocket==0)
  // when a tool is absent, set default (zero offset) tool parameters

  if ((! _setup.random_toolchanger) && (_setup.tool_table[0].toolno <= 0)) {
    default_tool_parameters();
    return 0;
  }
  _setup.parameters[5400] = _setup.tool_table[0].toolno;
  _setup.parameters[5401] = _setup.tool_table[0].offset.tran.x;
  _setup.parameters[5402] = _setup.tool_table[0].offset.tran.y;
  _setup.parameters[5403] = _setup.tool_table[0].offset.tran.z;
  _setup.parameters[5404] = _setup.tool_table[0].offset.a;
  _setup.parameters[5405] = _setup.tool_table[0].offset.b;
  _setup.parameters[5406] = _setup.tool_table[0].offset.c;
  _setup.parameters[5407] = _setup.tool_table[0].offset.u;
  _setup.parameters[5408] = _setup.tool_table[0].offset.v;
  _setup.parameters[5409] = _setup.tool_table[0].offset.w;
  _setup.parameters[5410] = _setup.tool_table[0].diameter;
  _setup.parameters[5411] = _setup.tool_table[0].frontangle;
  _setup.parameters[5412] = _setup.tool_table[0].backangle;
  _setup.parameters[5413] = _setup.tool_table[0].orientation;

  return 0;
}
Кусок окда,который позволяет ремапить Т (для просмотра содержимого нажмите на ссылку)

Код: Выделить всё

# REMAP=T   prolog=prepare_prolog ngc=prepare epilog=prepare_epilog
# exposed parameters: #<tool> #<pocket>

def prepare_prolog(self,**words):
    try:
        cblock = self.blocks[self.remap_level]
        if not cblock.t_flag:
            self.set_errormsg("T requires a tool number")
            return INTERP_ERROR
        tool  = cblock.t_number
        if tool:
            (status, pocket) = self.find_tool_pocket(tool)
            if status != INTERP_OK:
                self.set_errormsg("T%d: pocket not found" % (tool))
                return status
        else:
            pocket = -1 # this is a T0 - tool unload
        self.params["tool"] = tool
        self.params["pocket"] = pocket
        return INTERP_OK
    except Exception, e:
        self.set_errormsg("T%d/prepare_prolog: %s" % (int(words['t']), e))
        return INTERP_ERROR

def prepare_epilog(self, **words):
    try:
        if not self.value_returned:
            r = self.blocks[self.remap_level].executing_remap
            self.set_errormsg("the %s remap procedure %s did not return a value"
                             % (r.name,r.remap_ngc if r.remap_ngc else r.remap_py))
            return INTERP_ERROR
        if self.blocks[self.remap_level].builtin_used:
            #print "---------- T builtin recursion, nothing to do"
            return INTERP_OK
        else:
            if self.return_value > 0:
                self.selected_tool = int(self.params["tool"])
                self.selected_pocket = int(self.params["pocket"])
                emccanon.SELECT_POCKET(self.selected_pocket, self.selected_tool)
                return INTERP_OK
            else:
                self.set_errormsg("T%d: aborted (return code %.1f)" % (int(self.params["tool"]),self.return_value))
                return INTERP_ERROR
    except Exception, e:
        self.set_errormsg("T%d/prepare_epilog: %s" % (tool,e))
        return INTERP_ERROR
Ихмо, выдернуть от тууда pocket для нашего случая тоже не правильно.

Разжуйте мне,
тут (для просмотра содержимого нажмите на ссылку)

Код: Выделить всё

from stdglue import *

# Extract the T number into a parameter, but don't try anything else clever

def get_T_number(self,**words):
    try:
        cblock = self.blocks[self.remap_level]
        if not cblock.t_flag:
            self.set_errormsg("T requires a tool number")
            return INTERP_ERROR
        self.params["tool"] = cblock.t_number
        return INTERP_OK
    except Exception, e:
        self.set_errormsg("T%d/prepare_prolog: %s" % (int(words['t']), e))
        return INTERP_ERROR
они извлекают номер инструмента? Откуда они его извлекают?
Вот пришла команда Т0104
params.["tool"] станет T0104, а потом в remap.ngc этому параметру присваивают 01? Так это работает?
Т.е. грубо говоря можно было бы сделать прямо в этом коде
self.params["tool"] = (cblock.t_number / 100)
self.params["pocket"] = (cblock.t_number / 100)
self.params["wear"] = (cblock.t_number % 100)
только вот последнего параметра в параметрах наверное нет?

дописать сюда же функцию setup.parameters(n)
_setup.parameters[5400] = _setup.tool_table[0].toolno;
_setup.parameters[5401] = _setup.tool_table[0].offset.tran.x;
_setup.parameters[5402] = _setup.tool_table[0].offset.tran.y;
_setup.parameters[5403] = _setup.tool_table[0].offset.tran.z;
_setup.parameters[5404] = _setup.tool_table[0].offset.a;
_setup.parameters[5405] = _setup.tool_table[0].offset.b;
_setup.parameters[5406] = _setup.tool_table[0].offset.c;
_setup.parameters[5407] = _setup.tool_table[0].offset.u;
_setup.parameters[5408] = _setup.tool_table[0].offset.v;
_setup.parameters[5409] = _setup.tool_table[0].offset.w;
_setup.parameters[5410] = _setup.tool_table[0].diameter;
_setup.parameters[5411] = _setup.tool_table[0].frontangle;
_setup.parameters[5412] = _setup.tool_table[0].backangle;
_setup.parameters[5413] = _setup.tool_table[0].orientation;

Так?
:bender:
nkp
Мастер
Сообщения: 8340
Зарегистрирован: 28 ноя 2011, 00:25
Репутация: 1589
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение nkp »

может какие то другие пути есть для достижения поставленой цели...
кстати , можно чуть более системно изложить ее суть?
то есть - имеем станок с емс ,а программы (Gкоды) под него будут всегда фануковские ??
какое преимущество использовать инструмент А с параметрами В ?? (ну кроме компенсации длины)
=======
может переопределить что нибудь из этого под свои нужды ?
++++++++++++++++++
self.params["tool"] = (cblock.t_number / 100)
self.params["pocket"] = (cblock.t_number / 100)

так тоже наверно можно - только это никакого не дает выиграша...
Аватара пользователя
Lexxa
Мастер
Сообщения: 2703
Зарегистрирован: 16 дек 2011, 16:48
Репутация: 319
Настоящее имя: Алексей
Откуда: ryazan
Контактная информация:

Re: Команда смены инструмента как в фануке.

Сообщение Lexxa »

я сейчас с трудом могу системно суть изложить - джетлаг, будь оннеладен в +8 часов, как в тумане хожу.
Удобно это тем, что это
а) наглядно для оператора
б) удобно в программировании - никогда не забудешь включить корректор
в) ну и как бы стандарт такой
:bender:
Ответить

Вернуться в «LinuxCNC»