X-Git-Url: https://rtime.felk.cvut.cz/gitweb/mirosot.git/blobdiff_plain/54df33c3edbfbf4b4faf94e81b5d2109b63aa40c..dde832db41b7598ef6dd7821c6ddf8843eb1b74e:/testapp/cmd_pxmc.c diff --git a/testapp/cmd_pxmc.c b/testapp/cmd_pxmc.c new file mode 100644 index 0000000..9e0200c --- /dev/null +++ b/testapp/cmd_pxmc.c @@ -0,0 +1,610 @@ +/******************************************************************* + Components for embedded applications builded for + laboratory and medical instruments firmware + + cmd_stm.c - interconnection of Stepper Motor control + subsystem with RS-232 command processor + used mainly for controller tuning + + Copyright (C) 2001 by Pavel Pisa pisa@cmp.felk.cvut.cz + (C) 2002 by PiKRON Ltd. http://www.pikron.com + + *******************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include "cmd_pxmc.h" + + +/** + * cmd_opchar_getreg - selects the right axis + * + * pxmc is designed for multi axis motion control, so each axis must be identificated. + * This done by a capital letter. The first axis must be A, the 2nd B, etc. + */ +pxmc_state_t *cmd_opchar_getreg(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + unsigned chan; + pxmc_state_t *mcs; + chan=*param[1]-'A'; + if(chan>=pxmc_main_list.pxml_cnt) return NULL; + mcs=pxmc_main_list.pxml_arr[chan]; + if(!mcs) return NULL; + return mcs; +} + +/** + * cmd_do_reg_go - checks the command format validity and calls pxmc_go. + * + * if pxmc_go returns -1, cmd_do_reg_go returns -1. + */ +int cmd_do_reg_go(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + long val; + pxmc_state_t *mcs; + if(*param[2]!=':') return -CMDERR_OPCHAR; + if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG; + val=atol(param[3])<pxms_ptofs=0; + return 0; +} + +/** + * cmd_do_reg_rw_pos - read or write function, param is converted in 'long' and shifted + * + * if the command typed is a write function, records the value, + * if it is a read function returns the value asked. + */ + +int cmd_do_reg_rw_pos(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + long val; + long *ptr; + int opchar; + pxmc_state_t *mcs; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG; + ptr=(long*)((long)des->info[0]+(char*)mcs); + if(opchar==':'){ + val=atol(param[3]); + *ptr=val<>PXMC_SUBDIV(mcs), 0, 0); + } + return 0; +} + +/** + * cmd_do_reg_short_val - read or write function, param is converted in 'integer' + * + * if the command typed is a write function, records the value, + * if it is a read function returns the value asked. + */ + +int cmd_do_reg_short_val(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + int val; + short *ptr; + int opchar; + pxmc_state_t *mcs; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG; + ptr=(short*)((long)des->info[0]+(char*)mcs); + if(opchar==':'){ + val=atoi(param[3]); + *ptr=val; + }else{ + return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0); + } + return 0; +} + +/** + * cmd_do_reg_long_val - read or write function, param is converted in 'long' + * + * if the command typed is a write function, records the value, + * if it is a read function returns the value asked. + */ +int cmd_do_reg_long_val(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + long val; + long *ptr; + int opchar; + pxmc_state_t *mcs; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG; + ptr=(long*)((long)des->info[0]+(char*)mcs); + if(opchar==':'){ + val=atol(param[3]); + *ptr=val; + }else{ + return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0); + } + return 0; +} + + +/** + * cmd_do_axis_mode - checks the command format and busy flag validity, calls pxmc_axis_mode + * + * if pxmc_axis_mode returns -1, cmd_do_axis_mode returns -1. + */ +int cmd_do_axis_mode(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + int val; + pxmc_state_t *mcs; + if(*param[2]!=':') return -CMDERR_OPCHAR; +// if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG; + if(mcs->pxms_flg&PXMS_BSY_m) return -CMDERR_BSYREG; + val=atol(param[3]); + val=pxmc_axis_mode(mcs,val); + if(val<0) + return val; + return 0; +} + + +int cmd_do_regptmod_short_val(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + int val; + short *ptr; + int opchar; + pxmc_state_t *mcs; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG; + ptr=(short*)((long)des->info[0]+(char*)mcs); + if(opchar==':'){ + if(mcs->pxms_flg&PXMS_BSY_m) return -CMDERR_BSYREG; + pxmc_set_const_out(mcs,0); + val=atoi(param[3]); + if((val<((long)des->info[1])) || (val>((long)des->info[2]))) + return -CMDERR_BADPAR; + *ptr=val; + val=pxmc_axis_mode(mcs,0); + if(val<0) + return val; + }else{ + return cmd_opchar_replong(cmd_io, param, (long)*ptr, 0, 0); + } + return 0; +} + + +/** + * cmd_do_reg_type - no code written, will set controller structure + */ +int cmd_do_reg_type(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + /* should set controller structure */ + return 0; +} + + +/** + * cmd_do_regsfrq - sets or returns smapling frequency + */ +#ifdef WITH_SFI_SEL +int cmd_do_regsfrq(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + int val; + int opchar; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + if(opchar==':'){ + val=atoi(param[3]); + return pxmc_sfi_sel(val); + }else{ + return cmd_opchar_replong(cmd_io, param, pxmc_get_sfi_hz(NULL), 0, 0); + } + return 0; +} +#endif /* WITH_SFI_SEL */ + + +/* debugging functions */ +int cmd_do_reg_dbgset(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + pxmc_state_t *mcs; + int val; + int opchar; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + if((mcs=cmd_opchar_getreg(cmd_io,des,param))==NULL) return -CMDERR_BADREG; + if(opchar==':'){ + val=atoi(param[3]); + pxmc_dbgset(mcs,pxmc_dbg_ene_as,val); + }else{ + cmd_io_write(cmd_io,param[0],param[2]-param[0]); + cmd_io_putc(cmd_io,'='); + cmd_io_putc(cmd_io,mcs->pxms_flg&PXMS_DBG_m?'1':'0'); + } + return 0; +} + + +int cmd_do_reg_dbgpre(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + pxmc_dbg_hist_t *hist; + long count, val; + int i; + int opchar; + char *ps; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + ps=param[3]; + if(si_long(&ps,&count,0)<0) return -CMDERR_BADPAR; + if(!count||(count>0x10000)) return -CMDERR_BADPAR; + pxmc_dbg_histfree(NULL); + if((hist=pxmc_dbg_histalloc(count+2))==NULL) return -CMDERR_NOMEM; + for(i=0;ibuff[i]=val; + } + pxmc_dbg_hist=hist; + return 0; +} + + +int cmd_do_reg_dbghis(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + pxmc_dbg_hist_t *hist; + long count, val; + int i, opchar; + char *ps; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + ps=param[3]; + if(si_long(&ps,&count,0)<0) return -CMDERR_BADPAR; + if(!count||(count>0x10000)) return -CMDERR_BADPAR; + hist=pxmc_dbg_hist; + for(i=0;ibuff[i]end)) + val=hist->buff[i]; + else + val=0; + /* printf("%ld\r\n",val); */ /* !!!!!!!! */ + } + return 0; +} + + +int cmd_do_reg_dbggnr(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]) +{ + pxmc_state_t *mcs; + int i; + int opchar; + + if((opchar=cmd_opchar_check(cmd_io,des,param))<0) return opchar; + for(i=0;ipxms_flg&PXMS_DBG_m)){ + if(pxmc_dbg_gnr(mcs)<0){ + for(i=0;ipxms_flg&PXMS_DBG_m)) + pxmc_stop(pxmc_main_list.pxml_arr[i],0); + } + return -CMDERR_BADREG; + } + } + } + pxmc_dbg_hist->ptr=pxmc_dbg_hist->buff; + return 0; +} + + +/* motor executable commands */ +cmd_des_t const cmd_des_go={0, CDESM_OPCHR|CDESM_RW, + "G?","go to target position",cmd_do_reg_go,{}}; +cmd_des_t const cmd_des_pwm={0, CDESM_OPCHR|CDESM_RW, + "PWM?","direct axis PWM output",cmd_do_pwm,{}}; +cmd_des_t const cmd_des_hh={0, CDESM_OPCHR,"HH?","hard home request for axis",cmd_do_reg_hh,{}}; +cmd_des_t const cmd_des_spd={0, CDESM_OPCHR,"SPD?","speed request for axis",cmd_do_reg_spd,{}}; +cmd_des_t const cmd_des_spdfg={0, CDESM_OPCHR,"SPDFG?", + "fine grained speed request for axis",cmd_do_reg_spdfg,{}}; +cmd_des_t const cmd_des_stop={0, CDESM_OPCHR, + "STOP?","stop motion of requested axis",cmd_do_stop,{}}; +cmd_des_t const cmd_des_release={0, CDESM_OPCHR, + "RELEASE?","releases axis closed loop control",cmd_do_release,{}}; +cmd_des_t const cmd_des_zero={0, CDESM_OPCHR, + "ZERO?","zero actual position",cmd_do_zero,{}}; +cmd_des_t const cmd_des_align={0, CDESM_OPCHR, + "ALIGN?","align commutator",cmd_do_align,{}}; +cmd_des_t const cmd_des_clrerr={0, CDESM_OPCHR, + "PURGE?"," clear 'axis in error state' flag",cmd_do_clrerr,{}}; +/* motors and controllers variables */ +cmd_des_t const cmd_des_ap={0, CDESM_OPCHR|CDESM_RD, + "AP?","actual position",cmd_do_reg_rw_pos, + {(char*)pxmc_state_offs(pxms_ap), + 0}}; +cmd_des_t const cmd_des_st={0, CDESM_OPCHR|CDESM_RD, + "ST?","axis status bits encoded in number",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_flg), + 0}}; +cmd_des_t const cmd_des_axerr={0, CDESM_OPCHR|CDESM_RD, + "AXERR?","last axis error code",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_errno), + 0}}; +#if 0 +cmd_des_t const cmd_des_r_one={0, CDESM_OPCHR, + "R?","send R?! or FAIL?! at axis finish",cmd_do_r_one,{}}; +#endif +cmd_des_t const cmd_des_regp={0, CDESM_OPCHR|CDESM_RW, + "REGP?","controller proportional gain",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_p), + 0}}; +cmd_des_t const cmd_des_regi={0, CDESM_OPCHR|CDESM_RW, + "REGI?","controller integral gain",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_i), + 0}}; +cmd_des_t const cmd_des_regd={0, CDESM_OPCHR|CDESM_RW, + "REGD?","controller derivative gain",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_d), + 0}}; +cmd_des_t const cmd_des_regs1={0, CDESM_OPCHR|CDESM_RW, + "REGS1?","controller S1",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_s1), + 0}}; +cmd_des_t const cmd_des_regs2={0, CDESM_OPCHR|CDESM_RW, + "REGS2?","controller S2",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_s2), + 0}}; +cmd_des_t const cmd_des_regmd={0, CDESM_OPCHR|CDESM_RW, + "REGMD?","maximal allowed position error",cmd_do_reg_rw_pos, + {(char*)pxmc_state_offs(pxms_md), + 0}}; +cmd_des_t const cmd_des_regms={0, CDESM_OPCHR|CDESM_RW, + "REGMS?","maximal speed",cmd_do_reg_long_val, + {(char*)pxmc_state_offs(pxms_ms), + 0}}; +cmd_des_t const cmd_des_regacc={0, CDESM_OPCHR|CDESM_RW, + "REGACC?","maximal acceleration",cmd_do_reg_long_val, + {(char*)pxmc_state_offs(pxms_ma), + 0}}; +cmd_des_t const cmd_des_regme={0, CDESM_OPCHR|CDESM_RW, + "REGME?","maximal PWM energy or voltage for axis",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_me), + 0}}; +cmd_des_t const cmd_des_regcfg={0, CDESM_OPCHR|CDESM_RW, + "REGCFG?","hard home and profile configuration",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_cfg), + 0}}; +cmd_des_t const cmd_des_ptirc={0, CDESM_OPCHR|CDESM_RW, + "REGPTIRC?","number of irc pulses per phase table",cmd_do_regptmod_short_val, + {(char*)pxmc_state_offs(pxms_ptirc), + (char*)4,(char*)10000}}; +cmd_des_t const cmd_des_ptper={0, CDESM_OPCHR|CDESM_RW, + "REGPTPER?","number of elmag. revolutions per phase table",cmd_do_regptmod_short_val, + {(char*)pxmc_state_offs(pxms_ptper), + (char*)1,(char*)100}}; +cmd_des_t const cmd_des_ptshift={0, CDESM_OPCHR|CDESM_RW, + "REGPTSHIFT?","shift (in irc) of generated phase curves",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_ptshift), + 0}}; +cmd_des_t const cmd_des_ptvang={0, CDESM_OPCHR|CDESM_RW, + "REGPTVANG?","angle (in irc) between rotor and stator mag. fld.",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_ptvang), + 0}}; +cmd_des_t const cmd_des_pwm1cor={0, CDESM_OPCHR|CDESM_RW, + "REGPWM1COR?","PWM1 correction",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_pwm1cor), + 0}}; +cmd_des_t const cmd_des_pwm2cor={0, CDESM_OPCHR|CDESM_RW, + "REGPWM2COR?","PWM2 correction",cmd_do_reg_short_val, + {(char*)pxmc_state_offs(pxms_pwm2cor), + 0}}; +cmd_des_t const cmd_des_axis_mode={0, CDESM_OPCHR|CDESM_WR, + "REGMODE?","axis working mode",cmd_do_axis_mode, + {}}; +#ifdef WITH_SFI_SEL +cmd_des_t const cmd_des_regsfrq={0, CDESM_OPCHR|CDESM_RW, + "REGSFRQ","set new sampling frequency",cmd_do_regsfrq,{}}; +#endif /* WITH_SFI_SEL */ +/* axes debugging and tuning */ +cmd_des_t const cmd_des_reg_type={0, CDESM_OPCHR|CDESM_RW, + "REGTYPE?","unused",cmd_do_reg_type,{}}; +cmd_des_t const cmd_des_reg_dbgset={0, CDESM_OPCHR|CDESM_RW, + "REGDBG?","sets debug flag",cmd_do_reg_dbgset,{}}; +cmd_des_t const cmd_des_reg_dbgpre={0, CDESM_OPCHR|CDESM_WR, + "REGDBGPRE","store reference course",cmd_do_reg_dbgpre,{}}; +cmd_des_t const cmd_des_reg_dbghis={0, CDESM_OPCHR|CDESM_WR, + "REGDBGHIS","read history course",cmd_do_reg_dbghis,{}}; +cmd_des_t const cmd_des_reg_dbggnr={0, CDESM_OPCHR|CDESM_WR, + "REGDBGGNR","controller response to HIST course",cmd_do_reg_dbggnr,{}}; + +cmd_des_t const *cmd_stm_default[]={ + &cmd_des_go, + &cmd_des_pwm, + /*&cmd_des_hh,*/ + &cmd_des_spd, + &cmd_des_spdfg, + &cmd_des_stop, + &cmd_des_release, + &cmd_des_zero, + &cmd_des_align, + &cmd_des_clrerr, + &cmd_des_ap, + &cmd_des_st, + &cmd_des_axerr, + /*&cmd_des_r_one,*/ + &cmd_des_regp, + &cmd_des_regi, + &cmd_des_regd, + &cmd_des_regs1, + &cmd_des_regs2, + &cmd_des_regmd, + &cmd_des_regms, + &cmd_des_regacc, + &cmd_des_regme, + &cmd_des_regcfg, + &cmd_des_ptirc, + &cmd_des_ptper, + &cmd_des_ptshift, + &cmd_des_ptvang, + &cmd_des_pwm1cor, + &cmd_des_pwm2cor, + &cmd_des_axis_mode, + &cmd_des_reg_type, +#ifdef WITH_SFI_SEL + &cmd_des_regsfrq, +#endif /* WITH_SFI_SEL */ + &cmd_des_reg_dbgset, + &cmd_des_reg_dbgpre, + &cmd_des_reg_dbghis, + &cmd_des_reg_dbggnr, + NULL +};